本视频适合有Vue2.x基础同学观看
终于 Vue3 的正式版发布了,两年多的开发,99 位贡献者的努力 ,2600 次提交 628 次 PR。凝聚了这么多优秀开发者的智慧和努力,注定 Vue3 会成为下一个前端主流开发框架。这篇文章说是教程,但更多的是我的学习过程。因为 Vue3 刚出没几天,谁也不敢说自己就是这个领域的大神(除了尤雨溪以外)。
前端就是这样,要时刻保持学习,每个月都有新技术的产生。如果每个知识都学,显然不现实,所以也要有选择性的学习。但无论如何 Vue3 都是目前最值得一学的前端框架。
有的小伙伴这时候会说,我们公司还没开始使用,可以先不学。确实是这样,我们公司也没有使用,但无论什么技术的产生都会有个过程,这个过程中有一个阶段是可以充分享受技术红利的。你现在学,无论技术红利什么时候到来,你都可以从容的抓住技术红利期,获得最大的收益。
所以建议你还是每天花点时间,跟着技术胖一期学习。每天也就十几分钟,不会给你太大的压力。
如果你缺少学习的伙伴,可以扫码加入 QQ 群和上千小伙伴一起学习。QQ 群号:273225311
在 2020 年 9 月 19 日 Vue3 更新了 正式版本,正式版本一出,代表着不会再有太大的改动了,也意味着你可以开始学习了。我个人觉的大家跟着我的步伐学习就可以了,不用太着急。因为这个技术的应用和大面积普及,至少还会有 4-5 个月时间。你跟着技术胖一点点学,是完全够用的。我们也尽量保持一周 4-5 集的更新。
现在就给大家交个实地:此套课程会是个系列课程,从基础到实战都会有所涉及,用心学习可完全达到工作水平,而且完全免费(没套路更轻松)。
当然我也真诚希望你能在留言区或者 QQ 群指出我文章的错误(Vue3 刚出,我也个初学者),也感谢大家的包容,让我们一起完成这个 Vue3 的教程。如果你提出了宝贵的意见,并且我采纳了,你的名字就会出现在下方的贡献者名单中。(谢谢大家的支持)
技术胖 ,
虽然几乎是零基础的教学,但是还是对你有一些奢望的,如果会学习这门课程会简单很多。
希望你会 TypeScript,本套课程会全程使用 TS
的语法来编写程序。如果不会,技术胖有完全免费的视频课程,地址:TypeScript 从入门到精通图文视频教程-2020 年新版
希望你做过或者有 Vue2 的基础就更好了。如果不会,技术胖有完全免免费的视频课程:Vue2.x 学习路线
希望你会基本的 npm
或者 yarn
的包管理应用。对不起,这个专门的课程我还没出,但课程中我会详细讲解。
你说我就是都不会,能不能学这个课程。也能,但是你可能要多动手和多听两边视频,我尽量会站在一个初学者的角度来讲这些内容。
必须要夸一夸 Vue3,它真实可谓“千呼万唤使出来”,听说是尤大神每天抱着孩子完成的。故事已经不能说明 Vue3 的伟大了,我们用下面一组数字来了解一下 Vue3.
Vue3:两年开发,99 位程序员成为贡献者,2600 次提交,628 次 PR
这些数字可以看出 Vue3 的工作量之大,我在一年前就开始关注 Vue3 的开发进展,虽然没能力成为 Vue3 的贡献者之一,但是我热爱的心不可否认。
官方网站地址: v3.vuejs.org
那我们这节课先来了解一下 Vue3 让人惊艳的一些新特性啊。
首先是向下兼容,Vue3 支持大多数 Vue2 的特性。我们同事甚至开玩笑说,我就拿 Vue2 的语法开发 Vue3,也是没有任何问题的。
性能的提升,每个人都希望使用的框架更快,更轻。Vue3 做到了,给开发者一个极致的体验。官方网站给出的数据是:打包大小减少 41%,初次渲染快 55%,更新快 133%,内存使用减少 54%(惊艳到的请把惊艳
两个字打到公屏上)。
新推出的Composition API
,在 Vue2 中遇到的问题就是复杂组件的代码变的非常麻烦,甚至不可维护。说白了就是封装不好,重用不畅。这个Composition API
一推出,立马解决了这个问题,本套课程中也会重点介绍这部分内容。它是一系列 API 的合集。
其他新特性:Teleport(瞬移组件)、Suspense(解决异步加载组件问题)和全局 API 的修改和优化。
更好TypeScript
支持,我以前在开发 Vue2 的时候,是不适用TypeScript
的,因为集成时很困难,疼点太多。但 Vue3 解决了这个问题,Vue3 的源代码就是使用TypeScript
进行开发的。所以在新的版本上使用TS
也更加顺畅无阻。
这些就是 Vue3 的大部分新特性了,如果你更感兴趣,可以到 B 站去看一下尤大的发布会视频。
B 站 Vue3 发布会视频:https://www.bilibili.com/video/BV1iA411J7cA?from=search&seid=2979047174353974296
好了,这节课先到这里,下届我们用vue-cli
配置 Vue3 的开发环境。
我相信小伙伴已经摩拳擦掌,迫不及待的去创建一个 Vue3 的项目了。你可能会认为创建 Vue3 的项目非常麻烦,如果你自己动手作确实非常麻烦。官方非常贴心的准备了项目创建工具vue-cli
。
Vue-cli :Vue.js 开发的标准工具 , 新版的 vue-cli 还提供了图形界面,如果你对命令行陌生,也可以使用图形界面。
简单理解Vue-cli
的作用就是能够让你省去复杂的项目配置过程,快速生成标准化的 Vue 开发环境。
安装:
npm install -g @vue/cli
# OR
yarn global add @vue/cli
建议使用npm
进行安装,而且要做全局安装。因为我在使用yarn
进行安装后,也可以安装成功,但是安装完成不能使用vue
命令。
安装时间两分钟左右,安装完成会有success
的提示。
如果你以前安装过,需要检查一下版本,升级到最新版本,因为只有最新版本(V4.5.4 以上版本)才有创建 Vue3 的选项。
//检查版本命令为:
vue --version
这时候可以展示出类似这样的版本信息@vue/cli 4.5.6
。如果你的版本低于这个,可以再使用npm install -g @vue/cli
来进行安装。
通过 9 步对话式的询问,你就可以轻松的创建一个 Vue3 项目。
这里我先用命令行的方式创建一个Vue3
项目,直接在命令行中输入vue create vue3-1
,输入完成后,他会有这样一句询问。
Your connection to the default yarn registry seems to be slow.
Use https://registry.npm.taobao.org for faster installation? (Y/n)
意思是你不能科学上网,建议你使用淘宝源,这时候你需要选择Y
,也就是使用淘宝源进行创建。如果你已经配置淘宝源不会显示这个选项。
当你选择Y
之后,就会跳出三个菜单让你选择。
? Please pick a preset: (Use arrow keys) //请选择预选项
> Default ([Vue 2] babel, eslint) //使用Vue2默认模板进行创建
Default (Vue 3 Preview) ([Vue 3] babel, eslint) //使用Vue3默认模板进行创建
Manually select features //手动选择(自定义)的意思
因为你要使用TypeScript
进行开发 Vue3 的代码,所以不能直接使用第二项默认模板,这时候我们选择第三项手动选择。选择的时候按回车就可以实现。(如果这时候你没有上面的三个选项,说明的 vue-cli 是旧版本,需要你更新。)
这时候就会出现很多可插拔的选项让你自定义选择:
? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection)
>(*) Choose Vue version
(*) Babel
( ) TypeScript
( ) Progressive Web App (PWA) Support
( ) Router
( ) Vuex
( ) CSS Pre-processors //CSS预处理器
(*) Linter / Formatter //格式化工具
( ) Unit Testing //单元测试
( ) E2E Testing //E2E测试
这里我们需要再多选一个TypeScript
的选项,然后再按回车进入下一层选择。
? Choose a version of Vue.js that you want to start the project with (Use arrow keys)
> 2.x
3.x (Preview)
这里要选择 3.x 的版本,点击回车,然后会提示你是否需要使用class-style
,教学中旧不使用这个类样式语法了,所以我们选择n
。
Use class-style component syntax?
然后会出现下面的选项 ,意思是否使用TypeScript
和Babel
的形式编译 JSX.这里我们也选择n
Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? (Y/n)
然后会出现ESLint
的一些配置,这里我们选择第一项,默认就好,因为下面这些规则并不是这个课程的重点。
? Pick a linter / formatter config: (Use arrow keys)
> ESLint with error prevention only
ESLint + Airbnb config
ESLint + Standard config
ESLint + Prettier
TSLint (deprecated)
回车后会让你选择增加lint
的特性功能。
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)
>(*) Lint on save //保存的时候进行Lint
( ) Lint and fix on commit //需要帮你进行fix(修理),这项我们不进行选择
回车后让你选择这些配置文件时单独存放,还是直接存放在package.json
文件里。这里选择放在单独的文件里。
Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
最后一个问题,是问你需不需要把这些配置保存下来,下次好直接进行使用。我这里选择不用(n)。淡然你可以自行选择
Save this as a preset for future projects? (y/N)
如果你同时安装了npm
和yarn
来个包管理软件,它还会作最后一次询问,让你选择使用什么进行下载。
? Pick the package manager to use when installing dependencies:
> Use Yarn
Use NPM
我选择了yarn
进行安装,也可能是心里问题,我老觉的 yarn 更快一些,我这里只用了 10 几秒就完成了下载和构建。
出现下面的信息,说明我们已经安装完成了。
Done in 10.33s.
$ cd vue3-1
$ yarn serve
根据提示在命令行输入cd vue3-1
进入项目,然后再输入yarn serve
开启项目预览。这时候就会给出两个地址,都可以访问到现在的项目.
App running at:
- Local: http://localhost:8080/
- Network: http://192.168.0.118:8080/
Note that the development build is not optimized.
To create a production build, run yarn build.
把地址放到浏览器的地址栏,如果看到下面的页面,说明安装正常了。
上节你已经能用命令行或者说终端配合Vue-cli
构建 Vue3 的项目了,这节看一下Vue-cli
如何用图形界面构建项目。因为是图形界面,所以代码很少,多是界面。本节课程强烈推荐看视频学习。
当你安装了最新版的Vue-cli
就可以使用 vue ui
这个命令,开启一个 UI 界面,然后会出现下面的提示。
Starting GUI.
Ready on http://localhost:80
出现提示后,把http://localhost:80
地址拷贝到浏览器地址栏中,就会出现下面的界面。
这时候点击创建
按钮,然后选择页面下方的在此处创建新项目
。这时候会让你输入项目名称和包管理器。我再这里输入了vue3-2
,并使用了yarn
作为管理器。
可以点击下一步了,之后会让你选择预设模板,这里选择手动。
之后就和命令行基本一样了,根据自己的项目来进行配置。(视频中会作详细的演示)
这不完成后,可以选择“创建项目”,然后弹出提示,问是不是保存这个配置,这里依然是不保存。
这时候如果你注意VSCode
中的终端,会发现它开始为我们构建项目。大概一分钟左右,会跳出下面的页面,说明项目已经构建完成。
这时候再回到 VSCode 的终端中,进入项目cd vue3-2
,然后启动服务npm serve
,等到服务启动后在浏览器地址栏输入http://localhost:8080/
,就可以看到下面的界面了。
看到这个界面,正面你的 Vue3+TypeScript 项目已经创建好了。下节课学习一下里边的基本结构。
这节主要讲一下用Vue-cli
构建好项目后,最初始的文件结构是怎么样的?我们需要由一个最基本的了解,只有了解后才能进行开发。
以一个目录树状结构进行展示。后边的作用我也写到了下面
|-node_modules -- 所有的项目依赖包都放在这个目录下
|-public -- 公共文件夹
---|favicon.ico -- 网站的显示图标
---|index.html -- 入口的html文件
|-src -- 源文件目录,编写的代码基本都在这个目录下
---|assets -- 放置静态文件的目录,比如logo.pn就放在这里
---|components -- Vue的组件文件,自定义的组件都会放到这
---|App.vue -- 根组件,这个在Vue2中也有
---|main.ts -- 入口文件,因为采用了TypeScript所以是ts结尾
---|shims-vue.d.ts -- 类文件(也叫定义文件),因为.vue结尾的文件在ts中不认可,所以要有定义文件
|-.browserslistrc -- 在不同前端工具之间公用目标浏览器和node版本的配置文件,作用是设置兼容性
|-.eslintrc.js -- Eslint的配置文件,不用作过多介绍
|-.gitignore -- 用来配置那些文件不归git管理
|-package.json -- 命令配置和包管理文件
|-README.md -- 项目的说明文件,使用markdown语法进行编写
|-tsconfig.json -- 关于TypoScript的配置文件
|-yarn.lock -- 使用yarn后自动生成的文件,由Yarn管理,安装yarn包时的重要信息存储到yarn.lock文件中
这就是基本目录结构和用处了,你可以在表中自查。
上两节课你可以使用npm run serve
或yarn serve
查看项目效果,就是因为有package.json
中的scripts
起到了作用。先来看一下这三条命令。
{
//----
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
//----
}
能使用vue-cli-service
是因为vue-cli
自动安装了cli-service
这个工具,此处可以在devDependencies
中看出哦。
这三个命令的意思是:
我们顺便讲一下package.json
中另外两个比较重要的配置项dependencies
和devDependencies
。这两个都是用来记录安装包信息的,但如果要想完全搞清楚他们的区别,你先要弄清楚什么是开发环境和生产环境。
开发环境: 作为一个程序员,每天作的事情都是在开发环境中,编写代码、测试代码、修改 Bug。也就说这些代码没有上线。
生产环境:就是代码已经上线,放到了正式的服务器上,公司开始运营去赚钱的代码。
明白了这两个概念后,dependencies
下的包是生产环境中必须用到的,当然开发环境也需要。devDependencies
是只有开发环境中使用的,上线后这些包就没用了,打包后也不会打包进去的代码。
项目里边还有一个非常重要的文件main.ts
文件,你可以把它叫做入口文件
,这里边只有简单的三行代码。
import { createApp } from "vue"; // 引入vue文件,并导出`createApp`
import App from "./App.vue"; // 引入自定义组件,你在页面上看的东西基本都在这个组件里
createApp(App).mount("#app"); // 把App挂载到#app节点上,在public目录下的index.html找节点
顺着这个线索你可以找到App.vue
这个组件,打开这个组件,看到里边的内容还是很多的,甚至你可能还有些东西看不明白。
<template>
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import HelloWorld from './components/HelloWorld.vue';
export default defineComponent({
name: 'App',
components: {
HelloWorld
}
});
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
在这个根组件里模板、vue 的 js 业务逻辑代码和 css 代码。在业务逻辑代码中,你可以看到引入了一个HelloWorld.vue
的自定义组件。
这个自定义组件里边就是放了一些链接和模板用的 html 代码了,可以试着删除一些 html 代码,然后查看效果。
这节课你要通过一个简单的大宝剑点餐流程,初步了解一下 Vue3 中 Ref 的魅力。这个点餐很简单,所以你学习的时候不要有任何的压力。 如果你真的听起来非常难,请一定在听过之后动手敲一下这段代码,你会有更深的领悟。
### 清理无用的代码在用vue-cli
生产的 Vue3 项目中,有一些默认的代码,为了方便学习,这些代码需要清理掉无用的代码。
打开根组件App.vue
文件,去掉HelloWorld
自定义组件相关代码。
<template>
<img alt="Vue logo" src="./assets/logo.png" />
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "App",
components: {},
});
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
这时候再进行浏览就没有其他的元素了,只剩下一个Vue
的图标。就可以继续开发啦。这时候你可以在终端中运行yarn serve
,在浏览器中预览一下效果。
在App.vue
里添加如下代码,我先修改了template
,增加了两行代码和一个按钮。
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<div>
<h2>欢迎光临红浪漫洗浴中心</h2>
<div>请选择一位美女为你服务</div>
</div>
<div>
<button> </button>
</div>
</template>
然后我开始改写<script>
部分,使用setup()
新语法,写了这个就不需要再写data
这样的东西了。然后在setup
中加入一个girls
变量,为了能让模板中进行使用,还需要返回。(有的小伙伴此时可能会感觉有点复杂,没有 Vue2 直接写 data 那么直观,但这正式 Vue3 的先进之处,不用暴漏在界面中的变量就可以不进行返回了。精确控制那些方法和变量被导出和使用)。
<script lang="ts">
import { defineComponent, ref } from "vue";
export default defineComponent({
name: "App",
setup() {
const girls = ref(["大脚", "刘英", "晓红"]);
return {
girls
};
},
});
</script>
写完后可以把这三个美女用按钮的形式展示在页面上,这里使用v-for
语法。代码如下:
<button v-for="(item, index) in girls" v-bind:key="index">
{{ index }} : {{ item }}
</button>
现在要实现的就是当我们点击按钮的时候,触发一个方法selectGirlFun
,方法绑定一个选定值selectGirl
,具体实现代码如下。
<script lang="ts">
import { defineComponent, ref } from "vue";
export default defineComponent({
name: "App",
setup() {
const girls = ref(["大脚", "刘英", "晓红"]);
const selectGirl = ref("");
const selectGirlFun = (index: number) => {
selectGirl.value = girls.value[index];
};
//因为在模板中这些变量和方法都需要条用,所以需要return出去。
return {
girls,
selectGirl,
selectGirlFun,
};
},
});
</script>
修改template
代码,为Button
绑定selectGirlFun
事件,实现联动效果。
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<div>
<h2>欢迎光临红浪漫洗浴中心</h2>
<div>请选择一位美女为你服务</div>
</div>
<div>
<button
v-for="(item, index) in girls"
v-bind:key="index"
@click="selectGirlFun(index)"
>
{{ index }} : {{ item }}
</button>
</div>
<div>你选择了【{{ selectGirl }}】为你服务</div>
</template>
这样我们这个最简单的点餐小程序就制作完了。
我们通过一个简单的大宝剑点餐需求,讲解了一些 Vue3 的新知识点,现在来总结一下:
setup
函数的用法,可以代替 Vue2 中的 date 和 methods 属性,直接把逻辑卸载 setup 里就可以ref
函数的使用,它是一个神奇的函数,我们这节只是初次相遇,要在template
中使用的变量,必须用ref
包装一下。return
出去的数据和方法,在模板中才可以使用,这样可以精准的控制暴漏的变量和方法。这节课我们就学这么多,需要提醒小伙伴的是一定要跟着技术胖一起学习,把代码敲出来。只听是学不会的,我在所有的课程中反复强调这个问题,目的只有一个,就是让你能学有所成。
上节课学习了setup()
和ref()
,也算和 Vue3 代码有了一次亲密接触,你现在也做出了一个“大宝剑餐单”。这节我们就学一下reactive
对语法和规范,然后用它来优化上节课的代码。所以此刻没有打上节课代码的同学,请暂停一下,把上节课的代码打出来,再继续学习。
上节课的代码可以说没什么章法可言,所有的变量和方法都混淆在一起,我最不能忍受的是在setup
中要改变和读取一个值的时候,还要加上value
。这种代码一定是可以优化的,需要引入一个新的 APIreactive
。它也是一个函数(方法),只不过里边接受的参数是一个 Object(对象)。
然后无论是变量和方法,都可以作为 Object 中的一个属性,而且在改变selectGirl
值的时候也不用再加讨厌的value
属性了。再return
返回的时候也不用一个个返回了,只需要返回一个data
,就可以了。
<script lang="ts">
import { ref, reactive } from "vue";
export default {
name: "App",
setup() {
const data = reactive({
girls: ["大脚", "刘英", "晓红"],
selectGirl: "",
selectGirlFun: (index: number) => {
data.selectGirl = data.girls[index];
},
});
return {
data,
};
},
};
</script>
修改完成<script>
部分的代码后,还需要修改template
部分的代码,因为我们这时候返回的只有data
,所以模板部分的字面量前要加入data
。
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<div>
<h2>欢迎光临红浪漫洗浴中心</h2>
<div>请选择一位美女为你服务</div>
</div>
<div>
<button
v-for="(item, index) in data.girls"
v-bind:key="index"
@click="data.selectGirlFun(index)"
>
{{ index }} : {{ item }}
</button>
</div>
<div>你选择了【{{ data.selectGirl }}】为你服务</div>
</template>
这个修改完成后,可以在Terminal
终端里打开yarn serve
,查看一下效果了,如果没有错误,应该和原来的效果一样。效果虽然一样,但是这时候代码,要比上节课优雅了很多。着一些的功劳要归属于reactive
函数。
这时的代码虽然可以完美的运行,但是细心的小伙伴可以发现data
这个变量,我们并没有作类型注解
,而是采用了TypeScript
的类型推断。
这样的代码,在我们公司是不允许出现的,必须要增加类型注解。所以我们先定义一个接口,用接口(interface
)来作类型注解。
interface DataProps {
girls: string[];
selectGirl: string;
selectGirlFun: (index: number) => void;
}
编写完成后,你在显示的为 data
变量作一个类型注解.
cosnt data: DataProps = ...
这时候我们的代码才是严谨的。
现在template
中,每次输出变量前面都要加一个data
,这是可以优化的。有的小伙伴说了,我用...
扩展运算符就可以解决这个问题了。
在这里我就可以告诉你不行,因为结构后就变成了普通变量,不再具有响应式的能力。所以要解决这个问题,需要使用 Vue3 的一个新函数toRefs()
。使用前需要先进行引入。
import { reactive, toRefs } from "vue";
引入后就可以对data
进行包装,把 data 变成refData
,这样就可以使用扩展运算符的方式了。具体代码如下:
export default {
name: "App",
setup() {
// const girls = ref(["大脚", "刘英", "晓红"]);
// const selectGirl = ref("");
// const selectGirlFun = (index: number) => {
// selectGirl.value = girls.value[index];
// };
const data: DataProps = reactive({
girls: ["大脚", "刘英", "晓红"],
selectGirl: "",
selectGirlFun: (index: number) => {
data.selectGirl = data.girls[index];
},
});
const refData = toRefs(data);
return {
...refData,
};
},
};
这样写之后,你的template
就应该去掉 data,而是直接使用变量名和方法,就可以了。
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<div>
<h2>欢迎光临红浪漫洗浴中心</h2>
<div>请选择一位美女为你服务</div>
</div>
<div>
<button
v-for="(item, index) in girls"
v-bind:key="index"
@click="selectGirlFun(index)"
>
{{ index }} : {{ item }}
</button>
</div>
<div>你选择了【{{ selectGirl }}】为你服务</div>
</template>
网络上对这两个方法的争论还是不少的,但到目前为止,还没有什么实质性的理论到底是用Ref()
好,还是reactive()
好,也就是两种方法都可以。他们的作用都是生成响应式对象,目前来看只是编写上有所不同。
我个人更倾向于使用reactive()
,因为它让程序看起来更规范。如果你学到这里还犹豫不定,也没关系,随着你进一步的深入学习,一定会有你自己的最佳选择。
Vue3 版本的生命周期和 Vue2 比有了些变化,所以我先站在一个初学者的角度(没有学过 Vue2 版本的新手),从新讲一下 Vue3.x 的生命周期,等你完全理解之后,我们再来和 Vue2.x 的生命周期作一个对比。
Vue 是组件化编程,从一个组件诞生到消亡,会经历很多过程,这些过程就叫做生命周期。
来个比喻,生命周期和人从出生到入土是一样的。有少年时期、有青年时期、有中年时期、有老年时期。每个时期都应该有不同的任务,可以作不同的事。
当你理解了什么是生命周期,你还了解一个概念“钩子函数”。
钩子函数: 伴随着生命周期,给用户使用的函数,操控生命周期,主要是操控钩子函数。
Vue3 的生命周期比较多,我们需要一个个给大家讲。
beforeCreate
和created
之前执行。创建的是data
和method
<keep-alive>
中的组件,会多出两个生命周期钩子函数。被激活时执行。注:使用<keep-alive>
组件会将数据保留在内存中,比如我们不想每次看到一个页面都重新加载数据,就可以使用<keep-alive>
组件解决。
来到上节课的“红浪漫点餐程序”,在这个程序中依次输出对应的生命周期函数,来看看结果。
Vue3.x 生命周期在调用前需要先进行引入,我们先暂时演示前五个生命周期。
import {
reactive,
toRefs,
onMounted,
onBeforeMount,
onBeforeUpdate,
onUpdated,
} from "vue";
先来说setup()
,setup 这个函数是在beforeCreate
和created
之前运行的,所以你可以用它来代替这两个钩子函数。
为了看出钩子函数执行的时机,我在setup()
函数里,编写了下面的代码:
<script lang="ts">
//....
const app = {
name: "App",
setup() {
console.log("1-开始创建组件-----setup()");
const data: DataProps = reactive({
girls: ["大脚", "刘英", "晓红"],
selectGirl: "",
selectGirlFun: (index: number) => {
data.selectGirl = data.girls[index];
},
});
onBeforeMount(() => {
console.log("2-组件挂载到页面之前执行-----onBeforeMount()");
});
onMounted(() => {
console.log("3-组件挂载到页面之后执行-----onMounted()");
});
onBeforeUpdate(() => {
console.log("4-组件更新之前-----onBeforeUpdate()");
});
onUpdated(() => {
console.log("5-组件更新之后-----onUpdated()");
});
const refData = toRefs(data);
return {
...refData,
};
},
};
export default app;
</script>
写完后可以到浏览器看一下效果,效果和你想象的应该是一样的。
1 - 开始创建组件---- - setup();
2 - 组件挂载到页面之前执行---- - onBeforeMount();
3 - 组件挂载到页面之后执行---- - onMounted();
4 - 组件更新之前---- - onBeforeUpdate();
5 - 组件更新之后---- - onUpdated();
你这时候一定会有个疑问,那Vue2.X
版本的生命周期函数还可以使用吗?答案是肯定的。
你可以在setup()
函数之后编写Vue2
的生命周期函数,代码如下:
beforeCreate() {
console.log("1-组件创建之前-----beforeCreate()");
},
beforeMount() {
console.log("2-组件挂载到页面之前执行-----BeforeMount()");
},
mounted() {
console.log("3-组件挂载到页面之后执行-----Mounted()");
},
beforeUpdate() {
console.log("4-组件更新之前-----BeforeUpdate()");
},
updated() {
console.log("5-组件更新之后-----Updated()");
},
这时候可以看到,原来的生命周期也是完全可以使用。
你也许会问,那我到底是使用Vue2.x
还是Vue3.x
的生命周期钩子函数?其实这个无所谓,但是不愿混用,如果你用 setup 这种Vue3
的生命周期函数,就不要再使用Vue2
的了。为了你更好的掌握,我作了一个函数对比:
Vue2--------------vue3
beforeCreate -> setup()
created -> setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
activated -> onActivated
deactivated -> onDeactivated
errorCaptured -> onErrorCaptured
通过这样对比,可以很容易的看出 vue3 的钩子函数基本是再 vue2 的基础上加了一个on
,但也有两个钩子函数发生了变化。
BeforeDestroy
变成了onBeforeUnmount
destroyed
变成了onUnmounted
尤大神的介绍是mount
比Destroy
更形象,也和beforeMount
相对应。
除了这些钩子函数外,Vue3.x
还增加了onRenderTracked
和onRenderTriggered
函数,这两个函数放到下节课再讲解。这节就先到这里了。
这两个钩子函数是Vue3.x
版本新加的两个钩子函数,官方说是用来调试使用的,但是目前还没有给出具体的调试案例。
Vue 官方的文档里,明确指出了。如果你使用 Vue3,请尽量使用新的生命周期钩子函数,也就是上节课写在setup()
函数中带on
的这些钩子函数。
onRenderTracked
直译过来就是状态跟踪
,它会跟踪页面上所有响应式变量和方法的状态,也就是我们用return
返回去的值,他都会跟踪。只要页面有update
的情况,他就会跟踪,然后生成一个event
对象,我们通过event
对象来查找程序的问题所在。
使用onRenderTracked
同样要使用import
进行引入。
import { .... ,onRenderTracked,} from "vue";
引用后就可以在setup()
函数中进行引用了。
onRenderTracked((event) => {
console.log("状态跟踪组件----------->");
console.log(event);
});
写完后可以到终端中启动测试服务yarn serve
,然后看一下效果,在组件没有更新的时候onRenderTracked
是不会执行的,组件更新时,他会跟组里边每个值和方法的变化。
onRenderTriggered
直译过来是状态触发
,它不会跟踪每一个值,而是给你变化值的信息,并且新值和旧值都会给你明确的展示出来。
如果把onRenderTracked
比喻成散弹枪,每个值都进行跟踪,那onRenderTriggered
就是狙击枪,只精确跟踪发生变化的值,进行针对性调试。
使用它同样要先用import
进行引入
import { .... ,onRenderTriggered,} from "vue";
在使用onRenderTriggered
前,记得注释相应的onRenderTracked
代码,这样看起来会直观很多。
然后把onRenderTriggered()
函数,写在setup()
函数里边,
onRenderTriggered((event) => {
console.log("状态触发组件--------------->");
console.log(event);
});
对 event 对象属性的详细介绍:
- key 那边变量发生了变化
- newValue 更新后变量的值
- oldValue 更新前变量的值
- target 目前页面中的响应变量和函数
通过这些你能很好的对代码进行调试。这些调试用的钩子函数,如果你能正确合理的使用,是真的可以快速解决问题的。
有的小伙伴看到这里肯定会觉的,这个和watch
很像,那下节课我们再讲一下watch
的使用吧,这个也有了很大的变化。
Vue2中也有watch
-监听器(侦听器),作用是用来侦测响应式数据的变化,并且可以得到newValue
新值和oldValue
老值。如果你熟悉Vue2一定熟悉这个函数,但在Vue3中watch
有了一些细微的变化,我们来学习一下。
现在我们的“红浪漫洗浴中心”老板有新的需求了,当你点击按钮,点餐完毕,WEB标题也要跟着改变,这时候你好像没办法变成自动相应,双向绑定了。今天的主角就排上用场了,watch
监听器隆重登场。
类似的情况也会有,比如根据值的变化,进行网络请求,根据值的变化进行组件的生成和销毁(我们经常成为这类操作为副作用)。把这类需求写在watch
监听器里就是不错的选择。
在写代码之前,你可以删除前两节课学习生命周期时的钩子函数,让代码变得干净一些。
现在你可以先作一个按钮的响应值和改变值的方法,并写在setup()
函数中,这里我使用了ref来生成响应式数据,你可以跟着我一起复习一下。
{
//.....
const overText = ref("红浪漫");
const overAction = () => {
overText.value = overText.value + "点餐完成 | ";
};
return { ...refData, overText, overAction};
}
写完js代码后,在template
模板中,编写下面的代码,这样可以在点击按钮时,调用overAction
函数。
<div><button @click="overAction">点餐完毕</button></div>
<div>{{ overText }}</div>
现在完成老板的需求,我们在改变的时候直接用js修改WEB的title。
const overAction = () => {
overText.value = overText.value + "点餐完成 | ";
document.title = overText.value;
};
都完成后,可以到浏览器中看一下你写的效果。发现我们写的根本没有用处,跟我们想的一点都不一样。这时候就需要Watch来救场啦。
使用watch同样需要先进行导入.
import {... , watch} from "vue"
引入后编写watch函数,它接受两个参数,第一个是要监听的值,这里是overText
,然后是一个回调函数。在函数中你可以获得到新知和老值。
watch(overText, (newValue, oldValue) => {
document.title = newValue;
});
为了看到效果,我用console.log
输出一下新值和老值。
watch(overText, (newValue, oldValue) => {
console.log(`new--->${newValue}`);
console.log(`old--->${oldValue}`);
document.title = newValue;
});
当你要监听多个值的时候,不是写多个watch
函数,而是要传入数组的形式。比如现在我们同时要监听data
中你选择了那个女孩,也就是selectGirl
时,我们可以使用数组的形式。
我们把程序写成这个样子,然后到浏览器中预览。
watch([overText, data.selectGirl], (newValue, oldValue) => {
console.log(`new--->${newValue}`);
console.log(`old--->${oldValue}`);
document.title = newValue[0]; //返回的newValue也是一个数组
});
发现报错了,它告诉我们可以用一个函数解决reactive
中的值的问题。把程序写成这个下面的样子就不报错了。
watch([overText, () => data.selectGirl], (newValue, oldValue) => {
console.log(`new--->${newValue}`);
console.log(`old--->${oldValue}`);
document.title = newValue[0];
});
现在程序就可以正常运行了,有人会说Vue3不能监听reactive
里边的值是不是一个Bug,我想说的这并不是Bug,而是为了保持和Vue2的一致性,因为在Vue2中也时这种结果,解决方案是要么是ref或者这种get/set方法的形式。要么你你开启设置watchOptions
的deep为true,也就是深度监听模式。
好了,这节课的内容就到这里了,下节课我们继续学习。
Vue3.x版本最大的一个提升,就是有更好的重用机制,你可以把任何你想独立的模块独立出去。比如在上节课的基础上,加一个显示当前时间的功能(例如:17:30:20)。并且这个功能要在不同的页面进行反复调用。
使用Vue2.x的版本,一定会使用mixins
进行代码的重用。当有Vue3.x
为了方便学习,我们把程序中大部分代码删除掉,修改为下面的样子。
<template>
<div>
</div>
</template>
<script lang="ts">
import { ref } from "vue";
const app = {
name: "App",
setup() {
},
};
export default app;
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
然后就可以编写代码了
先来看不重用的写法,也就是我们把程序直接写在App.vue
这个组件里。这里你可以先顶一个ref
变量nowTime
,然后通过getNowTime
的方法,让他可以显示并一直更新当前时间。最后在return
里返回这个变量和方法。
//....
const app = {
name: "App",
setup() {
//.....
const nowTime = ref("00:00:00");
const getNowTime = () => {
const now = new Date();
const hour = now.getHours() < 10 ? "0" + now.getHours() : now.getHours();
const minu =now.getMinutes() < 10 ? "0" + now.getMinutes() : now.getMinutes();
const sec =now.getSeconds() < 10 ? "0" + now.getSeconds() : now.getSeconds();
nowTime.value = hour + ":" + minu + ":" + sec;
setTimeout(getNowTime, 1000); //每一秒执行一次这个方法
};
//...
return {
//....
nowTime,
getNowTime,
};
},
};
export default app;
然后你需要在template
里使用他们,代码如下.
<div>{{ nowTime }}</div>
<div><button @click="getNowTime">显示时间</button></div>
这样就可以在浏览器里看到初始时间00:00:00
,点击按钮后,开始显示当前时间,并一直更新。
这个显示时间的方法,可能在其他页面中也会使用,所以现在的需求是把这个时间显示的功能进行模块和重用化。
可以在src
目录下,新建一个文件夹hooks
(所有抽离出来的功能模块都可以放到这个文件夹里),然后再新建一个文件useNowTime.ts
,这里使用use
开头是一个使用习惯,代表是一个抽离出来的模块。
有了模块之后,我们就可以把写的代码复制到useNowTime.ts
文件里了。然后进行必要的修改。
import { ref } from "vue";
const nowTime = ref("00:00:00");
const getNowTime = () => {
const now = new Date();
const hour = now.getHours() < 10 ? "0" + now.getHours() : now.getHours();
const minu =
now.getMinutes() < 10 ? "0" + now.getMinutes() : now.getMinutes();
const sec =
now.getSeconds() < 10 ? "0" + now.getSeconds() : now.getSeconds();
nowTime.value = hour + ":" + minu + ":" + sec;
setTimeout(getNowTime, 1000);
};
export { nowTime, getNowTime }
需要注意的是,你需要在代码的最前面用import
进行引入ref
,在最后用export
的方式,导出nowTime
和getNowTime
.
模块写好了,回到App.vue
页面,现在可以引入并使用模块了。
引入代码:
import { nowTime, getNowTime } from "./hooks/useNowTime";
然后记得,要用return进行导出哦
return {nowTime,getNowTime};
现在可以看出这种方式,比vue2中要好很多,不用再使用mixins
(混入)要好很多。我觉的这个算是Vue3.x一个非常重要的改进。
这时候“红浪漫”洗浴的老板有了新的项目,要求来的顾客可以随机选择一位美女服务,增加刺激性,我们的任务也是作一个随机选择的菜单,每次刷新都会随机出现大脚、刘英或者是晓红。趁这个机会,我们正好也练习一下Vue3.x中的模块化。
以前我们写了很多程序,看起来有些杂乱无章了,所以这节我们先把一些无用的代码删除掉。然后再用模块化的概念编写今天的随机选美女的程序。
<template>
<div>
<h2>欢迎光临红浪漫洗浴中心</h2>
<div>随机选择一位美女为你服务</div>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, ref, watch } from "vue";
const app = {
name: "App",
setup() {
return {};
},
};
export default app;
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
我们删除掉了大部分的代码,只留了几个文字。这样代码看起来就清爽的多了,也可以开始编写代码了。
这里我们使用axios来进行远程随机获得图片,但是我们这里作的不是远程随机获得图片,而是模块化一个通用的远程调用API的组件,这个组件可以远程请求一个指定的URL,并且返回所得到的值。
先用npm
的方式安装axios
.
npm install axios --save
这个的安装的时间会稍微有一点长。
在上节课的文件夹里,新建一个文件,叫做useURLAxios.ts
,然后先引入ref
和axios
.在文件里写一个useUrlAxios
方法,在方法里声明四个响应式变量result
、loading
、loaded
和error
。声明好后,使用axios
进行访问远程链接。最后记得要进行return
和export default
。
import { ref } from 'vue'
import axios from 'axios'
function useUrlAxios(url: string) {
const result = ref(null)
const loading = ref(true)
const loaded = ref(false)
const error = ref(null)
axios.get(url).then((res) => {
loading.value = false
loaded.value = true
result.value = res.data
}).catch(e => {
error.value = e
loading.value = false
})
return {
result,
loading,
loaded,
error
}
}
export default useUrlAxios
我自己作了一个随机美女的API,你直接调用就可以了,不用传任何参数,只要进行get请求就可以得到随机出现大脚、刘英和晓红的图片的地址。
也请小伙伴手下留情,不要随意攻击此接口,方便其他小伙伴们学习。
我们先来实现进入页面随机显示一个美女图片,然后刷新会出现不同的美女。
<template>
<div>
<h2>欢迎光临红浪漫洗浴中心</h2>
<div>随机选择一位美女为你服务</div>
<div v-if="loading">Loading.....</div>
<img v-if="loaded" :src="result.message" />
<div></div>
</div>
</template>
<script lang="ts">
import { ref } from "vue";
import useUrlAxios from "./hooks/useUrlAxios";
const app = {
name: "App",
setup() {
const { result, loading, loaded } = useUrlAxios(
"https://dog.ceo/api/breeds/image/random"
);
return { result, loading, loaded };
},
};
export default app;
</script>
好了,我们只要刷新,都可以随机显示一张美女的照片。但这不是重点,重点是你要学会这种独立模块化的方式,让我们的代码可以复用。建议这个代码要多写两边,养成这种模块化的思维方式。
Teleport
在国内大部分都翻译成了瞬间移动组件,个人觉得不太好理解。我把这个函数叫独立组件,它可以把你写的组件挂载到任何你想挂载的DOM上,所以说是很自由很独立的。
在使用Vue2
的时候是作不到的。
为了更好的演示和复习,先编写一个弹出框组件,这节我们作到显示就好,其它的显示、隐藏功能先不作。
在/src/components/
目录下,创建一个Modal.vue
的组件,组件代码很简单。
<template>
<div id="center">
<h2>JSPang11</h2>
</div>
</template>
<script lang="ts">
export default {};
</script>
<style>
#center {
width: 200px;
height: 200px;
border: 2px solid black;
background: white;
position: fixed;
left: 50%;
top: 50%;
margin-left: -100px;
margin-top: -100px;
}
</style>
这样组件就编写好了,这段代码非常简单,多数都在CSS样式层面,而样式学习不是我们的重点,你完全可以复制。
组件写好后,在App.vue中使用就非常简单了,先引入这个,然后声明为component
就可以了。
//...
import modal from "./components/Modal.vue";
const app = {
name: "App",
components: {
modal,
},
//...
}
//...
这样就可以在template
中进行使用了<model />
。写完后,你可以用yarn serve
开启服务,并在浏览器中使用http://localhost:8080/
查看结果。
在看结果时,你会发现所有的Dom都是在app节点下的,如果你想改变节点,在Vue2时代这非常困难。但是在Vue3.x
时代,只需要使用Teleport
组件就可以解决。
这样包裹遇到的问题
Teleport
方法,可以把Dialog
组件渲染到你任意想渲染的外部Dom上,不必嵌套再#app
里了,这样就不会互相干扰了。你可以把Teleport
看成一个传送门,把你的组件传送到你需要的地方。
teleport
组件和其它组件没有任何其它的差异,用起来都是一样的。
使用的第一步是把你编写的组件用<teleport>
标签进行包裹,在组件上有一个to
属性,这个就是要写你需要渲染的DOM
ID了。
<template>
<teleport to="#modal">
<div id="center">
<h2>JSPang11</h2>
</div>
</teleport>
</template>
然后我们在打开/public/index.html
,增加一个model
节点。
<div id="app"></div>
<div id="modal"></div>
这时候在浏览器中预览,就会发现,现在组件已经挂载到model
节点上了,这就是teleport
组件的使用了。
在前端开发中,异步请求组件必不可少。比如读取远程图片,比如调用后台接口,这些都需要异步请求。在Vue2.x时代,判断异步请求的状态是一件必须的事情,但是这些状态都要自己处理,根据请求是否完毕展示不同的界面。尤大神深知民间饥苦,在Vue3.x中给我们提供了Suspense
组件。这节课我们就先简单学习一下。
在红浪漫随机选择服务菜单那节中,已经作了一个异步请求的组件,并且是简单处理了请求状态的。学会Suspense
之后,就不用自己手写这些业务逻辑处理请求状态了,Suspense
提供两个template的位置,一个是没有请求回来时显示的内容,一个是全部请求完毕的内容。这样进行异步内容的渲染就会非常简单。
注意点:如果你要使用Suspense
的话,要返回一个promise对象,而不是原来的那种JSON
对象。
我们先用一个例子来感受一下,我们先来写一个组件,在components
文件夹下边,新建一个AsyncShow.vue
文件,然后边下代码如下:
<template>
<h1>{{ result }}</h1>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
setup() {
return new Promise((resolve, reject) => {
setTimeout(() => {
return resolve({ result: "JSPang" });
}, 2000);
});
},
});
</script>
defineComponent
是用来解决TypeScript情况下,传统的Vue.extends
无法对组件给出正确的参数类型推断的。也就是说在TypeScript环境中如果参数类型推断不正常时,用defineComponent()
组件来进行包装函数。
然后我们new
了一个Promise
对象,然后用setTimeout
等待两秒后返回JSPang
文字就可以了。
组件写起来并没有什么难点,下面就是把这个组件放置到App.vue
中。
下面我们把App.vue
文件中以前写的代码尽量清理干净。
<template>
<div>
</div>
</template>
<script lang="ts">
import { ref } from "vue";
import useUrlAxios from "./hooks/useUrlAxios";
const app = {
name: "App",
components: { },
setup() {
return {};
},
};
export default app;
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
然后先把刚才编写好的自定义组件AsyncShow.vue
组件引进过来。代码如下(此时的路径有可能和我不同):
import AsyncShow from "./components/AsyncShow.vue";
引入之后,想使用这个组件,记得要再components
中进行声明,也就是把AsyncShow
放入到components
中。
const app = {
name: "App",
components: { AsyncShow },
setup() {
return {};
},
};
这样自定义组件就可以使用了,我们的自定组件已经返回了Pronmise
结果,所以可以直接使用Suspense
来控制状态和输出内容。
<template>
<div>
<Suspense>
<template #default>
<AsyncShow />
</template>
<template #fallback>
<h1>Loading...</h1>
</template>
</Suspense>
</div>
</template>
可以看到Suspense
是有两个template
插槽的,第一个default
代表异步请求完成后,显示的模板内容。fallback
代表在加载中时,显示的模板内容。
写完后,用yarn serve
打开测试服务,看一下结果。如果一切正常,你可以看到,当我们打开页面时,首先显示的是Loading
,然后才会显示JSPang
。也就是promise返回的结果。
这节课,算是初步认识一下Suspense
组件,下节课我们继续学习Suspense
更多的用法。
上节课我们是一个假的异步请求,利用了setTimeOut()
方法来模拟异步请求,当然这也很恰当的演示了Suspense
的使用方法。这节课我们就深入一下,用以前请求象牙山三大美女的API真实接口来继续深入学习一下。
我在这里先给出API地址:
在/src/components/
目录下,新建一个GirlShow.vue
的新组件。
我们先来写个基本的模板,其实你可以把这段代码复制进你的程序,因为这段代码你一定打过很多遍了。
<template>
</template>
<script lang="ts">
import axios from 'axios'
import { defineComponent } from 'vue'
export default defineComponent({
setup() {
}
})
</script>
再向下写,需要注意的是,上节课的例子,我们返回的是一个promise
对象,其实我个人是不喜欢promise
这种写法的,我更喜欢用async...await
的写法,它是promise
的语法糖。建议你在工作中也尽量的使用async...await
的写法。
Suspense
也是支持async...await
的语法的,所以这个组件就用async
的写法来写。
<template>
<img :src="result && result.imgUrl" />
</template>
<script lang="ts">
import axios from 'axios'
import { defineComponent } from 'vue'
export default defineComponent({
async setup() { //promise 语法糖 返回之后也是promise对象
const rawData = await axios.get('https://apiblog.jspang.com/default/getGirl')
return {result:rawData.data}
}
})
</script>
这样组件就编写完成了,看起来是比纯Promise
的写法好看很多了。
打开App.vue
页面,然后先用import
引入GirlShow.vue
。
import GirlShow from "./components/GirlShow.vue";
然后在components
中声明一下,就可以在模板中使用了
const app = {
name: "App",
components: { AsyncShow, GirlShow },
setup() {
return {};
},
};
模板部分代码。
<template>
<div>
<Suspense>
<template #default>
<girl-show />
</template>
<template #fallback>
<h1>Loading...</h1>
</template>
</Suspense>
</div>
</template>
这部分写完,就可以打开服务yarn serve
,然后到http://localhost:8080/
预览一下结果哦。注意,我的服务器设置了缓存,所以你可能几次刷新都会是同一张照片,这个不是你的问题。但你也要注意,自己是不是也有图片缓存。
在异步请求中必须要作的一件事情,就是要捕获错误,因为我们没办法后端给我们返回的结果,也有可能服务不通,所以一定要进行捕获异常和进行处理。
在vue3.x
的版本中,可以使用onErrorCaptured
这个钩子函数来捕获异常。在使用这个钩子函数前,需要先进行引入.
import { ref , onErrorCaptured} from "vue";
有了onErrorCaptured
就可以直接在setup()
函数中直接使用了。钩子函数要求我们返回一个布尔值,代表错误是否向上传递,我们这里返回了true
。
const app = {
name: "App",
components: { AsyncShow, GirlShow },
setup() {
onErrorCaptured((error) => {
console.log(`error====>`,error)
return true
})
return {};
},
};
写好后,我们故意把请求地址写错,然后打开浏览器的终端,看一下控制台已经捕获到错误了。在实际工作中,你可以根据你的真实需求,处理这些错误。我这里就不做过多的演示啦。
No Data