Vue3的新特性变化,上手指南!

文章目录

  • 一、Vue3相比Vue2,更新了什么变化?
  • 二、Proxy 代理响应式原理
  • 三、组合式 API (Composition API)
    • setup()函数:
      • ref()函数
      • reactive()函数
      • 组合式 setup 中使用 Props 父向子传递参数
      • 计算属性
      • watch(数据监视)
      • watchEffect()函数
      • Vue3 生命周期钩子函数
      • 自定义 Hook 函数()
      • toRef 和 toRefs 钩子函数
      • shallowReactive 和 shallowRef 函数
      • readonly 和 shallowReadonly 函数
      • toRaw 和 markRaw 函数
      • customRef 自定义Ref 函数
      • 依赖注入 ( provide(), inject() )
        • provide() 函数
        • inject() 函数
      • defineAsyncComponent 函数
  • 总结

一、Vue3相比Vue2,更新了什么变化?

  • 新增 响应式数据劫持的Api,在Vue2 中,数据响应式劫持更新采用的是 Object.defineProperty(),但是 Object.defineProperty(),会有一些缺陷,例如监听不到对象属性的新增或者删除,以及数组通过下标索引,直接更改数据后,无法响应式更新。,所以Vue3中,新增了 Proxy 作为响应式数据劫持的Api,响应式数据监听更加高效。
  • 友好的支持了 TypeScript 的语法。
  • 以及新增了组合式API 的编码风格!

二、Proxy 代理响应式原理

        let arr = {
            name: "张三",
            age: 18
        }
        let Responsivedata = new Proxy(arr, {      //通过 Proxy 实例实现代理对象
            get(target, attributeName) {   //   收到两个参数  用来捕获读取代理对象属性时的数据
                // target:代理的源数据
                // attributeName : 操作当条数据的key
                console.log(target, attributeName);
                return Reflect.get(target, attributeName);  //  使用  Reflect 反射对象 把数据 返回出去
            },
            set(target, attributeName, value) {   //捕获修改新增对象属性时,拿到新增修改的值
                // target:代理的源数据
                // attributeName : 操作当条数据的key
                // value :新增 修改的 value 值
                console.log(target, attributeName, value);
                Reflect.set(target, attributeName, value); //   使用  Reflect 反射对象  在这里真正操作修改源数据的变化
            },
            deleteProperty(target, attributeName) {    //捕获 源数据 ,以及删除当前数据的key。
                // target:代理的源数据
                // attributeName : 操作当条数据的key
                console.log(target, attributeName);
                return Reflect.deleteProperty(target, attributeName); //  使用  Reflect 反射对象  在这里真正操作删除源数据。
            }
        });

点击了解 Reflect

三、组合式 API (Composition API)

概念:

组合式 API 的核心思想是直接在函数作用域内定义响应式状态变量,并将从多个函数中得到的状态组合起来处理复杂问题。这种形式更加自由,也需要你对 Vue 的响应式系统有更深的理解才能高效使用。相应的,它的灵活性也使得组织和重用逻辑的模式变得更加强大。

setup()函数:

setup是vue3新增的生命周期函数,setup的加入就是为了让vue3使用组合式API(Composition API)。使用组合式API更符合大型项目的开发,通过setup可以将该部分抽离成函数,让其他开发者就不用关心该部分逻辑。
————————
setup内部可以定义数据和方法,如果想在模板中使用,必须通过return进行返回。
————————
setup函数内,要使用的Api方法配置项,采用按需映入 如 computed、watch等。

<script>
import { computed, watch} from 'vue';   //按需映入
export default {
  name: 'HelloWorld',
  setup() {
    let name = "张三";   //直接定义数据
    let arr = [{ a: 1 }, { b: 2 }];
    const addnum = () => name = "李四";  //直接定义数据的方法
    return {
      name,
      arr,
      addnum 
    }
  }
}
</script>

