本文最后更新于:2020年5月3日 凌晨
                
              
            
            
              前言
尤大大前段时间发布了vue3.0-beta版本,现在趁着五一假期尝尝鲜,记录一下。
vue3设计更新点
先回顾官方提出的vue3.0设计目标
- 更小
- 全局 API 和内置组件
- 支持 tree-shaking
- 常驻代码大小控制在 10kb gzipped 左右
 
- 更快
- 基于 Proxy 的变动侦测
- Virtual DOM 重构
- 编译器架构重构,更多的编译时优化
 
- 加强API设计一致性
- 加强TypeScript支持
- 提高自身可维护性
- 代码采用 monorepo 结构,内部分层更清晰
- TypeScript 使得外部贡献者更有信心做改动
 
- 开放更多底层功能
开始
创建项目
| 12
 3
 4
 5
 6
 7
 8
 
 | cnpm install -g @vue/cli
 
 
 vue create vue-3.0-beta-test
 
 
 vue add vue-next
 
 | 
然后打开项目,可以看到vue的版本已经变成^3.0.0-beta.1,还有一些插件版本的更新和新增了两个插件

对比项目结构
再从项目的整体结构来看,对比2.x版本基本没有变化,主要看下变化了的main.js文件

通过图片可以看到,这里只解构出一个createApp函数,因为vue3.0支持tree-shaking,可以把每一个用到的API抽取出来,让vue变得更小
Composition API
原先是叫Vue-Function-API,后面经社区意见收集,更改为Vue-Composition-API,这里面有几个变化比较大的:
- 生命周期钩子
- reactive API
- ref API
- watch API
- computed API
生命周期
在3.0中,生命周期发生了很大变化:
| 2.x | 3.0 | 
| beforeCreate | setup | 
| created | setup | 
| beforeMount | onBeforeMount | 
| mounted | onMounted | 
| beforeUpdate | onBeforeUpdate | 
| updated | onUpdated | 
| beforeDestroy | onBeforeUnmount | 
| destroyed | onUnmounted | 
reactive
该API作用是创建响应式对象,类似之前在data中声明变量
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | // App.vue<template>
 <div id="app">
 <img alt="Vue logo" src="./assets/logo.png" />
 <h3>{{ info.msg }}</h3>
 </div>
 </template>
 
 <script>
 import { reactive } from "vue";
 export default {
 name: "App",
 setup() {
 let info = reactive({
 msg: `vue3.0-beta尝鲜`
 });
 return {
 info
 };
 }
 };
 </script>
 
 | 
效果:

ref
创建一个包装式对象,含有一个响应式属性value,通过修改value来修改值
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 
 | // App.vue<template>
 <div id="app">
 <img alt="Vue logo" src="./assets/logo.png" />
 <h3>{{ info.msg }}</h3>
 <h3>{{ tip }}</h3>
 </div>
 </template>
 
 <script>
 import { reactive, ref } from "vue";
 export default {
 name: "App",
 setup() {
 let info = reactive({
 msg: `vue3.0-beta尝鲜`
 });
 let tip = ref(`value of ref`);
 // 通过修改value属性来修改值
 tip.value = `change ref of value`;
 return {
 info,
 tip
 };
 }
 };
 </script>
 
 | 
效果:

事件处理
3.0没有methods对象,也是写在setup里面
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 
 | // App.vue<template>
 <div id="app">
 <img alt="Vue logo" src="./assets/logo.png" />
 <h3>{{ info.msg }}</h3>
 <h3>tip:{{ tip }}</h3>
 <input v-model="inputValue" />
 <button @click="handleClick">click me</button>
 </div>
 </template>
 
 <script>
 import { reactive, ref } from "vue";
 export default {
 name: "App",
 setup() {
 let info = reactive({
 msg: `vue3.0-beta尝鲜`
 });
 let tip = ref(`value of ref`);
 tip.value = `change ref of value`;
 let inputValue = ref("");
 const handleClick = () => {
 tip.value = inputValue.value;
 };
 return {
 info,
 tip,
 inputValue,
 handleClick
 };
 }
 };
 </script>
 
 | 
上面写了一个方法,绑定一个点击事件来改变变量tip的值,效果如图:

onMounted钩子
我们在vue项目中用得最多的生命钩子就是created和mounted,在created发送请求,接收、处理参数之类,在mounted页面渲染后进行相关的业务处理,在上面有提过,现在beforeCreate和created 都是setup了,现在看下新的onMounted怎么用:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 
 | <template><div id="app">
 <img alt="Vue logo" src="./assets/logo.png" />
 <h3>{{ info.msg }}</h3>
 <h3>tip:{{ tip }}</h3>
 <input v-model="inputValue" />
 <button @click="handleClick">click me</button>
 </div>
 </template>
 
 <script>
 import { reactive, ref, onMounted } from "vue";
 export default {
 name: "App",
 setup() {
 // 省略上面例子的代码
 // ...
 onMounted(() => {
 console.log(`mounted`);
 // 页面渲染完 获取所有h3元素
 let h3List = document.querySelectorAll("h3");
 console.log({
 h3List: h3List
 });
 });
 return {
 // ...
 };
 }
 };
 </script>
 
 
 | 
computed
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 
 | <template><div id="app">
 <img alt="Vue logo" src="./assets/logo.png" />
 <h3>{{ info.msg }}</h3>
 <h3>tip:{{ tip }}</h3>
 <h3>computed num:{{ num }}</h3>
 <input v-model="inputValue" />
 <button @click="handleClick">click me</button>
 <button @click="incrementNum">increment</button>
 </div>
 </template>
 
 <script>
 import { reactive, ref, onMounted, computed } from "vue";
 export default {
 name: "App",
 setup() {
 // ...
 let initNum = ref(0);
 const incrementNum = () => {
 initNum.value++;
 };
 // 让num成为计算属性
 let num = computed(() => {
 return initNum.value * 2;
 });
 return {
 // ...
 incrementNum,
 num
 };
 }
 };
 </script>
 
 
 | 
看下效果:

总结
从上面的例子可以看到,3.0的语法更加简洁精炼!总的来说,3.0会兼容2.x,我们的学习成本基本就只集中在composition这一块,而更具体、更详细的内容,可访问composition-api,上面还有很丰富的内容等着我们探索,包括对TypeScript的更好支持等。