vue的初始化改了:

// 旧版
let vm = new Vue({
    el: '#app',
    data: {}
})

// 新版,且data必须为function了
createApp({
    data() {
        return {}
    }
}).mount('#app')

常用部分的改动

新增部分:vue3新增的最大亮点就是新加了setup,几乎替代了data,methods,mounted等生命周期,且setup中无法访问this

  • 新增了setup函数,用于减少数据的冗杂。但个人感觉就是把其他地方的数据统一放到了setup中。

    <template>
        <!-- 或者使用$emit给父级传值 -->
        <button @click="$emit('toFather', '传给父级的值')"></button>    
    </template>
    
    import {toRefs, ref} from 'vue'
    export default{
        porps: ['msg', 'obj'],
        // setup接受2个参数
        // props:即上面的props,且因为是响应式,不接受es6的解构,如果希望解构,则使用vue提供的toRefs方法
        // context:
        setup(props, context) {
            // 如果想通过解耦取props的值,则需要用toRefs,如果或者props.msg.value直接取值
            const {obj} = toRefs(props);
            // 通过toRefs方法的数据如果要取值需要.value,这是因为vue3采用了Proxy
            console.log(obj.value);
            
            // 变量声明的方法改变了,
            // 需要通过ref来
            // 且需要在外面import引入ref,
            // 且声明的变量的取值需要xx.value,
            // 且要实现像data中一样暴露声明的变量,需要在setup中return出去
            // 比如:我声明一个变量name,需要用ref,ref中放初始值
            const name = ref('');
            // 如果我想要获取我声明变量的值,则需要:
            console.log(name.value); // ''
            // 如果我想要对外暴露,则需要return出去:
            return {
                name
            }
        }
    }
  • 新增了$attr,它是props的加强版,且包含方法,具体可以看下面:

    参考资料:vue3 组件传值之 props 与 attrs 的区别

    // Father.vue
    <template>
      <div>
        <Son :msg="message" @toFather="getMsgFromSon" @qita="ck" :onQita="ck" @qita2="ck"></Son>
      </div>
    </template>
    
    <script>
      import Son from './Son.vue'
      import {ref} from 'vue'
      export default {
        name: "Father",
        components: {
          Son,
        },
        setup() {
          const message = ref('信息');
          const getMsgFromSon = (val) => {
            console.log(val)
          };
    
          const ck = () => {
            console.log(1)
          };
    
          return {
            message,
            getMsgFromSon,
            ck
          }
        }
      }
    </script>
    
    <style scoped>
    
    </style>
    
    
    
    // Son.vue
    <template>
      <div>
        <span>{{msg}}</span>
        <button @click="clickFn">按钮</button>
        <button @click="onQita2">按钮2</button>
      </div>
    </template>
    
    <script>
      export default {
        name: "Son",
        props: {
          msg: String,
          onQita: Function,
          onQita2: Function
        },
        emits: ['toFather'],
        setup(props, context) {
          const clickFn = () => {
            context.emit('toFather', '传给父级的信息')
          };
          console.log(props.msg)
          console.log(props.onQita)
          console.log(props, context);
          return {
            clickFn
          }
        }
      }
    </script>
    
    <style scoped>
    
    </style>
    • props需要先声明才能取值,attrs不用声明就可以用,attrs是通过setup第二个参数context取的context.attrs.xx

      比如此时props把所有都声明了,那么attrs中就不会出现:

      image-20211012150926756.png

      又比如此时props不声明onQita2,那么attrs中就会出现:

      image-20211012151055963.png

    • props声明过的属性和方法,attrs中不会再出现。