注意:如上在setup中定义的数据,页面中虽然能够读取,但是数据发生改变时,不会触发响应式更新。需要借助 ref() 函数 以及 reactive() 函数实现响应式

ref()函数

<script>
import { ref } from 'vue'  //按需映入ref
export default {
  name: 'HelloWorld',
  setup() {
    let name = ref("张三");  //直接定义数据
    const addnum = () => name.value = "李四";  //通过.value 操作数据
    console.log(name);   //见下图
    return {
      name,
      addnum 
    }
  }
}
</script>

Vue3的新特性变化,上手指南!_第1张图片

在setup函数中 ref() 函数 通常用来 包裹 基本数据类型 ,为该数据提供响应式监听,操作该数据时,需要通过点. value 拿取到数据。

reactive()函数

<script>
import { ref, reactive } from 'vue'
export default {
  name: 'HelloWorld',
  setup() {
    let arr = reactive([{ a: 1 }, { b: 2 }]);
    console.log(arr);   //通过 reactive 函数包裹的 数据结构见下图
    const addnum = () => arr[0].a = 456;  //直接更改数据的方法
    return {
      addnum,
      arr
    }
  }
}
</script>

Vue3的新特性变化,上手指南!_第2张图片

reactive 函数 通常用来包裹 引用数据类型,为引用数据类型提供响应式。

