本文最后更新于:2020年5月3日 凌晨
前言
尤大大前段时间发布了vue3.0-beta版本,现在趁着五一假期尝尝鲜,记录一下。
vue3设计更新点
先回顾官方提出的vue3.0设计目标
- 更小
- 全局 API 和内置组件
- 支持 tree-shaking
- 常驻代码大小控制在 10kb gzipped 左右
- 更快
- 基于 Proxy 的变动侦测
- Virtual DOM 重构
- 编译器架构重构,更多的编译时优化
- 加强API设计一致性
- 加强TypeScript支持
- 提高自身可维护性
- 代码采用 monorepo 结构,内部分层更清晰
- TypeScript 使得外部贡献者更有信心做改动
- 开放更多底层功能
开始
创建项目
1 2 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
中声明变量
1 2 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来修改值
1 2 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
里面
1 2 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
怎么用:
1 2 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
1 2 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
的更好支持等。