自学内容网 自学内容网

Vue3和Vue2的区别

根标签


Vue2

  • Templata只支持一个根标签
<template>
  <div></div>
</template>

Vue3

  • Templata支持多个根标签
<template>
  <div></div>
  <img/>
</template>

初始化方法


Vue2

  • 使用 new Vue(), 参数是new Vue({template, render})
import Vue from 'vue';
import router from './routers/';
import store from './stores';
import App from './App.vue';
const app =  new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app');

Vue3

  • 使用 createApp() 参数是 createApp(组件)
import { createApp } from 'vue';
import App from './App.vue';
import { router } from './router';
const app = createApp(App).use(router).mount('#app');

挂载容器


Vue2

  • 可以通过el选项和$mount()方法来挂载容器
new Vue({
el:'容器名字 '
})
new Vue({
}).$mount('容器名字')

Vue3

  • 只能通过mount()方法来挂载容器
Vue.createApp({
}).mount('容器名字')

data选项


Vue2

  • data选项可以是一个对象,也可以是一个方法(由方法返回一个对象)
new Vue({
el:'容器名字 ',
data:{
}
//或者
new Vue({
el:'容器名字 ',
data () {
  return { }
}
})
})

Vue3

  • data选项只能是一个方法,由方法返回一个对象
Vue.createApp({
data(){
return{}
}
}).mount('容器名字')

响应式原理


Vue2的响应式

核心:

  • 对象: 通过defineProperty对对象的已有属性值的读取和修改进行劫持(监视/拦截)
  • 数组: 通过重写数组更新数组一系列更新元素的方法来实现元素修改的劫持
Object.defineProperty(data, 'count', {
    get () {}, 
    set () {}
})

问题:

  • 对象直接新添加的属性或删除已有属性, 界面不会自动更新
  • 直接通过下标替换元素或更新length, 界面不会自动更新 arr[1] = {}

Vue3的响应式

核心:

  • 通过 Proxy(代理):拦截对data任意属性的任意(13种)操作, 包括属性值的读写, 属性的添加, 属性的删除等...
  • 通过 Reflect(反射):动态对被代理对象的相应属性进行特定的操作
new Proxy(data, {
    // 拦截读取属性值
    get (target, prop) {
        return Reflect.get(target, prop)
    },
    // 拦截设置属性值或添加新属性
    set (target, prop, value) {
        return Reflect.set(target, prop, value)
    },
    // 拦截删除属性
    deleteProperty (target, prop) {
        return Reflect.deleteProperty(target, prop)
    }
})

proxy.name = 'tom'   

Vue3的响应式数据的核心原理
简单实现,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Proxy 与 Reflect</title>
</head>
<body>
  <script>
    
    const user = {
      name: "John",
      age: 12
    };

    /* 
    proxyUser是代理对象, user是被代理对象
    后面所有的操作都是通过代理对象来操作被代理对象内部属性
    */
    const proxyUser = new Proxy(user, {

      get(target, prop) {
        console.log('劫持get()', prop)
        return Reflect.get(target, prop)
      },

      set(target, prop, val) {
        console.log('劫持set()', prop, val)
        return Reflect.set(target, prop, val); // (2)
      },

      deleteProperty (target, prop) {
        console.log('劫持delete属性', prop)
        return Reflect.deleteProperty(target, prop)
      }
    });
    // 读取属性值
    console.log(proxyUser===user)
    console.log(proxyUser.name, proxyUser.age)
    // 设置属性值
    proxyUser.name = 'bob'
    proxyUser.age = 13
    console.log(user)
    // 添加属性
    proxyUser.sex = '男'
    console.log(user)
    // 删除属性
    delete proxyUser.sex
    console.log(user)
  </script>
</body>
</html>

Vue3更好的 ts 支持

  • vue2 不适合使用 ts,在于它的 Options API 风格。
  • options 是一个简单的对象,而 ts 是一种类型系统、面向对象的语法,两个不匹配。
  • vue3 新增了 defineComponent 函数,使组件在 ts 下,更好的利用参数类型推断。如:reactive 和 ref 很具有代表性。
Vue3更先进的组件

Fragment

  • vue2 中,每个模板必须有一个根节点,否则就会报错。
  • vue3 中可以不需要根节点,多个元素或标签可并列存在。

Teleport

  • 可以把 teleport 中的内容添加到任意的节点内,对于嵌套较深的组件来说绝对是一个福音。

Supense

  • 允许程序在等待异步组件渲染一些后备的内容,可以让我们创建一个平滑的用户体验。
Vue3新推出的组合式API
  • Vue2:定义方法的时候需要写在methods里面,后添加的属性是非响应式的。页面不更新。需要用get()和set()方法
  • Vue3:组合式API的作用是将原来分散开来定义的数据、方法、计算属性、监听器、组合起来定义一个完整的业务。

生命周期


vue2的生命周期

vue2.png

vue3的生命周期

vue3.png

与 2.x 版本生命周期相对应的组合式 API

  • beforeCreate -> 使用 setup()
  • created -> 使用 setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

组合式 API 还提供了以下调试钩子函数:

  • onRenderTracked
  • onRenderTriggered

例子
演示各个生命周期钩子
父组件App

<template>
  <h2>App</h2>
  <button @click="isShow=!isShow">切换</button>
  <hr>
  <Child v-if="isShow"/>
</template>

<script lang="ts">
import Child from './Child.vue'
export default {

  data () {
    return {
      isShow: true
    }
  },

  components: {
    Child
  }
}
</script>

子组件Child

<template>
<div class="about">
  <h2>msg: {{msg}}</h2>
  <hr>
  <button @click="update">更新</button>
</div>
</template>

<script lang="ts">
import {
  ref,
  onMounted,
  onUpdated,
  onUnmounted, 
  onBeforeMount, 
  onBeforeUpdate,
  onBeforeUnmount
} from "vue"

export default {
  beforeCreate () {
    console.log('beforeCreate()')
  },

  created () {
    console.log('created')
  },

  beforeMount () {
    console.log('beforeMount')
  },

  mounted () {
    console.log('mounted')
  },

  beforeUpdate () {
    console.log('beforeUpdate')
  },

  updated () {
    console.log('updated')
  },

  beforeUnmount () {
    console.log('beforeUnmount')
  },

  unmounted () {
     console.log('unmounted')
  },
  
  setup() {

    const msg = ref('abc')

    const update = () => {
      msg.value += '--'
    }

    onBeforeMount(() => {
      console.log('--onBeforeMount')
    })

    onMounted(() => {
      console.log('--onMounted')
    })

    onBeforeUpdate(() => {
      console.log('--onBeforeUpdate')
    })

    onUpdated(() => {
      console.log('--onUpdated')
    })

    onBeforeUnmount(() => {
      console.log('--onBeforeUnmount')
    })

    onUnmounted(() => {
      console.log('--onUnmounted')
    })
    
    return {
      msg,
      update
    }
  }
}
</script>
最后编辑于:2024-09-27 20:39:01


喜欢的朋友记得点赞、收藏、关注哦!!!


原文地址:https://blog.csdn.net/pingguocu3/article/details/142794018

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!