一、安装
1. cdn
<script src="https://unpkg.com/vue@next"></script>
2. npm
$npm install vue@next
3. vue-cli
需要升级到Vue CLI v4.5
yarn global add @vue/cli@next
# OR
npm install -g @vue/cli@next
4. vite
使用 vite 体验更快速
#npm
$ npm init vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev
#yarn
$ yarn create vite-app <project-name>
$ cd <project-name>
$ yarn
$ yarn dev
补充:vue-cli方法搭建步骤可参考下图:
二、Vue3.0 新特性
1. Composition API
官网:https://v3.vuejs.org/api/composition-api.html
使用Vue2.0的Option API写组件,随着业务复杂度越来越高,代码量会不断的加大;由于相关业务的代码需要遵循option的配置写到特定的区域,导致后续维护非常的复杂,同时代码可复用性不高,而Composition API就是为了解决这个问题而生的
1.1 Dom 节点的挂载方式
DOM节点挂载的方式从vue2.0中 new Vue() 实例的方式变成了Vue3.0中 createApp() 的方法
1.2 setup
- composition api其实是配合着 options选项一起使用的,因为还有name、props、components、setup这些选项。只不过是以前所有的功能都成为了一个一个的hook函数,在使用时需要手动引入,并且需要写在setup选项里面。而setup的存在就是为了让我们能够使用composition api。
- setup在组件实例创建之前便开始执行,因此在setup选项中没有this。这也意味着,除了props,你将无法访问到组件任何的状态或者方法。 以前data里面的数据我们是直接可以绑定到template上面的,而在vue3.0 Composition API中需要在setup里面return出去,那么数据便会被合并到渲染的上下文中去,从而在template中使用。
- setup参数
setup(props,context)/setup(props,{attrs,slots,emit})
参数 | 含义 |
---|---|
props | 包含props配置声明且传入了的所有属性的对象(props对象是响应式的,不要去解构,解构会失去响式性) |
attrs | 包含没有在props配置中声明的属性的对象,相当于this.$attrs |
slots | 包含所有传入的插槽内容的对象,相当于this.$slots |
emit | 用来分发自定义事件的函数,相当于this.$emit |
1.3 reactive
reactive接收一个普通对象然后返回该普通对象的响应式代理
- 普通对象==>返回一个proxy对象,响应式转换是深层的,对影响对象内部所有嵌套的属性
- 用user.name=“new name”来修改值
- 内部基于proxy实现
- 获取数据值的时候直接获取,不需要加.value
- 参数只能传入对象类型
1.4 ref
ref 接受一个内部值并返回一个响应式可变的ref对象
- 任意类型==>返回一个ref对象
- 用num.value=***来修改值
- 获取数据值的时候需要加.value。可以理解为ref是通过reactive包装了一层具有value属性的对象实现的
- 参数可以传递任意数据类型,传递对象类型时也能保持深度响应式,所以适用性更广,setup中定义数据时推荐优先使用ref,方便逻辑拆分和业务解耦
- template中使用ref值不用通过value获取(导出后已默认做了一个解构),js中使用ref必须通过.value获取
- ref获取元素
通过 box.value 获取
1.5 toRef
toRef 用于为源响应式对象上的属性新建一个ref,从而保持对其源对象属性的响应式连接。接收两个参数:源响应式对象和属性名,返回一个ref数据。例如使用父组件传递的props数据时,要引用props的某个属性且要保持响应式连接时就很有用。
- Template中直接获取值,js中需要加.value获取数据值
- toRef后的ref数据不是原始数据的拷贝,而是引用,改变结果数据的值也会同时改变原始数据
- 不会触发UI界面的更新
1.6 toRefs
toRefs 用于将响应式对象转换为普通对象,但是其中的每个属性都会指向原始对象相应属性的ref(也就是依然保持响应式)。常用于es6的解构赋值操作,因为在对一个响应式对象直接解构时解构后的数据将不再有响应式,而使用toRefs可以方便解决这一问题。
- 获取数据值的时候需要加.value
- toRefs后的ref数据不是原始数据的拷贝,而是引用,改变结果数据的值也会同时改变原始数据
- 作用其实和 toRef 类似,只不过 toRef 是一个个手动赋值,而 toRefs 是自动赋值
1.7 计算属性 监控属性
computed函数
和vue2.0差不多,在return数据之前,需要对数据做一些操作的话,可以在computed计算属性里面去完成。
watch函数
- 第一个参数可以是一个回调函数(但是当使用reactive包括数据时,必须使用这种方式,如果是ref的话,则可以直接写监听的数据即可不用再写回调函数了)。
- 第二个参数是一个回调函数。
- 第三个参数也是一个flush用于决定执行的时间。
watchEffect
- 不用直接指定要监视的数据, 回调函数中使用的哪些响应式数据就监视哪些响应式数据
- 默认初始时就会执行第一次, 从而可以收集需要监视的数据
- 监视数据发生变化时回调
与watch的不同
1)我们可以从示例代码中看到 watchEffect 不需要指定监听的属性,他会自动的收集依赖, 只要我们回调中引用到了 响应式的属性, 那么当这些属性变更的时候,这个回调都会执行,而 watch 只能监听指定的属性而做出变更(v3开始可以同时指定多个)。
2)watch 可以获取到新值与旧值(更新前的值),而 watchEffect 是拿不到的。
3)watchEffect 如果存在的话,在组件初始化的时候就会执行一次用以收集依赖(与computed同理),而后收集到的依赖发生变化,这个回调才会再次执行,而 watch 不需要,因为他一开始就指定了依赖。
1.8 生命周期
beforeCreate -> 请使用 setup()
created -> 请使用 setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
errorCaptured -> onErrorCaptured
2. Teleport
Teleport 是一种能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术
场景:像 modals, toast 等这样的元素,很多情况下,我们将它完全的和我们的 Vue 应用的 DOM 完全剥离,管理起来反而会方便容易很多,如果我们嵌套在 Vue 的某个组件内部,那么处理嵌套组件的定位、z-index 和样式就会变得很困难。另外,像 modals,toast 等这样的元素需要使用到 Vue 组件的状态(data 或者 props)的值,这就是 Teleport 派上用场的地方。
我们可以在组件的逻辑位置写模板代码,这意味着我们可以使用组件的 data 或 props。然后在 Vue 应用的范围之外渲染它。
3. Fragments
vue3组件中可以拥有多个根
4. Emits Component Option
vue3新增emits选项,需要将组件发送的自定义事件定义在emits选项中。
- 可以避免当自定义事件与原生事件重名时,事件会触发多次的情况,比如:click事件
- 可以更好的指示组件的工作方式
- 对象形式可对事件进行校验
5. 自定义渲染器 custom renderer
vue官方实现的 createApp 会给我们的 template 映射生成 html 代码,但是要是你不想渲染生成到 html ,而是要渲染生成到 canvas 之类的不是html的代码的时候,那就需要用到 Custom Renderer API 来定义自己的 render 渲染生成函数了。
在vue3中将渲染器的创建函数 createRenderer 方法单独分离出来,允许用户自定义目标渲染平台,以往的版本中目标渲染被局限于浏览器dom平台,而现在可以把 vue 的开发模型扩展到其他平台(Canvas、iOS、Android等等)。
三、Vue3.0 非兼容性变更
1. Global API改为应用程序实例调用
Vue2.0 中有很多全局api可以改变vue的行为,比如Vue.component等。这会导致一些问题:
- Vue2没有app的概念,new Vue() 得到的根实例被作为app,这样的话所有创建的根实例是共享相同的全局配置,这在测试时会污染其他测试用例,导致测试变得很困难。
- 全局配置也导致没有办法在单页面创建不同全局配置的多个app实例。
Vue3.0中使用createApp返回app实例,由它暴露一系列全局api
列举如下:
2.x Global API | 3.x Instance API (app) |
---|---|
Vue.config | app.config |
Vue.config.productionTip | removed |
Vue.config.ignoredElements | app.config.isCustomElement |
Vue.component | app.component |
Vue.directive | app.directive |
Vue.mixin | app.mixin |
Vue.use | app.use |
Vue.filter | removed |
2. Global and internal API重构为可做摇树优化
Vue2.0中不少global-api是作为静态函数直接挂在构造函数上的,例如Vue.nextTick(),如果我们从未在代码中用过它们,就会形成所谓的dead code,这类global-api造成的dead code无法使用webpack的tree-shaking排除掉。
Vue3中做了相应的变化,将它们抽取成为独立函数,这样打包工具的摇树优化可以将这些dead code排除掉。
受影响的api:
- Vue.nextTick
- Vue.observable(replaced by Vue.reactive)
- Vue.version
- Vue.compile(only in full builds)
- Vue.set(only in compat builds)
- Vue.delete(only in compat builds)
3. v-model 变更
- 用于自定义组件时,v-model prop和事件默认名称更改
prop:value -> modelValue;
event:input -> update:modelValue; - v-bind 的 .sync 修饰符和组件的 model 选项已移除,可用 v-model 作为代替
- 同一个组件上可以使用多个v-model进行双向绑定
- 可以自定义v-model修饰符
1.不带参数的v-model绑定,修饰符将通过 prop 名称
modelModifiers 提供给子组件
2.带参数的 v-model 绑定,修饰符将通过 prop 名称
arg + “Modifiers“ 提供给子组件
4. 渲染函数变更
4.1 渲染函数API变更
此更改不会影响到<template>
用户
- h现在全局导入,而非作为参数传递给渲染函数
- 渲染函数参数更改为在有状态组件和函数组件之间更加一致
- vnode现在又一个扁平的prop结构
4.1.1 render函数参数
4.1.2 render函数签名更改
4.1.3 Vnode参数格式
4.2 slot统一
更改了普通slot和作用域slot
- this.$slots现在将slots作为函数公开
- 移除this.$scopedSlots
4.3 移除$listeners
$listeners 对象在vue3中已经移除,现在事件监听器是 $attrs 的一部分
- vue2中,可以使用 this. a t t r s 和 t h i s . attrs 和 this. attrs和this.listeners 分别访问传递给组件的attribute和事件监听器,结合inheritAttrs: false,开发者可以将这些attribute和监听器应用到其他元素,而不是根元素。
- vue3中,事件监听器现在只是以on为前缀的attribute,这样就成了attrs对象的一部分,listeners被移除了
4.4 $attrs包括class和style
现在的 $attr
包含所有的 attribute,包括 class 和 style
在vue2中,虚拟dom会对class和style进行特殊处理,所以他们不包括在$attr中,在使用 inheritAttr: false 的时候会产生副作用
$attrs 中的 attribute 不再自动添加到根元素中,而是由开发者决定在哪添加,但是 class 和 style 不属于 $attrs,仍然会应用到组件的根元素。
5. 函数式组件变更
- Vue 3 中函数式组件的性能提升微乎其微(与 Vue 2.x 相比),所以vue3中建议直接使用常规组件
- 如果想创建一个函数式组件,写一个接收 props 和 context 的普通函数就可以了
- 废弃:单文件组件(SFC)中 的 functional 属性被干掉了
- 废弃:通过给 Render 函数传递 { functional: true } 以创建函数式组件的方式也被废弃了
6. 异步组件变更
- 新增了一个方法:defineAsyncComponent,用来显式地定义异步组件
- component 选项改名:loader
- Loader 函数不再接受 resolve 和 reject 作为参数,并且必须返回一个 Promise
7. data选项变更
- data 组件选项声明不再接收纯 JavaScript object,而需要 function 声明
- 当合并来自 mixin 或 extend 的多个 data 返回值时,现在是浅层次合并的而不是深层次合并的(只合并根级属性)
8. 自定义组件白名单
Vue3中自定义元素检测发生在模板编译时,如果要添加一些vue之外的自定义元素(例如通过 Web Components API定义的自定义元素),需要在编译器选项中设置 isCustomElement 选项。如果组件匹配了这个条件,就不需要本地或全局注册,Vue也不会抛出 unknown custom element 的警告。
- 使用 vue-cli 构建时,模板都会用 vue-loader 预编译,在 vue.config.js 中设置compilerOptions 即可:
- 使用 vite 构建时,在 vite.config.js 中配置 vueCompilerOptions 即可:
- 如果是采⽤的运⾏时编译版本的vue,可通过全局配置isCustomElement
9. is属性变更
vue2中 is 可用在两个场景下:
- 用于动态组件 component 来切换要渲染的组件
- 用于在使用DOM模板时的一些HTML元素的限制,比如 ui 元素里只能出现 li 元素,这样当 ul 里使用自定义组件时浏览器会认为是无效内容,此时可以使用 is 属性
Vue3 中 is 只能用在 component 上,上述功能需要使用 v-is 来代替
10. 插槽变更(同4.2)
Vue3中统一普通插槽和作用域插槽到$slots,具体变化如下:
- 插槽均以函数形式暴露
- $scopedSlots移除
11. 自定义指令API和组件保持一致
Vue3中指令api和组件保持一致
- created - 新的!在元素的 attribute 或事件侦听器应用之前调用。
- bind → beforeMount
- inserted → mounted
- beforeUpdate:新的!这是在元素本身更新之前调用的,很像组件生命周期钩子。
- update → 移除!有太多的相似之处要更新,所以这是多余的,请改用 updated。
- componentUpdated → updated
- beforeUnmount:新的!与组件生命周期钩子类似,它将在卸载元素之前调用。
- unbind -> unmounted
12. transition类名变更
- v–enter -> v-enter-from
- v–leave -> v-leave-from
13. watch变更
- 以 .分割的表达式不再被watch和 w a t c h 支 持 , 可 以 使 用 一 个 计 算 函 数 作 为 w a t c h 和 watch支持,可以使用一个计算函数作为watch和 watch支持,可以使用一个计算函数作为watch和watch的参数实现
- 新增watchEffect,俗称函数副作用。(见1.7)
14. 被挂载的应用不会替换元素
- 在 Vue 2.x 中,当挂载一个具有 template 的应用时,被渲染的内容会替换我们要挂载的目标元素。
- 在 Vue 3.x 中,被渲染的应用会作为子元素插入,从而替换目标元素的 innerHTML
四、Vue3.0 移除功能
1. keyCode 作为 v-on 修饰符被移除
vue2中可以使⽤keyCode指代某个按键,vue3不再⽀持。
2. o n , on, on,off 和 $once 实例方法已被移除
这3个方法被认为不应该由vue提供,因此被移除了,可以使用其他三方库实现(如Event bus 模式可以被替换为实现了事件触发器接口的外部库mitt、tiny-emitter)。
3. filter移除
Vue3中移除了过滤器,建议用方法调用或计算属性替换。
4. 内联模板attribute移除
5 $children 实例 property移除
子组件实例建议使用$refs访问
6 propsData 选项移除
propsData 选项之前用于在创建 Vue 实例的过程中传入 prop,现在它被移除了。如果想为 Vue 3 应用的根组件传入 prop,请使用 createApp 的第二个参数。