前端

梗概:

  • 底层使用js原生的Proxy对象来拦截变量的访问与赋值
  • 当在某个函数引用了响应式变量时, Vue将会执行track过程, 将该函数记录起来
  • 响应式变量更新的时候, Vue将会执行trigger过程, 实现响应式
  • 比较复杂的对象中的属性也是支持响应式的trigger的
    • Map键值对中的值
    • 但是闭包内的变量不行
      • 毕竟是封闭在函数内部的,可以理解

实例

组件模板中引用响应式变量

child::

组件模板中调用响应式变量

指向原始笔记的链接

Map对象的响应式

<template>
  <div v-for="(map, index) of mapList">
    {{ index }} : {{ map.get(`test${index}`) }}
  </div>
  <button @click="mapList[1].set('test1', 'v2')"></button>
</template>
<script setup>
import { ref } from "vue";
 
let mapList = ref([]);
for (let i = 0; i < 3; i++) {
  mapList.value.push(new Map([["test" + i, "v" + i]]));
}
</script>
<style scoped></style>
 
  • 能够监听map对象的值的变化

类与闭包的响应式

<template>
  <div>count: {{ obj.count }}</div>
  <button @click="obj.addCount()"></button>
  <div>packCount: {{ pack.getPackCount() }}</div>
  <button @click="console.log(pack.addPackCount())"></button>
</template>
<script setup>
import { ref } from "vue";
 
class MyObj {
  count = 0;
  addCount() {
    this.count++;
  }
  packCount() {
    let selfCount = 0;
    return {
      addPackCount() {
        selfCount++;
        return selfCount;
      },
      getPackCount() {
        return selfCount;
      },
    };
  }
}
let obj = ref(new MyObj());
let pack = obj.value.packCount();
</script>
  • 能够监听类中属性的变量
  • 但是不能监听闭包中变量的变化

真实的响应式结构

<script setup lang="ts">
import reactive from "@/components/reactive.vue";
import { getCurrentInstance, onMounted, ref } from "vue";
let rea = ref();
function show() {
  console.log("component ref:\n", rea.value);
  console.log("component's count:\n", rea.value.count);
  console.log("component's obj\n", rea.value.obj);
  console.log("component's refObj\n", rea.value.refObj);
}
</script>
  
<template>
  <reactive ref="rea"></reactive>
  <button @click="show">show</button>
</template>
  
<style scoped></style>

子组件:

<template></template>
  
<script setup lang="ts">
import { ref, reactive } from "vue";
let count = ref(0);
let obj = reactive({
  message: "outside",
  obj2: {
    message: "inside",
  },
});
let refObj = ref({
  message: "outside",
  obj2: {
    message: "inside",
  },
});
function say() {
  count.value++;
  obj.message = "inside";
  obj.obj2.message = "outside";
}
defineExpose({ count, obj, say, refObj });
</script>
<style></style>

|