vue2与vue3对比

创建实例

  • vue2 :引入vue构造函数,主要依靠render( (creatElement) => {})创建app实例对象

    //引入vue
    import Vue from 'vue'
    //引入App
    import App from './App.vue'
    
    //创建vm
    new Vue({
      el:'#app',
      render: *h* *=>* h(App),
      router:router
    })//.$mount('#app')
    
  • vue3:按需引入,直接用引入的createApp创建实例对象

    //引入的不再是vue构造函数,而是叫createApp的工厂函数
    import { createApp } from 'vue'
    import App from './App.vue'
    
    //创建应用实例对象-app(类似于v2中的vm,但app比vm更轻)并挂载
    createApp(App).mount('#app')
    

vue2与vue3对比_第1张图片

响应式原理

  • Vue2:

    实现原理:

    • 对象类型:通过Object.definrProperty()对属性的读取、修改进行拦截(数据劫持)。
    • 数组类型:通过重写更新数组的一系列方法来实现拦截。(对数组的变更方法进行了包裹)

    存在的问题:

    • 新增属性、删除属性,界面不会更新

      新增属性:this.person.sex=‘女’ 界面不更新的,如果想让它自动更新 那么需要写成如下:

      this.$set(this.person,‘sex’,‘女’) 或者 引入Vue,然后 Vue.set(this.person,‘sex’,‘女’)

      删除属性:delete this.person.sex 属性可以删除,界面不更新,也是需要改变写法:

      this.$delete(this.person,‘sex’) 或者 引入Vue, Vue.delete(this.person,‘sex’)

    • 直接通过更改下标修改数组,界面不会自动更新

      修改数组同理:this.person.hobby[0]=‘学习’ ,不更新,同样的方法:

      this.$set(this.person.hobby,0,‘学习’) 或者 引入Vue,然后 Vue.set(this.person.hobby,0,‘学习’) 或者 this.person.hobby.splice(0,1,‘学习’)

    模拟Vue2响应式实现原理:

    /* let p = {}
    			Object.defineProperty(p,'name',{
    				configurable:true,
    				get(){ //有人读取name时调用
    					return person.name
    				},
    				set(value){ //有人修改name时调用
    					console.log('有人修改了name属性,我发现了,我要去更新界面!')
    					person.name = value
    				}
    			})
    			Object.defineProperty(p,'age',{
    				get(){ //有人读取age时调用
    					return person.age
    				},
    				set(value){ //有人修改age时调用
    					console.log('有人修改了age属性,我发现了,我要去更新界面!')
    					person.age = value
    				}
    			}) 
    
  • Vue3:

    实现原理:

    • 通过Proxy(代理):拦截对象中任意属性的变化,包括增删改查
    • 通过Reflect(反射):对源对象的属性进行操作

    模拟Vue3响应式实现原理:

    const p = new Proxy(person,{
    				//有人读取p的某个属性时调用
    				get(target,propName){
    					console.log(`有人读取了p身上的${propName}属性`)
    					return Reflect.get(target,propName)
    				},
    				//有人修改p的某个属性、或给p追加某个属性时调用
    				set(target,propName,value){
    					console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`)
    					Reflect.set(target,propName,value)
    				},
    				//有人删除p的某个属性时调用
    				deleteProperty(target,propName){
    					console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`)
    					return Reflect.deleteProperty(target,propName)
    				}
    			})
    

一个小知识:如果我们用Object.defineProperty去给一个对象添加属性,如果重复添加,那么代码就会直接崩了;然而用映射Reflect.defineProperty去添加,不会报错,只是通过返回值true或者false来告诉是否操作成功,后面的代码依然能继续执行

生命周期函数

  • vue2:

    1. 有了Vue实例对象就先beforeCreate
    2. created完之后去判断有没有绑定根组件,有没有template模板,如果有就继续走挂载流程beforeMount和mouted,如果没有就停滞了,等到$mount()了再走
    3. 组件销毁要走beforeDistroy和distroyed
  • vue3:

    1. 创建实例对象之前就要去检查有没有创建const app = createApp(App),有没有挂载app.mount(’#app’),如果都符合,这时候才开始创建实例对象

    2. 后面就无需再去判断挂载了,创建完直接判断有没有template模板就进入挂载流程

    3. 组件不销毁了,变成了卸载beforeUnmount和unmounted

    4. .Vue3.0也提供了Composition API形式的生命周期钩子,与Vue2.x中钩子对应关系如下:

      如果要用组合式API,是需要import引入的。也就是挂载、更新、卸载的钩子前都加一个on

      • beforeCreate===>setup()

      • created =======> setup()

        如果把beforeCreate当作一个配置项写,那么setup的执行是先于beforeCreate的,但是如果想把它当成组合式API写进setup里,则setup里没有这两个API

      • beforeMount ===> onBeforeMount

      • mounted =======> onMounted

      • beforeUpdate===> onBeforeUpdate

      • updated =======> onUpdated

      • beforeUnmount ==> onBeforeUnmount

      • unmounted =====> onUnmounted

全局API的转移


  • Vue 2.x有许多全局API和配置。
    例如:注册全局组件、注册全局指令等。

    //注册全局组件
    Vue.component('MyButton', {
    	data: () => ({
    	count: 0
    	}),
    	template: ' 
    })
    //注册全局指令
    Vue.directive('focus', {
    	inserted: el => el.focus()
    }
    
  • Vue3中对这些API做出了调整,将全局的API调整到应用实例app上

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rin2E2EN-1650199822736)(E:\markdown\前端\csdn\20220416_1.png)]

API风格的改变

  • vue2 Options API(选项式API)存在的问题:

    使用传统的Options API时,新增或者修改一个需求,就需要分别在data、methods、computed、watch等里面不断地寻找、修改。如果代码量大的时候,修改起来就很痛苦。

  • vue3中 Composition API(组合式API)的优势:

    更加优雅的组织我们的代码、函数,让相关功能的代码更加有序的组织在一起,都写在setup里面。甚至可以把他们都变成一个个hook函数,修改那部分就可以直接去对应的文件里修改。把定义数据、方法这部分也添加了模块化封装的思想


根标签

  • vue2中组件必须有一个根标签
  • Vue3中组件可以没有根标签,内部会自动将多个标签包含在一个Fragment虚拟元素中。

较常用的其他改变

  • data选项应始终被声明为一个函数

  • 过度类名的更改,就是在开始的那个位置上加了一个-from

    • Vue2.x写法
    .v-enter,
    .v-leave-to {
    	opacity: 0;
    }
    .v-leave,
    .v-enter-to {
    	opacity: 1;
    }
    
    • Vue3.x写法
    v-enter-from, 
    .v-leave-to {
    	opacity: e;
    }
    .v-leave-from,
    .v-enter-to {
    	opacity: 1;
    }
    
  • 移除了keyCode作为v-on的修饰符,同时也不支持config.keyCodes了(自定义按键别名,别名的定义也是依赖keyCode的,所以一并移除了)

  • 移除了v-on.native修饰符

    父组件中绑定事件:

    
    

    子组件中声明自定义事件:子组件emits里面接收的就是自定义事件,不接收就默认是原生事件

    
    

上述为讲课中所整理的部分内容,下面再自己去看看官方文档,来总结一些其他的。

从头到尾读文档

1. 创建实例对象
  • vue2:引入Vue,创建一个实例对象并挂载,渲染的时候render函数若存在,则 Vue 构造函数不会从template选项或通过el选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。

    在脚手架中没有render是运行不下去的。因为脚手架里面引入的vue是残缺版的vue。而且我在里面试了,template要搭配el一起使用,而el绑定的标签中写了内容是可以不需要template的。但是有template优先显示template的内容

  • vue3:每个 Vue 应用都是通过 createApp 函数创建一个新的 应用实例,传入根组件,挂载然后渲染

    二者的实例对象的一个对比

    vue2:

vue2与vue3对比_第2张图片

vue3:

vue2与vue3对比_第3张图片

从图上我们可以看出,vue2是一个Vue的实例对象,而vue3是一个经过Proxy数据劫持过的对象,而且里面只有hanler和target两个属性,里面分别包含着其他。vue3看起来更优雅且简洁了。vue2里面的数据等都是经过加工变成_开头的来赋予get和set,数据表面看经过了加工复制,而vue3通过数据劫持直接就加好了get与set。

这部分都是自己分析的,有不对的地方欢迎指正。

2.数据响应式
  • vue2中,data中写的数据都是响应式的,后追加的数据不是响应式的,可以通过数据代理使后添加的数据为响应式。通过getter和setter实现响应式。

    Object.defineProperty(obj2,'x',{
        get(){
            return obj.x
        },
        set(value){
            obj.x = value
        }
    })
    
  • vue3中,只有通过ref()定义的基本类型数据(对象使用ref定义也是响应式的,但这是不规范的)和通过reactive()定义的对象才是响应式的。所以后期直接往对象里添加属性还是响应式的。在组件挂载后才能访问 ref。通过proxy实现响应式。

3.生命周期函数
  • vue2中new了一个Vue(),那么就开始创建了,判断没有绑定el,那就不能走下去进行挂载了。只有绑定了el才可以往下走。

    • 最后两个生命周期函数为销毁:beforeDestroy和destroyed。

    • 生命周期函数的位置和data,methods等平级。

  • vue3中要先判断有没有创建实例对象并绑定,只有都完成了才会开始创建,然后挂载。

    • 最后两个生命周期函数改成了卸载:beforeUnmount和unmounted

    • 官网最新的写法是

你可能感兴趣的:(前端重要知识详解,前端,vue.js)