[Day13 关于vue3中的一些知识 | 青训营笔记]

27 阅读2分钟

这是我参与「第五届青训营 」笔记创作活动的第13天

常用的Composition API

初识setup

<template>
  <h1>一个人的信息</h1>
  <h2>姓名:{{name}}</h2>
  <h2>年龄:{{age}}</h2>
  <button @click="sayHello">click</button>
</template>

<script>

export default {
  name: 'App',
  setup(){
  //  数据
    let name = '张三'
    let age  = 18
    
    function  sayHello(){
      alert('我叫${name}')
    }

    return{
      name,
      age,
      sayHello
    }
  }
}
</script>

ref函数

响应式数据的修改

<template>
  <h1>一个人的信息</h1>
  <h2>姓名:{{name}}</h2>
  <h2>年龄:{{age}}</h2>
  <button @click="changInfo">click</button>
</template>

<script>
import {ref} from 'vue'
export default {
  name: 'App',
  setup(){
  //  数据
    let name = ref('张三')
    let age  = ref(18)

    function changInfo(){
        name.value = '李四'
        age.value  =  48
    }

    return{
      name,
      age,
      changInfo
    }
  }
}
</script>

reactive函数

vue3响应式的实现

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
  </head>
  <body>
    <script type="text/javascript">
      //   源数据
      let person = {
        name:"张三",
        age:18
      }

      // 模拟vue3中的响应式的实现
      const p = new Proxy(person,{
        // 有人读取p的某个属性时调用
        get(target, p, receiver) {
          console.log(`有人读取了p身上的${p}属性`);
          return target[p]
        },
        // 有人修改p的某个属性时调用,或者给p追加某个属性时调用
        set(target, p, newValue, receiver) {
          console.log(`有人修改了p身上的${p}属性,我要去更新界面了`);
          target[p] = newValue
        },
        // 有人删除p的某个属性时调用
        deleteProperty(target, p) {
          console.log(`有人删除了p身上的${p}属性,我要去更新界面了`);
          return delete target[p]
        }
      })
    </script>

  </body>
</html>

reactive对比ref

computed

vue2中的计算属性的实现

<template>
  <h1>一个人的信息</h1><input text="姓" v-model="person.firstName" />
  <br><input text="名" v-model="person.lastName" />
    <br>
      <span>全名:{{fullName}}</span>
    </template>

<script>
  import {reactive} from "vue";
  export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name: "Demo",
    computed:{
      fullName(){
        return this.person.firstName+'----'+this.person.lastName
      }
    },
    setup(){
      //  数据
      let person = reactive({
        firstName:'王',
        lastName:'杰'
      })
      return {
        person,
      }
    }

  }
</script>

<style scoped>

</style>

vue3中计算属性的实现

<template>
  <h1>一个人的信息</h1><input text="姓" v-model="person.firstName" />
  <br><input text="名" v-model="person.lastName" />
  <br>
  <span>全名:{{person.fullName}}</span>
</template>

<script>
import {computed, reactive} from "vue";

export default {
  // eslint-disable-next-line vue/multi-word-component-names
  name: "Demo",
  setup(){
  //  数据
  let person = reactive({
     firstName:'王',
     lastName:'杰'
  })
    //计算属性-------- 没有考虑计算属性被修改的情况
    // person.fullName = computed(()=>{
    //   return person.firstName+'---'+person.lastName
    // })
    //计算属性完整写法(考虑读和写)
    person.fullName = computed({
      get(){
        return person.firstName+'-'+person.lastName
      },
      set(value){
        let nameArr = value.split('-')
        person.firstName = nameArr[0]
        person.lastName = nameArr[1]
      }
    })
  return {
    person,
  }
  }

}
</script>

<style scoped>

</style>

一、setup函数

setup:一般返回一个对象,对象的key可以直接使用(也可以返回一个渲染函数)

注意

  • 正常情况下setup不能是一个async函数,因为返回值不再是return的对象, 而是promise,模板看不到return对象中的属性,则组件不会被渲染出来。
  • 但是如果配合新增的组件Suspense和异步组件的引用方式,也可以返回一个Promise实例,具体查看 vue3新的组件

二、ref函数

创建一个响应值:ref(“张三”),ref({ name:“张三” }),返回一个RefImpl对象(引用实现的实例化对象,简称引用对象,也叫ref对象)
操作基础类型的响应值:ref(“张三”).value,ref(“张三”).value = “李四”
操作引用类型的响应值:ref({ name:“张三” }).value.name,ref({ name:“张三” }).value.name = “李四”

重点:ref函数返回的是ref对象,当创建的是基础类型的响应式是使用的是object.defineproperty的get与set方法进行数据劫持;当创建的是引用类型时使用的是ES6里面的 Proxy对象 进行代理实现的(实际上是求助了reactive函数)

三、reactive函数

作用:定义一个对象类型的响应式数据(基础类型不能用它)
创建一个响应值:const 代理对象 = reactive(源对象),返回一个代理对象(Proxy的实例化对象,简称Proxy对象)
操作响应值:reactive({ name:“张三” }).name,reactive({ name:“张三” }).name = “李四”

四、回忆vue2 的响应式

1. 实现原理

  • 对象类型:进行递归遍历对象的属性进行object.defineproperty的数据劫持
  • 数组类型:通过重写更新数组的一系列方法来进行实现拦截。(对数组的变更方法进行包裹)

2. 存在问题

  • 新增,删除属性时,界面不会更新
  • 直接通过下标修改数组,界面不会更新
  • 得采用s e t , set,set,delete,splice等方式进行修改