vue2和vue3的.vue的区别

136 阅读3分钟
vue2生命周期
生命周期描述使用场景具体分析
beforeCreate组件实例被创建之初执行时组建实例还未创建,通常用于插件开发中执行一些初始化任务初始化Vue实例
create组件实例已经完全创建组件初始化完毕,各种数据可以使用,常用于异步数据获取1.完成数据观测,属性与方法的运算,watchevent事件回调的配置 2.可调用methods中的方法,访问和修改data数据触发相应式渲染dom,可通过computedwatch完成数据计算 3.vm.$el并没有被创建
beforeMount组件挂载之前未执行渲染、更新,dom未创建1.在此阶段可获取vm.$el 2.此阶段vm.$el虽已完成DOM初始化,但并未挂载在el选项上
mounted组件挂载到实例上去之后初始化结束,dom已创建,可用于获取访问数据和dom元素vm.$el已经完成DOM的挂载与渲染,此刻打印vm.$el,发现之前的挂载点及内容已被替换成新的DOM
beforeUpdate组件数据发生变化,更新之前更新前,可用于获取更新前各种状态1.更新的数据必须是被渲染在模版上的(eltemplaterender之一)2.此刻view层还未更新 3.若在beforeUpdate中再次修改数据,不会再次触发更新方法
update组件数据更新之后更新后,所有状态已是最新1.完成view层的更新 2.若在update中再次修改数据,会再次触发更新方法(beforeUpdateupdate
beforeDestroy组件实例销毁之前销毁前,可用于一些定时器和订阅的取消实例被销毁前调用,此时实例属性与方法仍可访问
destroy组件实例销毁之后组建已销毁,作用同上1.完全销毁一个实例。可清理它与其他实例的链接,接棒他的全部指令及事件监听器 2.并不能清除Dom,仅仅销毁实例
数据请求在created和mouted的区别

created 是在组件实例一旦创建完成的时候立刻调用,这时候页面dom节点并未生成; mounted 是在页面 dom 节点渲染完毕之后就立刻执行的。触发时机上 created 是比 mounted 要更早的,两者的相同点:都能拿到实例对象的属性和方法。讨论这个问题本质就是触发的时机,放在 mounted 中的请求有可能导致页面闪动(因为此时页面 dom 结构已经生成),但如果在页面加载前完成请求,则不会出现此情况。建议对页面内容的改动放在 created 生命周期当中。

mvvm和双向绑定

Vue 是数据双向绑定的框架,核心功能便是“数据双向绑定”,双向绑定由三个重要部分构成

  1. 数据层(Model):应用的数据及业务逻辑.
  2. 视图层(View):应用的展示效果,各类UI组件
  3. 业务逻辑层(ViewModel):框架封装的核心,它负责将数据与视图关联起来而上面的这个分层的架构方案

ViewModel:

  • 数据变化后更新视图
  • 视图变化后更新数据当然,它还有两个主要部分组成
    • 监听器(Observer):对所有数据的属性进行监听
    • 解析器(Compiler):对每个元素节点的指令进行扫描跟解析,根据指令模板替换数据,以及绑定相应。的更新函数
组件通信

vue中每一个.vue可以视作为组件,通信的本质是信息同步。 每个组件都有自己的作用域,在工作业务中不同组件存在需要传递信息、共享数据。 组件通信分为:

  • 父子组件之间的通信
  • 兄弟组件之间的通信
  • 祖孙与后代组件之间的通信
  • 非关系组件之间的通信

Vue2常见的8种组件通信:

  1. 通过props传递
  2. 通过$emit触发自定义事件
  3. 使用ref
  4. EventBus
  5. parentroot
  6. attrslisteners
  7. ProvideInject
  8. Vuex

可参考代码链接:# Vue3的8种和Vue2的12种组件通信,值得收藏

  • 父子关系的组件数据传递选择 props$emit 进行传递,也可选择ref兄弟关系的组件数据传递可选择 $bus ,其次可以选择 $parent 进行传递
  • 祖先与后代组件数据传递可选择 attrslisteners或者 ProvideInject
  • 复杂关系的组件数据传递可以通过 vuex 存放共享的变量
vuex

适用场景:复杂关系的组件数据传递,Vuex 作用相当于一个用来存储共享变量的容器

  • state 用来存放共享变量的地方
  • getter ,可以增加一个 getter 派生状态,(相当于 store 中的计算属性),用来获得共享变量的值
  • mutations 用来存放修改 state 的方法。
  • actions 也是用来存放修改state的方法,不过 action 是在 mutations 的基础上进行。常用来做一些异步操作。
vue2和vue3生命周期区别

常用生命周期对比如下表所示。

vue2vue3
beforeCreate
created
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestroyonBeforeUnmount
destroyedonUnmounted

Vue 2 的生命周期钩子如下所示:

  • 创建阶段 beforeCreate created
  • 挂载前后 beforeMount mounted
  • 更新阶段 beforeUpdate updated
  • 销毁阶段 beforeDestroy destroyed
  • 错误处理 errorCaptured
  • 异步组件 activated deactivated
  • 服务端渲染 serverPrefetch

Vue 3 的生命周期钩子如下所示:

  • 创建阶段 setup (Composition API),beforeCreate 和 created 被 setup 替代
  • 挂载阶段 beforeMount mounted
  • 更新阶段 beforeUpdate updated
  • 销毁阶段 beforeUnmount unmounted
  • 错误处理 errorCaptured
  • 异步组件 activated deactivated
  • 服务端渲染 serverPrefetch
<template> // Vue2 中只能有一个根节点
  <div class='form-element'>
    ...
  </div>
</template>
<script>
export default {
  props: ['secondNum'], //父组件传过来的值,默认为0
  data () { // 创建
     return {
       firstNum: 0,
       msg: "123456"
     }
  },
  computed: {
     thirdNum () {
       console.log('computed', this.firstNum, this.secondNum)
       return this.firstNum + this.secondNum + '元' }
     },
 watch: {
    //简单形式
    // msg(newValue, oldValue) {
    //   console.log("newValue", newValue);
    //   console.log("oldValue", oldValue);
    // }
    //对象形式
    msg: {
      deep: true,
      immediate: true,//初始化是否执行
      handler(newValue, oldValue) {
        console.log("newValue", newValue);
        console.log("oldValue", oldValue);
      },
    }
  },
 created () {
   console.log('created', this.firstNum, this.secondNum)
 },
 beforeMount () {
   console.log('beforeMount', this.firstNum, this.secondNum)
 },
 mounted () {
   console.log('mounted', this.firstNum, this.secondNum)
 },
 beforeUpdate () {
   console.log('beforeUpdate', this.firstNum, this.secondNum)
 },
 updated () {
   console.log('updated', this.firstNum, this.secondNum)
 },
 methods: {
   btnClick () {
     this.firstNum = 'firstNum' + Math.random() * 999 console.log('methods', this.firstNum, this.secondNum)
   }
 }
}
</script>

<template> //Vue3 中支持多个根节点
  <div class='form-element'>
    ...
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue' 
  props: {
    title: String
  },
  const state = reactive({
    username: '',
    password: '',
    lowerCaseUsername: computed(() => state.username.toLowerCase())
  })
  const count = ref(1) // 有人这么用 const arr = ref([]) 
  console.log(arr.value) // [] 
  // 也有人这么用,一个组件里所有的属性全部定义在一个对象里,有点 Vue2 data 的味道
  const data = reactive({ name: '沐华', age: 18, ... })   
  console.log(data.name) // 沐华
  // 也有人一个组件里 ref 和 reactive 两种都用,随便你
  
  // 这样虽然能拿到 name / age,但是会变成普通变量,没有响应式效果了
  const { name, age } = data // 取出来一个响应式属性
  const name = toRef(data, 'name') // 这样解构出来的所有属性都是有响应式的
  const { name, age } = toRefs(data) // 不管是 toRef 还是 toRefs,这样修改是会把 data 里的 name 改掉的
  // 就是会改变源对象属性,这才是响应式该有的样子 name.value = '沐沐华华'
    
    // 请求接口函数
    const getData = () => { xxxApi.then(() => { ... }) } 

    onMounted(() => {
      console.log('title: ' + props.title)
      getData()
    })
    
    // 监听
    const msg = ref('1111')
    //简单的没有其他设置的监听
    // watch(msg, (newVal, oldVal) => {
    //     console.log('监听msg变化', newVal, oldVal)
    // })
    //对象形式
    watch(msg, (newVal, oldVal) => {
        console.log('监听msg变化', newVal, oldVal)
    }, {
        immediate: true,
        deep: true
    })
    
    // 组件卸载前,对应 Vue2 的 beforeDestroy
    onBeforeUnmount(() => {
      clearTimeout(timer)
      window.removeAddEventListener('...')
    })
    // 退出缓存组件,对应 Vue2 的 deactivated
    onDeactivated(() => {
      clearTimeout(timer)
      window.removeAddEventListener('...')
    })

    return { 
      login,
      state
    }
  }
}
</script>