修改部分:

  • 改动了cdn的引入,vue2的引入为<script src="https://unpkg.com/vue"></script>,vue3是<script src="https://unpkg.com/vue@next"></script>
  • 修改了父子组件原本emit和props的通信。

    父级向自己使用props传值,父级写法不变,子级在html中正常使用,但在setup中需要通过props.msg.value取值,或者用toRefs解耦const {msg} = toRefs(props),却取值还是msg.value。

    子级向父级传值,子级中增加emits: ['toFather'],emits中声明了子级调用父级的方法,执行为:context.emit('toFather', '传给父级'),而父级监听子级的传递方式不变。

    具体实现如下:

    // Father.vue
    <template>
      <div>
        <Son :msg="message" @toFather="getMsgFromSon"></Son>
      </div>
    </template>
    
    <script>
      import Son from './Son.vue'
      import {ref} from 'vue'
      export default {
        name: "Father",
        components: {
          Son,
        },
        setup() {
          const message = ref('信息');
          const getMsgFromSon = (val) => {
            console.log(val)
          };
          return {
            message,
            getMsgFromSon,
          }
        }
      }
    </script>
    
    
    
    // Son.vue
    <template>
      <div>
        <span>{{msg}}</span>
        <button @click="clickFn">按钮</button>
        <!-- 或者使用$emit给父级传值 -->
        <button @click="$emit('toFather', '给父级的值')">按钮2</button>
      </div>
    </template>
    
    <script>
      export default {
        name: "Son",
        props: {
          msg: String
        },
        emits: ['toFather'],
        setup(props, context) {
          const clickFn = () => {
            context.emit('toFather', '传给父级的信息')
          };
          console.log(props, context);
          return {
            clickFn
          }
        }
      }
    </script>
  • mixin混淆不再是深层混淆了,现在改为只混淆第一层

    const Mixin = {
        data() {
            return {
                user: {
                    id: 0,
                    name: 1,
                    age: 2
                }
            }
        }
    }
    
    const old = {
        mixins: [Mixin],
        data() {
            return {
                user:{
                    id: 2
                }
            }
        },
        mounted() {
            console.log(this.user); 
        }
    }
    // 旧版:{id:2,name:1,age:2}
    // 新版:{id:2}
  • 全局变量的设置由Vue.prototype.xx改为Vue.config.globalProperties.xx
  • 修改了keyCodes,原本支持键盘码,现在只支持名了:

    // 旧版
    <input @keyup.13="subimit"/>
    
    // 新版:同时匹配q和Q
    <input @keyup.q="quit"/>
    // 匹配pagedown按键
    <input @keyup.page-down="quit"/>
    // 匹配逗号
    <input @keyup.,="quit"/>
    
    // 对于特殊字符"、'、/、=、> 和 .。,通过监听器的event.key实现
  • 插槽统一,统一了普通插槽和作用域插槽,以前:this.$scopedSlots.header,现在:this.$slots.header()
  • v-if和v-for同时在一个元素上,v-if优先,原本v-for优先。
  • v-model改变:

    // 旧版
    // 旧版中v-model是:value和@input的简写,比如
    // 简写
    <Father v-model="title"></Father>
    // 全写
    <Father :value="title" @input="title"></Father>
    
    
    // 新版
    // 父级
    <Father v-model:msg="message"></Father>
    // 子级-父级可以不用设置@update:msg="message = $event"方法,即可实现子级点击后改变父级传入的props.msg.value
    <div>
        <span>{{msg}}</span>
        <button @click="$emit('update:msg', '传给父级的信息')">按钮</button>
    </div>

删除部分

  • 删除了$on$off$once,还有过滤器filters,vue3推荐大家使用computed代替filters
  • 删除了Vue.extend,改为Vue.createApp(),因为两者比较相似:

    // vue2
    // 创建构造器
    const Profile = Vue.extend({
      template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
      data() {
        return {
          firstName: 'Walter',
          lastName: 'White',
          alias: 'Heisenberg'
        }
      }
    })
    // 创建一个 Profile 的实例,并将它挂载到一个元素上
    new Profile().$mount('#mount-point')
    
    
    // vue3
    const Profile = {
      template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
      data() {
        return {
          firstName: 'Walter',
          lastName: 'White',
          alias: 'Heisenberg'
        }
      }
    }
    Vue.createApp(Profile).mount('#mount-point')

咸鱼前端clw
19 声望4 粉丝

只会前端