2020 年 9 月 19 日 Vue3 更新了正式版本,自此VUE正式开启了3.x的时代!Vue3也是目前最值得一学的前端框架之一。
官方网站地址: v3.vuejs.org
Vue3 有哪些新特性呢?
- Vue3采用渐进式开发,向下兼容:Vue3 支持大多数 Vue2 的特性,也就是说咱们使用 Vue2 的语法开发 Vue3,也是没有任何问题的,当然我们并不推荐这种做法;
- 性能的提升,每个人都希望使用的框架更快、更轻,Vue3 做到了,给了开发者一个极致的体验,官方网站给出的数据是:打包大小减少 41%、初次渲染快 55%、更新快 133%、内存使用减少 54%,确实是非常惊艳的提升;
新推出
Composition API
Vue3 采取的新的接口使用方式。这种新的方式叫做Composition API
(组合式 API)。而与之相对应的经典 API 也是我们所熟知的 Vue 使用方式叫做Options API
(选项式 API)或Options-based API
(基于选项的 API)。
- 在经典的
Options API
中,我们使用一个具有data
,methods
等「选项」的 JS 对象来定义一个页面或者组件。这种简单直接的方式,在应用早期阶段,代码和业务逻辑较简单时,非常的友好亲民,这也是 Vue 学习门槛较低而广受开发者亲昵的的一个因素。- 但是,有过开发大型 Vue 应用的开发者应该心有体会。当页面的逻辑越来越多时,我们的组件将变得冗长复杂。很多本可以复用的逻辑和代码,你很难有一种使用起来非常舒适的方式来复用。比如:在 Vue2 中,组件逻辑和代码复用最常用的方式是混入
mixin
,这虽然是一种可行的方式,但是这种方式显然从出生和 Vue 框架紧密耦合。当你想要将一个框架无区别的普通 JS 函数或者对象复用到 Vue2 开发的组件中时,你发现一切都是那么的不优雅。基于满足在开发大型 Vue 应用中更优雅地复用已有代码的需求催生下,Vue3
Composition API
似乎是顺势而为,并且势在必得。
- 其他新特性:
Teleport
瞬移组件、Suspense
解决异步加载组件问题 和全局 API 的修改和优化;
- 更好
TypeScript
支持, Vue2 并不是特别适应TypeScript
,集成困难,痛点太多,但 Vue3 解决了这个问题,Vue3 的源代码就是使用TypeScript
进行开发的,所以使用TS
自然就更加顺畅无阻。
- 安装最新版本 vue-cli 脚手架工具,只有 V4.5.4 以上版本才有创建 Vue3 的选项
npm install -g @vue/cli # OR yarn global add @vue/cli vue -V
- 使用 vue-cli 命令行
vue create Projv3
创建一个项目$ vue create Projv3 # 选择使用 vue3 来构建项目 $ cd Projv3 $ yarn serve
- 使用 vue-cli 图形界面搭建 Vue3 项目
- 安装最新版
Vue-cli
就可以使用vue ui
这个命令,开启一个 UI 界面- 打开图形界面配置对应文件
|-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" } }
这三个命令的意思是:
serve
: 在开发时用于查看效果的命令build
: 打包打码,一般用于生产环境中使用lint
: 检查代码中的编写规范
package.json
中另外两个比较重要的配置项dependencies
和devDependencies
,
dependencies
下的包是生产环境中必须用到的,当然开发环境也需要;devDependencies
是只有开发环境中使用的,上线后这些包就没用了,打包后也不会打包进去的代码。
在 vue3 中,template 根节点中不再必须使用一个标签包裹起来了,允许咱们有多个兄弟标签
// 从 vue 依赖中导入 createAPP API 方法 import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' // 调用 createAPP 方法,这个方法的返回可以被链式调用 const app = createApp(App) app.use(store).use(router).mount('#app')
Vue3.x 生命周期简介
- setup() :开始创建组件之前,在
beforeCreate
和created
之前执行,创建的是data
和method
- onBeforeMount() : 组件挂载到节点上之前执行的函数;
- onMounted() : 组件挂载完成后执行的函数;
- onBeforeUpdate(): 组件更新之前执行的函数;
- onUpdated(): 组件更新完成之后执行的函数;
- onBeforeUnmount(): 组件卸载之前执行的函数;
- onUnmounted(): 组件卸载完成后执行的函数;
- onActivated(): 被包含在
中的组件,会多出两个生命周期钩子函数,被激活时执行; - onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行;
- onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数。
PS: 使用
组件会将数据保留在内存中,比如我们不想每次看到一个页面都重新加载数据,就可以使用
组件解决。
Vue2.x 和 Vue3.x 生命周期对比
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 - 生命周期钩子函数
响应式拦截数据 data 的值是:{{ msg }}
onRenderTracked
直译过来就是状态跟踪
,它会跟踪页面上所有响应式变量和方法的状态,也就是我们用return
返回去的值,他都会跟踪,只要页面有update
的情况,他就会跟踪,然后生成一个event
对象,我们通过event
对象来查找程序的问题所在;onRenderTriggered
直译过来是状态触发
,它不会跟踪每一个值,而是给你变化值的信息,并且新值和旧值都会给你明确的展示出来。- 如果把
onRenderTracked
比喻成散弹枪,每个值都进行跟踪,那onRenderTriggered
就是狙击枪,只精确跟踪发生变化的值,进行针对性调试。
重点:
- 熟悉
composition API
编程- 在
setup
生命周期方法中定义事件并返回出去才能被 template 调用
This is home page!
重点:
- 能够使用
reactive
构建 proxy 响应式对象;- 理解 proxy 响应式对象和普通对象之间的区别;
- 注意在
template
中使用响应式对象{{ state.msg }}
加上前缀;- 理解
getCurrentInstance
API 方法获取当前 vue 对象实例;- 注意: ref 构建的对象在 js 中使用
.value
获取值
This is home page!
{{ state.msg }}
{{ info }}
重点:
- 能够理解 ref 构建响应式对象的由来
- 能够使用 ref 方法构建响应式对象
- 能够使用 toRefs 转换 reactive 中构建的响应式对象
This demo-02 for study!
使用 v-model 双向绑定数据的内容是: {{state.msg}}
使用 @input 事件动态实现双向数据绑定的内容是: {{state.nmsg}}
使用 ref 方法动态定义并双向绑定的 hmsg 值是: {{hmsg}}
使用 toRefs 来实现在模板中不需要追加 state 调用数据
msg 的值是:{{msg}}
重点:
- 使用 computed API 方法构建响应式计算属性对象
- 注意在 Vue3 中不推荐使用 filter 过滤器,建议使用 computed 计算属性来替代
使用 v-model 双向绑定数据的内容是: {{state.msg}}
使用 计算属性,当前输入的内容长度是: {{ cmsg }}
重点:
- 能够使用 watch 实现简单监听数据变化效果
- 能够使用 watch 一次性监听多个响应式数据对象
- 能够使用 watchEffect 监听数据状态变化
Vue3 - watch 和 watchEffect
{{msg}}
重点:
- 能够使用 Vue3 基础数据操作相关知识,实现点餐基础 TodoList 功能
- js 浮点数相加误差消除简单办法的实现
ToDoList 点餐服务
菜单列表:
- {{item.name}} 价格 {{item.price}}
已点菜单:
- {{item.name}} 价格 {{item.price}}
你一共点了 {{checkListNum}} 道菜,消费 {{allPay}} 元
重点:
- 父组件基于 props 传递数据给子组件
- 子组件基于 事件模拟 触发父组件事件,完成数据通信
- 父组件基于 slot 传递文档结构给子组件
Vue3 - 父子组件通信
{{msg}}
-----------父组件传值给子组件---------
---------子组件模拟事件触发父组件定义好的事件-----------
这是父组件中slot传递过来的内容
被调用的 child 组件
直接接收父组件中传递过来的 props 内容:{{parentMsg}}
传递过来内容的长度是:{{msgLength}}
重点:
- 定义 vuex store 全局状态管理器
- 能够在 template 中使用 store 中定义的属性
- 能够使用 mapActions 使用 store 中定义的方法
import { createStore } from 'vuex' export default createStore({ state: { username: 'Vuex-username 初始化状态' }, mutations: { M_LOGIN (state, name) { state.username = name }, M_LOGOUT (state) { state.username = '退出状态' } }, actions: { login ({ commit }, name) { commit('M_LOGIN', name) }, logout ({ commit }) { commit('M_LOGOUT') } }, modules: { } })
Vue3 vuex 状态管理器
{{$store.state.username}}
目的:
能够理解
provide
在父组件以上如何供应消费数据理解子组件中
inject
如何调用定义的的数据provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性
provide:Object | () => Object
inject 选项应该是一个字符串数组,或一个对象,对象的 key 是本地的绑定名
inject:Array
| { [key: string]: string | Symbol | Object }
provide
和inject
主要为高阶插件/组件库提供用例,并不推荐直接用于应用程序代码中实际上,你可以把依赖注入看作一部分「大范围有效的 prop」,除了:
祖先组件不需要知道哪些后代组件使用它提供的属性
后代组件不需要知道被注入的属性来自哪里提示:provide 和 inject 绑定一般情况下并不是可响应的,以避免数据通信跨组件后的混乱不可控,当然我们一定要用来传递动态属性内容也是可以的
Vue3 对 provide&inject 封装成了其 composition API 方法,以方便更好的调用,同时也方便我们传递动态数据
Provide&inject使用
Inject 子组件
{{ provideMsg }}
{{ globalMsg }}
{{ golbalProxyData }}
Vue3 路由的基础使用
{{item.id}} - {{item.title}} - {{item.author}} - {{item.date}}
重点:
- 理解 组件的定义是为了 抽离复用的一个关键模块
- 组件的使用 components 注册后,在 template 中类似 HTML 标签一样闭合使用
重点:
- 理解 mixins 数据复用的意义和一般使用场景,比如:后台管理系统我们可能多次用到表格来展示内容
- 理解 mixins 数据复用可能存在的弊端
const todoMixin = { methods: { add () { this.num++ }, muit () { this.num-- } } } export default todoMixin
Vue3 - Hooks编程初体验
--- {{num}} ---
目的:
- 能够使用 hooks 实现代码复用
- 能够理解 hooks 实现代码复用的优势
// 定义一个纯函数使用的 hooks import { reactive, toRefs } from 'vue' function useCount () { const data = reactive({ num: 0, muit: () => { data.num-- }, add: () => { data.num++ } }) return { ...toRefs(data) } } // 自定义 hooks ,自定义一个钩子函数,内部的变量、方法独立,不依赖外围状态来实现调用,想咋用咱就咋用 export default useCount
// 在页面中使用 hooks
使用 hooks 实现数据逻辑操作复用
--- {{num}} ---
调用子组件
// 在组件中使用 hooks
组件中的页面结构及样式可以随意,复用的 hooks 逻辑很单纯
--- {{num}} ---
目的:
- 能够使用
Teleport
瞬移组件- 理解 瞬移组件 的优势
Teleport
「瞬间移动组件」,也可以叫做「独立组件」,它可以把你写的组件挂载到任何你想挂载的DOM ID上,所以说是很自由很独立的,我们在使用Vue2
的时候是做不到这一点的。
{{ title }}
{{ info }}
在 index.html 中写一个挂载点
<div id="app">div> <div id="modal">div>
在 Home.vue page 页面中直接调用,但是 modal 这个组件就不会挂载在
#app
下而在#modal
下面了
目的:
- 能够使用 Suspense 异步请求组件
- 理解 Suspense 的优势及意义
在前端开发中,异步请求组件必不可少,比如:读取远程图片、调用后台接口,这些都需要异步请求。
在 Vue2.x 中,我们一般是根据请求返回的结果状态自行追加逻辑来控制是否显示,这种方法略显笨重,所以Vue3.x 中就给我们提供了
Suspense
组件。需要注意的是:如果我们要使用
Suspense
的话,要返回一个promise
对象,而不是原来的那种JSON
对象
setTimeout
实现异步请求组件请求使用
Suspense异步调用显示的组件
{{ info }}
数据正在请求中...
axios
数据请求实现异步请求组件,同步使用 onErrorCaptured
生命周期钩子函数监听错误
新闻列表信息如下:
{{ item.title }}
新闻列表数据正在请求中...