Vue 团队于 2020 年 9 月 18 日晚 11 点半发布了 Vue 3.0 版本
本次主版本更新包含性能的改进,更小的 bundle 体积,对 TypeScript 更好的支持,用于处理大规模用例的全新 API
1. vue3.0相比2.0产生的变化,新特性
- performance-性能
- 使update性能得到很大提高,提高1.3~2倍(为了提高性能,作者相当于将vue重写了一遍,推翻上一个版本并且兼容上个版本)
- SSR速度提高了2~3倍
- 最主要的是重写了虚拟Dom的实现,主要思路是跳过了静态节点,只处理动态节点
- Tree shaking-精简无用代码
将按需打包融入到vue3.0中,用到什么打包什么,将没用的模块剪掉,最终打包出来的项目体积比较小
- Fragment-碎片
vue2中创建template根节点时,只允许创建1个,用div包裹起来,无形中让整个页面的html层级加深。 vue3可以直接在template标签里写多个节点。
- TypeScript
vue3.0之后底层都是基于TS写的,使用TS的好处是在大型项目开发,TS能有效的管控代码的编程感。不过在vue3中不使用TS也没问题。
- Composition API (对于应用来说,是最需要了解的)
组合式API,替换原有的Options API
- 根据逻辑相关性组织代码,提高可读性和可维护性
- 更好的重用逻辑代码(避免mixins混入时命名冲突的问题)
依然可以延用 Options [ˈɒpʃnz] API
2.0:
(1)data返回一个函数,包含了响应式数据,实现状态私有化
(2)后续写方法,根据方法的情况,把它写在methods里。写在computed,watch里进行计算属性或监听,
还有筛选放在filters里
(3)会发现项目代码少还好,看着很清晰。如果项目代码很多,会发现这么写不利于代码的可读性以及可维护性
3.0
因此在3.0版本提出了组合式API的概念
(1)在composition API中提供了setup,它是composition API的入口。
(2)将我们要实现的功能,它具体要实现的状态,方法,以及周期函数全部封装到模块下,将封装好的模块
全部导入到setup中,从setup中统一暴露出去,供模版来使用
mixins: 是有缺陷的,简单使用还可以,如果项目比较大,自己要往全局混入,别人也要全局混入,很有可能产生冲突,就比较难搞。
- Proxy
vue2.0 响应式数据基于Object defineProperty,它处理也可以,但存在局限性和不太好的地方。
ES6 为我们提供了Proxy,它在数据劫持方面做的要比Object defineProperty强很多
vue3.0响应式原理不再基于 Object.defineProperty
developer.mozilla.org/zh-CN/docs/…
2. 基于 vue/cli 配置 vue3.0
- 在@vue/cli基础上,通过
vue-cli-plugin-vue-next插件,让脚手架支持vue3.0的应用
$ npm install -g @vue/cli
$ vue --version
$ vue create xxx
$ vue add vue-next
要求cli的版本要高于4.3.1
3. 基于vite配置vue3.0
由 vue 作者尤雨溪开发的 web 开发工具,直接基于这个工具构建的项目就是vue3.0的项目
(非常快,不像webpack需要将所有东西打包编译,编译完再渲染)
- 基于浏览器原生 ES imports 的开发服务器(利用浏览器去解析 imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用)
- 同时不仅有 Vue 文件支持,还搞定了热更新,而且热更新的速度不会随着模块增多而变慢
$ npm init vite-app xxx // 创建项目
$ cd xxx
$ npm install
$ npm run dev
$ npm run build
4. 掌握setup和响应式系统API
vue-composition-api-rfc.netlify.app/zh/api.html
4.1 setup:
setup 函数是一个新的组件选项,作为在组件内使用 Composition API 的入口点
- 初始化属性(props)和beforeCreate之间调用
- 可以接收 props 和 context
- this在setup()中不可用
export default {
props: {
title: String,
},
setup(props) {
// props是基于proxy代理的响应式数据
// 监听props改变,props改变会触发回调函数重新执行
watchEffect(() => {
console.log(`title is: ` + props.title);
});
}
};
props是响应式的,可以基于watchEffect/watch监听,解构赋值后则无效(不再是响应式数据)
components API 放弃data,methods这些方法,所有的一切都通过vue提供的components API ,放在setup中去处理
export default {
props: { title: String },
setup() {
let supNum = 0,
oppNum = 0;
let change = lx => {
lx === 0 ? supNum++ : oppNum++;
};
// return的内容可以直接在模板中渲染使用,但此时数据并不是响应式数据,因此数据也不更新
return {
supNum, oppNum, change
};}};
4.2 构建响应式数据
方法一:ref(一般处理简单值的响应式)
原理:define property监听value值,value改变通知组件重新渲染
接受一个参数值并返回一个响应式且可改变的 ref 对象
- ref 对象拥有一个指向内部值的单一属性 .value
- 当ref在模板中使用的时候,它会自动解套,无需在模板内额外书写 .value
import { ref } from "vue";
export default {
setup() {
let supNum = ref(0),
oppNum = ref(0);
let change = lx => {
lx === 0 ? supNum.value++ : oppNum.value++;
};
return {
supNum,oppNum,change
};
}
};
以上方法存在问题:想用一个响应式数据就得用ref一次,很麻烦。可以整体变成一个对象
export default {
setup() {
let state = ref({
supNum:0,
oppNum:0
})
let change = lx => {
lx === 0 ? state.value.supNum++ : state.value.oppNum++;
};
return {
state,change
};
}
};
此时change方法也发生了改变,写起来依然很麻烦。
方法二:reactive
基于proxy对数据进行深度监听,以此构建响应式
接收一个普通对象,然后返回该普通对象的响应式代理
等同于2.x的Vue.observable()
- 响应式转换是“深层的”的,会影响对象内部所有嵌套的属性
export default {
setup() {
let state = reactive({
supNum:0,
oppNum:0
})
let change = lx => {
lx === 0 ? state.supNum++ : state.oppNum++;
};
return {
state,change
};
}
};
state()对象的形式在组件内使用需要{{state.supNum}}这么引用,可以通过toRefs方式将reactive中每一项变为ref响应式数据,就可以在组件中直接使用。
此时return返回:...toRefs(state)
4.3 响应式工具集
- isRef:检测是否是ref对象,是返回true,不是返回false
- toRefs:转变为ref响应式数据
- unref:如果参数是一个ref就返回它的value值,不是就返回参数本身。是
val=isRef(val)?val.value:val的语法糖。