本文最后更新于:2022年3月3日 下午
前言
vue3出来已经有很长一段时间了,很快vue官网也将默认上线vue3版本了,特此记录一下自己学习的小成果,比较片面零散,更多的会比较一下常用的api在vue2和vue3中有何异同,同时更推荐大家去看官网文档,写此博客是为了让自己在写的过程中重温一下印象更深刻
基础模板
vue2
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 36 37 38 39 40
| <template> <div >
</div> </template>
<script> export default { name: 'xxx', data() { return { //数据 } }, beforeCreate(){}, created(){}, beforeMount(){}, mounted() {}, beforeUpdate(){}, updated(){}, beforeDestroy(){}, destroyed(){}, methods: { //方法 } } </script>
<style lang="scss" scoped>
</style>
|
vue3
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 36 37 38 39 40 41 42 43 44 45 46
| <template> <div>
</div> </template>
<script>
import { reactive, toRefs,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted } from 'vue'
export default { setup () { const state = reactive({ count: 0, }); onBeforeMount(() => { console.log("onBeforeMount"); }); onMounted(() => { console.log("onMounted"); }); onBeforeUpdate(() => { console.log("onBeforeUpdate1"); }); onUpdated(() => { console.log("onUpdated"); }); onBeforeUnmount(() => { console.log("onBeforeUnmount"); }); onUnmounted(() => { console.log("onUnmounted"); }); return { ...toRefs(state), } } } </script>
<style lang="scss" scoped>
</style>
|
如上,单从代码上来看我们不难看出vue3相比vue2,多出了一个setup(),以及少了两生命周期钩子,最大的不同则是vue3使用的组合式API(composition API),下面谈谈这二者的异同
生命周期的变化
| vue2 |
vue3 |
| beforeCreate |
包含在setup() |
| created |
包含在setup() |
| beforeMount |
onBeforeMount |
| mounted() |
onMounted() |
| beforeUpdate |
onBeforeUpdate |
| update |
onUpdate |
| beforeDestroy |
onBeforeUnmount |
| destroyed |
onUnmounted |
如上所列,在vue2中的beforeCreate和created两个生命周期钩子函数在vue3中是不需要了,用官方文档的话说就是:因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。
setup()
setup()函数接收两个参数,分别是prop和context,官方说明:`setup 函数中的第一个参数是 props。正如在一个标准组件中所期望的那样,setup 函数中的 props 是响应式的,当传入新的 prop 时,它将被更新。
prop
1 2 3 4 5 6 7 8
| export default { props: { title: String }, setup(props) { console.log(props.title) } }
|
但是,因为 props 是响应式的,你不能使用 ES6 解构,它会消除 prop 的响应性。
如果需要解构 prop,可以在 setup 函数中使用 toRefs 函数来完成此操作:
1 2 3 4 5 6 7
| import { toRefs } from 'vue'
setup(props) { const { title } = toRefs(props)
console.log(title.value) }
|
如果 title 是可选的 prop,则传入的 props 中可能没有 title 。在这种情况下,toRefs 将不会为 title 创建一个 ref 。你需要使用 toRef 替代它:
1 2 3 4 5
| import { toRef } from 'vue' setup(props) { const title = toRef(props, 'title') console.log(title.value) }
|
context
传递给 setup 函数的第二个参数是 context。context 是一个普通 JavaScript 对象,暴露了其它可能在 setup 中有用的值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| export default { setup(props, context) { console.log(context.attrs)
console.log(context.slots)
console.log(context.emit)
console.log(context.expose) } }
|
context 是一个普通的 JavaScript 对象,也就是说,它不是响应式的,这意味着你可以安全地对 context 使用 ES6 解构。
1 2 3 4 5
| export default { setup(props, { attrs, slots, emit, expose }) { ... } }
|
attrs 和 slots 是有状态的对象,它们总是会随组件本身的更新而更新。这意味着你应该避免对它们进行解构,并始终以 attrs.x 或 slots.x 的方式引用 property。请注意,与 props 不同,attrs 和 slots 的 property 是非响应式的。如果你打算根据 attrs 或 slots 的更改应用副作用,那么应该在 onBeforeUpdate 生命周期钩子中执行此操作。
在 setup 中你应该避免使用 this,因为它不会找到组件实例。setup 的调用发生在 data property、computed property 或 methods 被解析之前,所以它们无法在 setup 中被获取。
setup这一节官方文档言简意赅,我直接发挥cv工程师的技能copy😂
响应式数据
vue的最大特性之一便是响应式数据,在vue2中响应式的实现原理是通过Object.defineProperty()去实现的,其最低支持到ie8,而vue3则是使用ES6的proxy实现响应式,因此并不兼容ie,所以如果你的项目是需要兼容到ie的,那你只能使用vue2或者让客户换个浏览器了(难以实现)😀
vue2中响应式
我们在使用vue2时,通常是把需要响应的数据放在data(){}中,如下所示,通过this.dataA,this.dataB去实现对响应式数据的修改或赋值,vue3与此对比可以说使用方式是大不相同
1 2 3 4 5 6 7 8 9 10
| <script> export default{ data(){ return{ dataA:'响应数据1', dataB:'响应数据2' } } } </script>
|
vue3响应式
在vue3中,提供了两种方式实现响应式,一个是ref,一个是reactive
ref
接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值。也就是说,一个普通变量使用ref()使其成为响应式变量,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <script> import {ref} from "vue" export default{ setup(){ let count = ref(0) console.log(count.value) count.value++ console.log(count.value) return{ count, } } } </script>
|
通常我们定义基础类型的响应式会使用ref(),引用类型则使用下面的reactive
reactive
返回对象的响应式副本
computed的使用
在vue2中
直接上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <template> <div> <span>{{name}}</span> </div> </template>
<script> export default{ computed:{ name(){ return this.xxx+this.xxx } }, methods:{ myName(){ console.log(this.name) } } } </script>
|
在vue3中
该方法可以传入一个函数,默认该函数就是getter,不管getter返回值为一个ref响应式数据还是一个普通变量,数据都是只读不能改变。
1 2 3 4 5 6 7 8 9 10 11
| <script> import { ref, computed } from "vue" export default { name: 'test', setup() { let name = ref("凡夫") let test = computed(() => name.value); test.value = "123" } } </script>
|
如果想要修改,传入一个对象set和get函数方法,这样就可以了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <script> import { ref, computed } from "vue" export default { name: 'test', setup() { let name = ref("凡夫") let test = computed({ get() { return name.value; }, set(val) { return name.value = val; } }); test.value = "123" } } </script>
|
watch的使用
store的使用
router的使用