ref 函数 和 reactive 函数 总结

  • ref() 函数 用来定义基本数据类型。
  • reactive () 函数 用来定义 引用数据类型。
    -备注: ref函数也能用来定义 引用数据类型( 但reactive () 函数不能用来定义基本数据类型),它内部会自动 调用 reactive 函数 转为代理对象=》 但是不推荐。
  • ref 函数 响应式原理 依然采用的是 Object.defineProperty 的get 和set 方法 通过 数据劫持来完成响应式。
  • reactive() 函数 通过 ES6 的 Proxy 代理对象的数据劫持来实现响应式 (见上节 Proxy 响应式原理。
  • ref 函数定义的数据 操作 数据时 需要通过 .value 模板中读取 则不需要。
  • reactive 函数 定义的数据 操作数据或 模板读取时,均不需要 .value

组合式 setup 中使用 Props 父向子传递参数

setup 可以接收两个参数
第一个参数Props

export default {
  name: 'HelloWorld',
  props:["masg"],  //父组件中,按v2 正常传递参数,子组件这里正常接收
  setup(props,context) {
   //  setup 这里的第一个参数 就是 Props ,不过被setup包裹成了 代理对象数据,具有响应式
    console.log(props,context);
    return {
     props
    }
  }
}

Vue3的新特性变化,上手指南!_第3张图片
第二个参数 context (上下文对象)

context 主要接收三个参数

  • attrs:值为对象,包含组件外部传递过来的参数,但是并没有在 Props 中声明接收,则会出现在这里,Props 中如果接受了参数,则就不会再出现在 这里 和 V2中 this.$attrs 同理
  • emit:分发自定义事件的函数 同 v2 this.$emit
  • slots:接收到外部组件传入的 插槽内容。

Vue3的新特性变化,上手指南!_第4张图片

计算属性

在Vue3.x 中,计算属性属性不再通过配置项操作,而是通过引用一个计算属性函数。
点击查看Vue2中计算属性

import { ref, reactive, computed } from 'vue'   //引入 computed  计算属性函数,函数回调 return  返回处理后的数据
export default {
  name: 'HelloWorld',
  setup() {
    let name = ref("张三");
    let age = ref(18);

    // let calculation = computed(() => {        //常见写法,读取 计算属性
    //   return `${name.value}++++${age.value}`
    // });

    let calculation = computed({    //完整写法。可读取,也可修改
      get() {
        return `${name.value}++++${age.value}`
      },
      set(value) {
        return `${name.value}++++${age.value}++++${value}`
      }
    });
    return {                  //提示: 别忘了 所定义的 数据 以及函数方法 ,记得 return 出去,页面才能使用。
      name,
      age,
      calculation,
    }
  }
}
</script>

watch(数据监视)

同样在Vue3.x 中,watch 属性不再通过配置项操作,而是通过引用一个 watch 函数。
点击查看Vue2 中watch

import { ref, reactive, watch } from 'vue'   //引入  watch  函数
export default {
  name: 'HelloWorld',
  setup() {
    let age = ref(18);
    let num = ref(22);
    let arr = reactive([{ a: 1, b: 2, c: 3 }, { b: 2 }, { c: 5 }]);
    let obj = reactive({
      age: 14,
      name: "张三",
      job: {
        a: 1,
        b: 2
      }
    })

   //监听ref 基本数据类型!
   //使用场景一:
    watch(num, (a, b) => {    // watch 函数监听 可以接收三个参数, 第一个参数 为 要监听的值 ,第二个参数为 回调函数,且回调函数 也能 接收两个参数,为新值和旧值。 第三个 参数 为一个配置对象  
      console.log("检测到数据被修改");
    },{ immediate: true });  //  immediate 为true时,可以开启 页面初始化 时就执行一次监听
    
//使用场景二:
    watch([age, num, arr], (a, b) => {    // watch 函数也可以一次性监听多个数据,第一个参数设置为一个数组,里面配置 多个需要监听得数据。
      console.log("检测到数据被修改", a, b);
    })
    let ick = () => age.value++;


/*  监听  reactive  引用数据类型!    

注意:watch 函数监听  reactive  数据时,存在两个问题 !
   1.  无法正确获取 旧的值;
   2. 强制开启了深度监视模式(配置 deep:false   无效)
*/

// 场景三 : 监听   reactive  所定义数据的全部属性
    let ickbtn = () => arr[0].a++
    watch(arr, (a, b) => {
      console.log("监听到arr更改了", a, b);
    }, { immediate: true })

//场景四:   监听   reactive  所定义数据的某个属性,watch 函数第一个参数是一个函数 返回值就是需要监听的值
    let ick = () => arr[0].a++
    watch(() => arr[0].a, (a, b) => {
      console.log("监听到arr[0].a 更改了", a, b);
    }, { immediate: true })

//场景五       监听   reactive  所定义数据的某一些属性,watch 函数第一个参数是一个数组 数组中返回多个函数,监听项。
 	 let ick = () => {
     	 arr[0].a++;
      	arr[0].b++;
     }
    watch([() => arr[0].a, () => arr[0].b], (a, b) => {
      console.log("监听到arr[0].a 和 b 更改了", a, b);
    }, { immediate: true })

// 特殊场景
    let ick = () => {
      obj.job.b++
    }
    watch(() => obj.job, (a, b) => {
      console.log("监听到arr[0].a 和 b 更改了", a, b);
    }, { immediate: true, deep: true })   //此处如果 监听的是 reactive   所定义数据中的某个 属性,同时所操作更改的值又 位于所监听的 属性下面,这时候 ,默认是监听不到更改的,所以这里需要手动 配置 deep:true ,开启深度监视


    return {
      age,
      arr,
      ick,
      num,
      ickbtn,
      obj
    }
  }
}
</script>

watchEffect()函数

Vue3的新特性变化,上手指南!_第5张图片

Vue3的新特性变化,上手指南!_第6张图片

Vue3 生命周期钩子函数

Vue3的新特性变化,上手指南!_第7张图片

注明:

在Vue3中,依然可以通过配置项使用Vue2中的 生命周期钩子函数,但是有两个钩子函数名称 被更名:


beforeDestroy =》更名为 beforeUnmount
destroyed =》 更名 为 unmounted

官方推荐在Vue 3中 使用 组合式 API (Composition API) ,所以Vue3 也提供了 一套 组合式 API (Composition API) 形式的生命周期钩子函数,与Vue2中的 函数钩子对应 如下:

Vue2 Vue3(setup) 描述
beforeCreate setup() 实例创建前调用
created setup() 实例创建后调用
beforeMount onBeforeMount DOM挂载前调用
mounted onMounted DOM挂载成功后调用
beforeUpdate onBeforeUpdate 数据更新之前调用
updated onUpdated 数据更新之后调用
beforeUnmount onBeforeUnmount 组件卸载之前调用
unmounted onUnmounted 组件卸载完成后调用

自定义 Hook 函数()

其本质是一个函数,把 setup 函数中使用的 Composition API 放到一个文件中进行了封装,然后在需要用到的地方,进行引入,类似于 vue2.x 中的 Mixin。总结就是,把多个地方都会用到的 组合式api 方法进行抽离化,封装。

toRef 和 toRefs 钩子函数

使用场景:当结构模板中使用到 reactive 对象类型数据的时候,如果数据结构嵌套过深的时候, 会出现 大量 xxx.xxx.xxx 的赋值现象
————————————————————————————————————————————————————
作用:代理创建一个 Ref 对象,其 Value 值 映射到 一个指定对象中的某个属性
————————————————————————————————————————————————————
语法:let name = toRef(obj, "name"); obj是所要代理的对象,name是obj身上所要具体映射的 key。
————————————————————————————————————————————————————
应用:要将响应式数据中的某个属性,单独提供给外部使用时,并且需要依然保持 响应式
————————————————————————————————————————————————————
扩展:toRefs 和 toRef 功能基本一致,但是可以批量创建 ref对象 语法: toRefs (obj)

shallowReactive 和 shallowRef 函数

shallowReactive处理对象形式的数据时,只进行浅层次监听响应式,只处理最外层数据
————————————————————————————————————————
shallowRef当传入基本数据类型的时候,作用和 ref 一样,如果传入的是对象类型数据时,则不会进行响应式监听处理。
Vue3的新特性变化,上手指南!_第8张图片
Vue3的新特性变化,上手指南!_第9张图片

readonly 和 shallowReadonly 函数

readonly把一个响应式数据,限制为只读的(深层次的)
shallowReadonly把一个响应式数据,限制为只读的(浅层次的)
Vue3的新特性变化,上手指南!_第10张图片
Vue3的新特性变化,上手指南!_第11张图片

toRaw 和 markRaw 函数

toRaw将 reactive 生成的响应式对象 转化成普通的原始对象,如果传入的是 ref 数据 ,之前会报出 undefined ,vue最新版修复后 则不会进行转化处理,也不会报 undefined
markRaw标记一个对象,使其被标记后的对象,不会被转换成响应式 数据对象。
Vue3的新特性变化,上手指南!_第12张图片
Vue3的新特性变化,上手指南!_第13张图片

customRef 自定义Ref 函数

概念:创建一个自定义的 ref,显式声明对其依赖追踪和更新触发的控制方式。,使其能够使开发者更加灵活地操作响应式数据。

  setup() {
    let myref = (val) => {
      return customRef((track, trigger) => {
        return {
          get() {
            console.log("读取数据");
            track()
            return val
          },
          set(newval) {
            console.log("修改数据");
            val = newval
            trigger()
          }
        }
      })
    }
    let keywordname = myref(500)
    return {
      keywordname
    }
  }

Vue3的新特性变化,上手指南!_第14张图片

依赖注入 ( provide(), inject() )

作用:用来实现跨级组件间的数据通讯

provide() 函数

Vue3的新特性变化,上手指南!_第15张图片

inject() 函数

Vue3的新特性变化,上手指南!_第16张图片

defineAsyncComponent 函数

作用:定义一个异步组件的的导入, 不过需要 搭配 组件使用。
Vue3的新特性变化,上手指南!_第17张图片

总结

上手章节到此结束:

本文 为 Vue 2 开发者提供 Vue3 的开发过度上手手册,Vue3 的变化 不止于这些,更多的 新特征,还需要 开发者自己去发现 !下面附上

点击访问Vue3 官网

你可能感兴趣的:(#,Vue3,javascript,前端,vue.js,前端框架)