frontvelsun

导航

Vue2至Vue3的变化

  • 同一元素上使用的v-ifv-for优先级已更改,但不推荐同时使用 v-ifv-for

  • 组件事件需要在emits选项中声明

  • destroyed 生命周期选项被重命名为 unmounted

  • beforeDestroy 生命周期选项被重命名为 beforeUnmount

  • 自定义指令的API已更改为与组件生命周期一致

  • 新增了三个组件:Fragment 支持多个根节点、Suspense 可以在组件渲染之前的等待时间显示指定内容、Teleport 可以让子组件能够在视觉上跳出父组件(如父组件overflow:hidden)

  • 新增指令 v-memo,可以缓存 html 模板,比如 v-for 列表不会变化的就缓存,简单说就是用内存换时间。

  • Proxy 代替 Object.defineProperty 重构了响应式系统,可以监听到数组下标变化,及对象新增属性,因为监听的不是对象属性,而是对象本身,还可拦截 apply、has 等13种方法

  • 重构了虚拟 DOM,在编译时会将事件缓存、将 slot 编译为 lazy 函数、保存静态节点直接复用(静态提升)、以及添加静态标记、Diff 算法使用 最长递增子序列 优化了对比流程,使得虚拟 DOM 生成速度提升 200%

  • 支持在 <style></style> 里使用 v-bind,给 CSS 绑定 JS 变量(color: v-bind(str))

  • 新增 Composition API 可以更好的逻辑复用和代码组织,同一功能的代码不至于像以前一样太分散,虽然 Vue2 中可以用 minxin 来实现复用代码,但也存在问题,比如方法或属性名会冲突,代码来源也不清楚等

  • 全局函数 setdelete 以及实例方法 $set$delete移除。基于代理的变化检测已经不再需要它们了

  • 毕竟 Vue3 是用 TS 写的,所以对 TS 的支持度更好

  • Vue3 不兼容 IE11

  • $on$off$once 实例方法已被移除,组件实例不再实现事件触发接口。

  •                                                                                                                                                                

  • 三、组合式API

  • 原有的组件选项(datacomputedmethodswatch)的方式来编写组件代码通常来说是十分有效的,但是也会存在一些不好的地方,例如把原有相关的逻辑、事件、变量按照选项划分区域,这样我们就必须不断上下滚动代码寻找对应的代码块逻辑,掩盖自身原有潜在的逻辑问题,带来极大不便,如果这段业务逻辑代码并非原本人来维护,这样会导致组件内代码难以理解和阅读。
  • 所以针对这类情况,Vue3提出了新的编写组织组件代码的方式——组合式API。组合式API需要一个可以实际使用的地方,那就是setup
  • setup触发时机在组件创建之前执行。需要注意的是,在setup中应避免使用this,因为这个时候this的指向并不代表组件实例。
  • setup的调用发生在datacomputedmethods被解析之前,所以其三没办法再setup中被获取
  • 当然在Vue3中同样支持Option API写法进行编码,与Vue2无异,但是官方不建议这么写。
  • 组合式API写法推荐
<script>
	import { defineComponent, ref, onMounted } from 'vue';
  export default defineComponent({
    setup(){
      let num = ref(0);
      let fn = () => {};
      onMounted(():void => {
				console.log('生命周期mounted');
      });
      return {
        num,
        fn
      }
    }
  })
</script>

 

  • 更为简便的一种写法
<script lang='ts' setup>
import { reactive, toRefs, ref} from 'vue'
//在setup环境下组件默认引入definedComponent
let num= ref(0);
const appClick =  ()=>{
   console.log(num.value)
}
// 无需return
</script>

