vue3 响应式原理

对于 vue3 来说,他的响应性核心 API 是 Proxy ,通过该 API 可以监听到具体某一个属性的 getter 和 setter。

因为 vue3 是通过 Proxy 代理对象去实现的响应性,所以不会出现新增属性丢失响应性的问题。

<template>
  <div id="app">
    <div v-for="(value, key, index) in obj" :key="index">
      <p>{{ key }}-{{ value }}-{{ index }}</p>
    </div>

    <button @click="onAdd">点击</button>
    <button @click="onAddVal">修改值</button>
  </div>
</template>

<script>
export default {
  name: 'app',
  data() {
    return {
      obj: {
        name: '张三'
      }
    }
  },
  methods: {
    onAdd() {
      this.obj.age = 30
    },
    onAddVal() {
      this.obj.age = 38
    }
  }
}
</script>

<style></style>

通过 Proxy 代理对象得到的响应式,不能解构,一旦解构就会数去响应性

<template>
  <div id="app">
    <div v-for="(value, key, index) in obj" :key="index">
      <p>{{ key }}-{{ value }}-{{ index }}</p>
    </div>

    <button @click="onAdd">点击</button>
    <button @click="onAddVal">修改值</button>
  </div>
</template>

<script>
export default {
  name: 'app',
  data() {
    return {
      obj: {
        name: '张三'
      }
    }
  },
  methods: {
    onAdd() {
      this.obj.age = 30
    },
    onAddVal() {
      let { age } = this.obj
      age = 38
    }
  }
}
</script>

<style></style>

语法

  1. options ApI:

  2. composition API : 组合式 API ,没有 this。改变仅针对于 script

    声明响应性对象 obj

    1. setup 函数:

      1. 想要让响应式数据或方法被模板( tempalte )使用,那么方式分为三步:

        1. 声明响应式数据或方法

        2. 在 setup 函数中,return 一个对象,对象中包含这个数据或方法,setup直接触发,可以将 setup 理解成 created

        3. 在 tempalte 中使用

      2. 缺点:当页面数据很多的时候,很看起来很臃肿,不利于观看

<template>
  <div id="app">
    <div v-for="(value, key, index) in obj" :key="index">
      <p>{{ key }}-{{ value }}-{{ index }}</p>
    </div>

    <button @click="onAdd">点击</button>
    <button @click="onAddVal">修改值</button>
  </div>
</template>

<script>
import { reactive } from 'vue'
export default {
  // 导入 reactive
  // 利用 reactive 生成 porxy 代理对象
  // 在 setup 中 return { },对象中包含 生成的 proxy 代理对象
  // 这样才可以在 template 中访问
  setup() {
    // 声明响应性对象
    const obj = reactive({
      name: '张三'
    })

    const onAdd = () => {
      obj.age = 18
    }

    const onAddVal = () => {
      obj.age = 50
    }
    return {
      obj,
      onAdd,
      onAddVal
    }
  }
}
</script>

<style></style>
  1. script setup 重要

    1. 想要让响应式数据或方法被模板( tempalte )使用,那么方式分为两步:

      1. 声明响应式数据或方法

      2. 在 tempalte 中使用

改进之后的代码如下:

<template>
  <div id="app">
    <div v-for="(value, key, index) in obj" :key="index">
      <p>{{ key }}-{{ value }}-{{ index }}</p>
    </div>

    <button @click="onAdd">点击</button>
  </div>
</template>

<script setup>
import { reactive } from 'vue'

const obj = reactive({
  name: '张三'
})

const onAdd = () => {
  obj.age = 18
}
</script>

<style></style>

vue3中 有两种响应式数据的方式

  1. reactive: 因为他是基于 proxy 实现的,所以它只能声明复杂数据类型的响应性

  2. ref: 可以声明 任意 数据类型的响应。在script 中使用 ref 声明的数据,必须要通过 .value 访问。

<template>
  <div id="app">
    <div>{{ name }}</div>
    <button @click="onAdd">点击</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const name = ref('张三')
const onAdd = () => {
  name.value = '李思'
}
</script>

<style></style>

因为proxy比ref更消耗性能,所以使用ref

vue源码类似于

<script>
    // const ref = (value) => {
    //     const obj = {
    //         value
    //     }
    //     return new Proxy(obj, {
    //         get(target, key) {
    //             console.log('get');
    //             return target[key]
    //         }
    //     })
    // }

    class RefImpl {
        constructor(val) {
            this.val = val
        }

        // name.value ===  name.value()
        get value() {
            console.log('get');
            return this.val
        }

        set value(val) {
            console.log('set');
            this.val = val
        }
    }

    const ref = (val) => {
        return new RefImpl(val)
    }
    const name = ref('张三')
    console.log(name.value);

    name.value = '李四'
    console.log(name.value);

</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值