1、vue3与vue2的区别
- 源码采用monorepo方式进行管理,将模块拆分到package目录中(是管理项目代码的一个方式,指在一个项目仓库(repo)中管理多个模块/包package,调用方便,但是体积大)
- vue3采用了ts开发,增强类型检测,vue2则采用了flow
- vue3的性能优化,支持tree-shaking,不使用则不打包
- vue2后期引入RFC,使每个版本改动可控rfcs
2、vue3.0的安装
npm install -g @vue/cli@next //对原有项目的升级 vue upgrade --next
升级后可以用vue ui进行vue3项目的创建
3、vue创建实例的区别
vue3与vue2的区别大致会编写在gitbub上的vuejs/rcfs
<script> // let app = new Vue({ // template: '<div>{{content}}</div>', // data: { // content: 'abc' // } // }) // let vm = app.$mount('#root') // console.log(app, vm) //两者都返回vue实例 let app = Vue.createApp({ template: '<div>{{content}}</div>', data() { //注意:这里用的是一个函数,与版本2是有区别的 return { content: 'abc' } }, setup() { const test = () => { console.log('yes') } return { test } } }) let vm = app.mount('#root') console.log(app, vm) //前者返回实例后者返回代码的数据对象 </script>
注意:前者的app与vm返回的都是vue实例,而后者进行的区别,app返回的是vue的实例,而vm返回的是数据的代理
4、vue3的生命周期函数的变量
vue3相对于vue2生命周期函数作了一些调号,把原来的beforeDestroy, destroyed替换成了beforeUnmount与unmounted两个函数,功能不变,同时在vue的实例中,把destroy方法改成了 unmount方法,实现不挂载
let app = Vue.createApp({ template: '<div @click="test">{{content}}</div>', data() { return { content: 'abc' } }, setup(proxy) { const test = () => { console.log(app, vm) } return { test } }, beforeUnmount() { //表示当Vue失效前,自动执行的函数 console.log('beforeUnmount') }, unmounted() { //表示当Vue应用失效时,且dom完全销毁之后,自动执行的函数 console.log('unmounted') } }) let vm = app.mount('#root')
5、数据响应的调整
在vue2时数据值的变化不能通过key值的形式直接赋值,但是vue3底层用proxy的原理来实现,可以使用key值的形式更改
let app = Vue.createApp({ template: '<div @click="test">{{content}} <span v-for="(val, ind) of list" :key="ind">{{val}}</span></div>', data() { return { content: 'abc', list: ['aa', 'bb'] } }, methods: { test() { this.list[0] = 'cc' } } }) let vm = app.mount('#root')
注意: 在vue的新版本里面,可以直接添加对象,通过key的方式添加,而在vue2里面,只能通过$set才能实现,在vue3中,v-if的优先级要低于v-for这点要区别于vue2
6、事件响应
通常来讲vue的事件中,在没有传参的情况下,第一个参数默认是event,但是如果遇到传参又想获取event对象,那么这个时候就需要手动传一个参数$event
let app = Vue.createApp({ template: `<div @click="test('yes', $event)">{{content}}</div>`, data() { return { content: 'abc' } }, methods: { test() { console.log(arguments) } } }) let vm = app.mount('#root')
如果一个事件需要绑定两个及以上的事件,那么可以按以下的写法
let app = Vue.createApp({ template: `<div @click="test('yes', $event), test2()">{{content}}</div>`, //注意这里的函数需要采用调用模式 data() { return { content: 'abc' } }, methods: { test() { console.log(arguments) }, test2() { console.log('test2', arguments) } } }) let vm = app.mount('#root')
.native
修饰符在 Vue 3.x 已经移除掉了。取而代之的是,在新增的 emits
选项中定义当前组件真正触发的事件(即,组件事件)。此外,Vue 现在将所有未在组件emits
选项中定义的事件作为原生事件添加到子组件的根元素中(除非子组件选项中设置了 inheritAttrs: false
)
<template> <div> <button v-on:click="$emit('click')">click</button> <button v-on:click="$emit('close')">close</button> </div> </template> <script> export default { emits: ['close'] } </script>
上面代码的执行结果是:click
事件会被自动添加到<div>
中,所以当子组件被点击时,就会触发click
事件。
<template> <div> <button v-on:click="$emit('click')">click</button> <button v-on:click="$emit('close')">close</button> </div> </template> <script> export default { emits: ['close', 'click'] } </script>
则click
事件不会被添加给<div>
。强烈建议组件中使用的所有通过emit
触发的event
都在emits
中声明。
7、组件.sync的调整
通常来讲在vue2.0版本,如果需要在子集中修改父级的值,那么在传入的时候用修饰值.sync,并且在方法内部调用this.$emit('update:key值', value)可以实现修改,但是vue3作了一些修改,用v-model替代。sync语法
let Check = { props: ['message'], template: `<div>this is check --- {{message}}</div><button @click='change'>点击</button>`, methods: { change() { this.$emit('update:message', 'haha') } } } let app = Vue.createApp({ template: `<div><div @click="test('yes', $event)">{{content}}</div> <Check v-model:message='content' /></div>`, components: { Check }, data() { return { content: 'abc' } }, methods: { test() { console.log(arguments) } } }) let vm = app.mount('#root')
注意:在使用v-model的时候有几个注意点,在处理表单的时候v-model后面可以加修饰符,如.lazy .number .trim但是在组件中使用v-model的时候也可以使用类似的修饰符,并且这些修饰符可以自定义,但是如果指定字段就不可以使用修饰符了:如v-model:msg='msg'就不能使用修饰符了
let Check = { template: `<div><div>{{modelValue}}</div><button @click='clickEvent'>点击</button></div>`, props: { modelValue: { // 默认v-model的值的接收要用到modelValue type: String }, modelModifiers: { //接收v-model的修饰符的,以便后面做逻辑处理 default: () => ({}) } }, methods: { clickEvent() { console.log(this.modelModifiers) this.$emit('update:modelValue', ' yes ') } } } let app = Vue.createApp({ template: `<div class='container'> <h1>this is app</h1> <Check v-model.check='msg' /> </div>`, components: { Check }, data() { return { msg: 'are you ok???' } } }) let vm = app.mount('#root')
8、ref的用法提升
在vue2版本中,ref不仅可以获得常规的dom元素,同时也可以获取所对应的组件,但是在vue3中作了一些调整,不仅可以挂载单个元素,同时也可以挂载多个元素集,具体如下
let Check = { template: `<div>this is check</div>`, } let app = Vue.createApp({ template: `<div><div @click="test('yes', $event)">{{content}}</div> <div :ref='setRefs'>haha</div></div>`, components: { Check }, data() { return { content: 'abc', // elem: [], elem: '' } }, methods: { setRefs(el) { // this.elem.push(el) this.elem = el }, test() { console.log(arguments) console.log(this.elem) } } }) let vm = app.mount('#root')
注意:以上可以是字符,数组,还可以是对象
9、slot的写法的调整
let Test = { template: `<div class='testContainer'> <slot name='header'>header</slot> <div>this is content</div> <slot name='footer'>footer</slot> </div>` } let app = Vue.createApp({ template: `<div class='container'> <Test> <template v-slot:header><div>1111</div></template> <template #footer><div>2222</div></template></Test> </div>`, components: { Test } }) let vm = app.mount('#root')
注意:在编写slot的时候,外面调用需要套一层template,并且里面的具名需要用v-slot:*** 简写 #***
slot值的回传
let Test = { template: `<div class='testContainer'> <slot name='header' :list='list'></slot> </div>`, data() { return { list: ['aa', 'bb', 'cc'] } } } let app = Vue.createApp({ template: `<div class='container'> <div id='abc'></div> <Test> <template v-slot:header='{list}'><div>{{list}}</div></template> </Test> </div>`, components: { Test } }) let vm = app.mount('#root')