Vue3(ref,reactive,setup,computed,watch,watchEffect)

目录

1.ref函数

2.reactive函数

3.Vue3的响应式实现

4.reactive和ref的区别

 5.setup的两个注意点

6.computed计算属性

7.watch计算属性

watchEffect函数


1.ref函数

import { ref } from 'vue'
export default {
  name: 'App',
  setup() {
    // 直接写数据不是响应式的
    let name = ref('张三')
    let age = ref(18)

    function changeInfo() {
      name = '李四'
      age = 19
      console.log(name, age)
    }
    // 还要return出去 返回一个对象
    return {
      name,
      age,
      changeInfo
    }
    // 返回一个函数(渲染函数 跟render相似 ,引入h)
    // return () => h('h1', '尚硅谷')
  }
}
</script>
  • 作用: 定义一个响应式的数据

  • 语法: const xxx = ref(initValue)

    • 创建一个包含响应式数据的引用对象(reference对象,简称ref对象)

    • JS中操作数据: xxx.value

    • 模板中读取数据: 不需要.value,直接:<div>{{xxx}}</div>

  • 备注:

    • 接收的数据可以是:基本类型、也可以是对象类型。如果是对象,对象还用调用 reactive,成为reactive型的响应式数据

    • 基本类型的数据:响应式依然是靠Object.defineProperty()getset完成的。

    • 对象类型的数据:内部 “ 求助 ” 了Vue3.0中的一个新函数—— reactive函数。

2.reactive函数

作用:定义一个对象类型的响应式数据(基本类型不要用reactive,要用ref)

- 语法:const 代理对象= reactive(源对象)```接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象)
- reactive定义的响应式数据是“深层次的”。
- 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。

   let sum = ref(0)
    let person1 = ref({
      name: 'zhangsan',
      age: 19
    })
    let person2 = reactive({
      name: 'lisi',
      age: 18
    })

输出

3.Vue3的响应式实现

vue2的响应式只有get和set,直接增加属性和删除属性不能得到响应式,要用到this.$set(对象,属性名,值)或者Vue.set()来获得响应式以及this.$delete和Vue.delete,很麻烦。主要是Vue实现响应式用到Object.defineProperty()只有查和改。

存在问题:

- 新增属性、删除属性, 界面不会更新。
- 直接通过下标修改数组, 界面不会自动更新。

Object.defineProperty(data, 'count', {
    get () {}, 
    set () {}
})

Vue3实现响应式用Proxy,把增删改查全实现了

target就是对象:

propsName是属性名:

在里面要用target[propsName]不能用点的形式:因为propsName是一个变量,[]有解析变量的作用,而点后面应该是字符串。

  <script>
    let person = {
      name: 'zhangsan',
      age: 18
    }
    const p = new Proxy(person, {
      // 增和查都设置在这里了
      get(target, propsName) {
        console.log(target, propsName)
        console.log(`有人读取了上${propsName}属性`)
        return target[propsName]
      },
      // 修改
      set(target, propsName, value) {
        console.log(`p上的${propsName}在被修改`)
        target[propsName] = value
      },
      // 删除
      deleteProperty(target, propsName) {
        console.log(`属性${propsName}正在被删除`)
        return delete target[propsName]
      }
    })
  </script>

Reflect来进行增删改查,这也是框架的做法,其实本质上没什么太大的区别,只是Reflect可以避免一些报错吧,不然还要用try-catch去捕获?这里不用太纠结,其实就是为了让框架更加的友好(少一些报错)

  <script>
    let person = {
      name: 'zhangsan',
      age: 18
    }
    const p = new Proxy(person, {
      // 增和查都设置在这里了
      get(target, propsName) {
        console.log(target, propsName)
        console.log(`有人读取了上${propsName}属性`)
        return Reflect.get(target, propsName)
      },
      // 修改
      set(target, propsName, value) {
        console.log(`p上的${propsName}在被修改`)
        Reflect.set(target, propsName, value)
      },
      // 删除
      deleteProperty(target, propsName) {
        console.log(`属性${propsName}正在被删除`)
        return Reflect.defineProperty(target, propsName)
      }
    })
  </script>

4.reactive和ref的区别

从定义数据角度对比:

  • ref用来定义:基本类型数据
  • reactive用来定义:对象(或数组)类型数据
  • 备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过reactive转为代理对象

从原理角度对比:

  • ref通过Object.defineProperty()getset来实现响应式(数据劫持)。

  • reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据

  • 从使用角度对比:

    • ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value

    • reactive定义的数据:操作数据与读取数据:均不需要.value

 

 5.setup的两个注意点

  • setup执行的时机

    • 在beforeCreate之前执行一次,this是undefined。

  • setup的参数

    • props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。

    • context:上下文对象

      • attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于 this.$attrs

      • slots: 收到的插槽内容, 相当于 this.$slots

      • emit: 分发自定义事件的函数, 相当于 this.$emit

打印输出第一个参数props,父组件传来的数据用props接收,把封装成了proxy对象

打印输出第二个参数:

父组件给子组件绑定的自定义事件,子组件也可以接收

context的emit就是用来触发自定义事件

6.computed计算属性

就是变成了函数形式并且需要import,其它没啥区别,如果没有set也是简写形式,直接在computed里写回调函数

<template>
  <h1>一个人的信息</h1>
  姓:<input type="text" v-model="person.fistName">
  <br>
  名:<input type="text" v-model="person.lastName">
  <br>
  全名:<input type="text" v-model="fullName">
  <button @click="test">测试</button>
  <slot></slot>

</template>

<script>
import { reactive, computed } from 'vue'
export default {
  name: 'Demo',
  setup() {
    let person = reactive({
      fistName: '张',
      lastName: '三',
    })
    let fullName = computed({
      get() {
        return person.fistName + '-' + person.lastName
      },
      set(value) {
        const arr = value.split('-')
        person.fistName = arr[0]
        person.lastName = arr[1]
      }
    })
    return {
      person,
      fullName
    }
  }
}
</script>

<style></style>

7.watch计算属性

 /第一种情况:监视ref所定义的一个响应式数据

    watch(sum, (newValue, oldValue) => {
      console.log(newValue + '------' + oldValue)
    }, { immediate: true })

情况二:监视多个ref定义的响应式数据

    watch([sum, msg], (newValue, oldValue) => {
      console.log('sum或msg变了', newValue, oldValue)
    })

情况三:监视reactive定义的响应式数据

能监视person里的全部属性,此处无法正确获得oldValue

watch(person,(newValue,oldValue)=>{
	console.log('person变化了',newValue,oldValue)
},{immediate:true}) 

情况四:监视reactive定义的响应式数据中的某个属性

监视对象里的一个属性,必须写成一个箭头函数进行返回,要不然就是死的值,无法进行监视,如果你监视的还是一个对象,必须手动开启深度监视

watch(()=>person.job,(newValue,oldValue)=>{
	console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true}) 

情况五:监视reactive定义的响应式数据中的某些属性

如果要监视对象里的多个属性,一样写成数组的形式

watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{
	console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})

watchEffect函数

watch的套路是:既要指明监视的属性,也要指明监视的回调。

 watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。

-watchEffect有点像computed:

   但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
   而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
  watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。

//watchEffect的回调一上来会先执行一次
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(()=>{
    const x1 = sum.value
    const x2 = person.age
    console.log('watchEffect配置的回调执行了')
})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值