—————————————————————————————————

  • 生命周期(钩子函数)
  • Option API setup 
    beforeCreate -
    created -
    beforeMount OnBeforeMount
    mounted onMounted
    beforeUpdate onBeforeUpdate
    Updated onUpdated
    beforeUnmount onBeforeUnmount
    unmounted onUnmounted
    组件缓存 activated onActivated
    组件缓存 deactivated onDeactivated
  • 在Vue3中,setup 是在 beforeCreatecreated 生命周期钩子前运行的,因此不需要定义他们。以上这些钩子中编写的代码都应该在setup函数中进行。
  • ref、toRefs、reactive响应式和methods

  • Vue2.X中默认写在data的值,初始化组件时,内部会自动完成值的数据响应式绑定(getset绑定),但是Vue3里需要手动调用内置方法进行实现。

  •  

    ref不仅可以用在数据响应式,还可以绑定DOM元素

  • <template>
      <div>
        <div>{{ num }}</div>
        <button @click="add1">num++</button>
        <p>-------------------------------</p>
        <div>{{ state.count }}</div>
        <button @click="add2">state.count++</button>
        <p>-------------------------------</p>
        <div>{{ count }}</div>
        <button @click="add3">count++</button>
      </div>
    </template>
    
    <script lang="ts">
    import { defineComponent, ref, reactive, toRefs } from "vue";
    export default defineComponent({
      setup() {
        interface ObjItf {
          count: number;
        }
        // ref声明响应式数据,用于声明基本数据类型
        let num = ref<number>(1);
        let obj = {
          count: 1,
        };
    
        // reactive声明响应式数据,用于声明引用数据类型
        let state = reactive<ObjItf>(obj);
    
        // toRefs解构响应式数据
        let { count } = toRefs<ObjItf>(state);
        const add1 = (): void => {
          num.value++; // 注意通过ref声明的变量,所以js要修改对应的值是要通过.value访问才可以,template模板不需要通过.value访问
        };
        const add2 = (): void => {
          state.count++; // 通过reactive声明的遍历,不需要通过.value访问值
        };
        const add3 = (): void => {
          count.value++; // 通过toRefs结构的值和ref声明的变量一样,需要通过.value访问其值
        };
    
        return {
          num,
          state,
          count,
          add1,
          add2,
          add3,
        };
      },
    });
    </script>

     

  • 注意:
  • 1.reactive可以传递基本数据类型和引用数据类型,基本数据类型不会被包装成响应式数据
  • 2.reactive返回的响应式数据本质是Proxy对象,对象里面每一层都会被包装成Proxy对象
  • 3.reactive返回的响应式数据和原始数据会相互影响
  • 4.ref可以传递基础数据类型和引用数据类型。如果是基本数据类型,那么这个值保存在返回的响应式数据的.value上;ref声明的变量,template模板上不需要通过.value访问。如果是引用类型,响应式数据同样在.value上。
  • 5.ref本质是将一个数据变成一个对象,这个对象具有响应式特点。
  • 为什么需要toRefs和toRef?

  • ref不同的是,toReftoRefs两个方法,其二之中不是创造响应式,而是延续 响应式。创造响应式一般由ref和reactive来解决,而toRef和toRefs则把都对象的数据进行分解和扩散,其这个对象针对的是响应式对象(reactive)而非普通的对象。
  • watch

  • 语法:watch(监听源|[多个],(val,newVal)=>{},{immediate?:false,deep:false})
  • watch写法上可以支持单个或若干个监听源,这些监听源必须只能是getter/effect函数,ref数据,reactive对象,或者是数组类型
  • <template>
      <div>
        {{ num }}
        <button @click="addNum">++</button>
      </div>
    </template>
    
    <script lang="ts" setup>
    import { reactive, toRefs, ref, watch } from "vue";
    interface ObjItf {
      num: number;
    }
    let obj: ObjItf = {
      num: 1,
    };
    // reactive声明响应式数据,用于声明引用数据类型
    let state = reactive<ObjItf>(obj);
    
    // toRefs解构响应式数据
    let { num } = toRefs<ObjItf>(state);
    
    const addNum = () => {
      num.value++;
    };
    watch(num, (newVal, oldVal) => {
      console.log(newVal, oldVal);
    });
    </script>
    <style lang="less" scoped></style>

     

  • watchEffect

  • 它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
  • <template>
      <div>{{num}}</div>
    </template>
    
    <script lang="ts" setup>
    import { reactive, toRefs, ref, watchEffect } from "vue";
    let num = ref(0);
    watchEffect(() => {
      console.log(num.value);
    });
    
    setTimeout(() => {
      num.value++;
    }, 2000);
    </script>
    <style lang="less" scoped></style>

     

  • watch和watchEffect的区别
  • 两者都可监听data属性的变化;
  • watch需要明确监听哪个属性;
  • watchEffect会根据其中的属性,自动监听其变化。
  • computed
  • <!--  -->
    <template>
      <div>{{ count }}</div>
    </template>
    
    <script lang="ts" setup>
    import { reactive, toRefs, ref, watchEffect, computed } from "vue";
    
    let state = reactive({
      num: 1,
      arr: [1, 54, 6, 3, 2, 3],
    });
    
    let count = computed((): number => {
      return state.num;
    });
    </script>

     

posted on   Velsun  阅读(44)  评论(0编辑  收藏  举报

努力加载评论中...
点击右上角即可分享
微信分享提示