Web front-end vue3


vue3 responsive data judgment, isRef, isReactive, isReadonly, isProxy, ref, reactive, readonly

import {
    
    
  defineComponent,
  isProxy,
  isReactive,
  isReadonly,
  isRef,
  reactive,
  readonly,
  ref,
} from "vue";
export default defineComponent({
    
    
  name: "App",
  // isRef: 检查一个值是否为一个 ref 对象
  // isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
  // isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
  // isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理

  setup() {
    
    
    // isRef: 检查一个值是否为一个 ref 对象
    console.log(isRef(ref({
    
    }))); // true
    // isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
    console.log(isReactive(reactive({
    
    }))); // true
    // isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
    console.log(isReadonly(readonly({
    
    }))); // true
    // isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理
    console.log(isProxy(readonly({
    
    }))); // true
    console.log(isProxy(reactive({
    
    }))); // true

    return {
    
    };
  },
});

vue3 life cycle

1. Parent component

<template>
	<h2>App</h2>
	<button @click="isShow=!isShow">切换</button>
	<hr>
	<Child v-if="isShow"/>
</template>

import Child from './Child.vue';

export default {
    
    
  data () {
    
    
    return {
    
    
      isShow: true
    }
  },
  components: {
    
    
    Child
  }
};

2. Subcomponents

<template>
	<div class="about">
		<h2>msg: {
   
   {msg}}</h2>
		<hr>
		<button @click="update">更新</button>
	</div>
</template>

import {
    
    
  ref,
  onMounted,
  onUpdated,
  onUnmounted, 
  onBeforeMount, 
  onBeforeUpdate,
  onBeforeUnmount
} from "vue";

export default {
    
    
  beforeCreate () {
    
    
    console.log('2.xbeforeCreate()')
  },

  created () {
    
    
    console.log('2.xcreated')
  },

  beforeMount () {
    
    
    console.log('2.xbeforeMount')
  },

  mounted () {
    
    
    console.log('2.xmounted')
  },

  beforeUpdate () {
    
    
    console.log('2.xbeforeUpdate')
  },

  updated () {
    
    
    console.log('2.xupdated')
  },

  beforeUnmount () {
    
    
    console.log('2.xbeforeUnmount')
  },

  unmounted () {
    
    
     console.log('2.xunmounted')
  },
  
  setup() {
    
    
    const msg = ref('abc');
    const update = () => {
    
    
      msg.value += '--';
    };

    onBeforeMount(() => {
    
    
      console.log('3.0--onBeforeMount')
    });

    onMounted(() => {
    
    
      console.log('3.0--onMounted')
    });

    onBeforeUpdate(() => {
    
    
      console.log('3.0--onBeforeUpdate')
    });

    onUpdated(() => {
    
    
      console.log('3.0--onUpdated')
    });

    onBeforeUnmount(() => {
    
    
      console.log('3.0--onBeforeUnmount')
    });

    onUnmounted(() => {
    
    
      console.log('3.0--onUnmounted')
    });
    
    return {
    
    
      msg,
      update
    };
  }
};

3. 2.x and 3.x life cycle execution order

The life cycle execution order in 3.x is faster than that in 2.x, that is, it is executed before the life cycle in 2.x.


vue3 handwritten isRef, isReactive, isReadonly, isProxy

1. Functions and functions included

isRef、isReactive、isReadonly、isProxy、shallowReactive、reactive、shallowReadonly、readonly、shallowRef、ref


2. Function implementation

// 定义一个reactiveHandler处理对象
const reactiveHandler = {
    
    
  // 获取属性值
  get(target, prop) {
    
    
    if (prop === '_is_reactive') return true;
    const result = Reflect.get(target, prop);
    console.log('拦截了读取数据', prop, result);
    return result;
  },
  // 修改属性值或者是添加属性
  set(target, prop, value) {
    
    
    const result = Reflect.set(target, prop, value);
    console.log('拦截了修改数据或者是添加属性', prop, value);
    return result;
  },
  // 删除某个属性
  deleteProperty(target, prop) {
    
    
    const result = Reflect.deleteProperty(target, prop);
    console.log('拦截了删除数据', prop);
    return result;
  }
}

// 01--------------------------------------
// shallowReactive
// 定义一个shallowReactive函数,传入一个目标对象
function shallowReactive(target) {
    
    
  // 判断当前的目标对象是不是object类型(对象/数组)
  if (target && typeof target === 'object') {
    
    
    return new Proxy(target, reactiveHandler);
  }
  // 如果传入的数据是基本类型的数据,那么就直接返回
  return target;
}

// 02--------------------------------------
// reactive
// 定义一个reactive函数,传入一个目标对象
function reactive(target) {
    
    
  // 判断当前的目标对象是不是object类型(对象/数组)
  if (target && typeof target === 'object') {
    
    
    // 对数组或者是对象中所有的数据进行reactive的递归处理
    // 先判断当前的数据是不是数组
    if (Array.isArray(target)) {
    
    
      // 数组的数据要进行遍历操作0
      target.forEach((item, index) => {
    
    
        // 如果数组中还有数组
        // 使用递归
        target[index] = reactive(item);
      });
    } else {
    
    
      // 再判断当前的数据是不是对象
      // 对象的数据也要进行遍历的操作
      Object.keys(target).forEach(key => {
    
    
        target[key] = reactive(target[key]);
      });
    }
    return new Proxy(target, reactiveHandler);
  }
  // 如果传入的数据是基本类型的数据,那么就直接返回
  return target;
}

// ===============================================================
// 定义了一个readonlyHandler处理器
const readonlyHandler = {
    
    
  get(target, prop) {
    
    
    if (prop === '_is_readonly') return true;
    const result = Reflect.get(target, prop);
    console.log('拦截到了读取数据了', prop, result);
    return result;
  },
  set(target, prop, value) {
    
    
    console.warn('只能读取数据,不能修改数据或者添加数据');
    return true;
  },
  deleteProperty(target, prop) {
    
    
    console.warn('只能读取数据,不能删除数据');
    return true;
  }
}

// 03--------------------------------------
// shallowReadonly
// 定义一个shallowReadonly函数
function shallowReadonly(target) {
    
    
  // 需要判断当前的数据是不是对象
  if (target && typeof target === 'object') {
    
    
    return new Proxy(target, readonlyHandler);
  }
  return target;
}

// 04--------------------------------------
// readonly
// 定义一个readonly函数
function readonly(target) {
    
    
  // 需要判断当前的数据是不是对象
  if (target && typeof target === 'object') {
    
    
    // 判断target是不是数组
    if (Array.isArray(target)) {
    
    
      // 遍历数组
      target.forEach((item, index) => {
    
    
        target[index] = readonly(item);
      });
    } else {
    
    
      // 判断target是不是对象
      // 遍历对象
      Object.keys(target).forEach(key => {
    
    
        target[key] = readonly(target[key]);
      });
    }
    return new Proxy(target, readonlyHandler);
  }
  // 如果不是对象或者数组,那么直接返回
  return target;
}

// ===============================================================
// 05--------------------------------------
// shallowRef
// 定义一个shallowRef函数
function shallowRef(target) {
    
    
  return {
    
    
    // 保存target数据保存起来
    _value: target,
    get value() {
    
    
      console.log('劫持到了读取数据');
      return this._value;
    },
    set value(val) {
    
    
      console.log('劫持到了修改数据,准备更新界面', val);
      this._value = val;
    }
  }
}

// 06--------------------------------------
// ref
// 定义一个ref函数
function ref(target) {
    
    
  target = reactive(target);
  return {
    
    
    _is_ref: true, // 标识当前的对象是ref对象
    // 保存target数据保存起来
    _value: target,
    get value() {
    
    
      console.log('劫持到了读取数据');
      return this._value;
    },
    set value(val) {
    
    
      console.log('劫持到了修改数据,准备更新界面', val);
      this._value = val;
    }
  }
}

// ===============================================================
// 定义一个函数isRef,判断当前的对象是不是ref对象
function isRef(obj) {
    
    
  return obj && obj._is_ref;
}

// 定义一个函数isReactive,判断当前的对象是不是reactive对象
function isReactive(obj) {
    
    
  return obj && obj._is_reactive;
}

// 定义一个函数isReadonly,判断当前的对象是不是readonly对象
function isReadonly(obj) {
    
    
  return obj && obj._is_readonly;
}

// 定义一个函数isProxy,判断当前的对象是不是reactive对象或者readonly对象
function isProxy(obj) {
    
    
  return isReactive(obj) || isReadonly(obj);
}

3. Function call

// 01--------------------------------------
// shallowReactive
const proxyUser1 = shallowReactive({
    
    
  name: '小明',
  car: {
    
    
    color: 'red'
  }
});
// 拦截到了读和写的数据
proxyUser1.name += '==';
// 拦截到了读取数据,但是拦截不到写的数据
proxyUser1.car.color + '==';
// 拦截到了删除数据
delete proxyUser1.name;
// 只拦截到了读,但是拦截不到删除
delete proxyUser1.car.color;

// 02--------------------------------------
// reactive
const proxyUser2 = reactive({
    
    
  name: '小明',
  car: {
    
    
    color: 'red'
  }
});
// 拦截到了读和修改的数据
proxyUser2.name += '==';
// 拦截到了读和修改的数据
proxyUser2.car.color = '==';
// 拦截了删除
delete proxyUser2.name;
// 拦截到了读和拦截到了删除
delete proxyUser2.car.color;

// 03--------------------------------------
// shallowReadonly
const proxyUser3 = shallowReadonly({
    
    
  name: '小明',
  cars: ['奔驰', '宝马']
});
// 可以读取
console.log(proxyUser3.name);
// 不能修改
proxyUser3.name = '==';
// 不能删除
delete proxyUser3.name;
// 拦截到了读取,可以修改
proxyUser3.cars[0] = '奥迪';
// 拦截到了读取,可以删除
delete proxyUser3.cars[0];

// 04--------------------------------------
// readonly
const proxyUser4 = readonly({
    
    
  name: '小明',
  cars: ['奔驰', '宝马']
});
// 拦截到了读取
console.log(proxyUser4.name);
console.log(proxyUser4.cars[0]);
// 只读的
proxyUser4.name = '哈哈';
// 只读的
proxyUser4.cars[0] = '哈哈';
delete proxyUser4.name;
delete proxyUser4.cars[0];

// 05--------------------------------------
// shallowRef
const ref1 = shallowRef({
    
    
  name: '小明',
  car: {
    
    
    color: 'red'
  }
});
console.log(ref1.value);
// 劫持到
ref1.value = '==';
// 劫持不到
ref1.value.car = '==';

// 06--------------------------------------
// ref
const ref2 = ref({
    
    
  name: '小明',
  car: {
    
    
    color: 'red'
  }
});
console.log(ref2.value);
// 劫持到
ref2.value = '==';
// 劫持到
ref2.value.car = '==';

// 07--------------------------------------
console.log(isRef(ref({
    
    })));
console.log(isReactive(reactive({
    
    })));
console.log(isReadonly(readonly({
    
    })));
console.log(isProxy(reactive({
    
    })));
console.log(isProxy(readonly({
    
    })));

vue3 handwritten ref, deep ref

1. Function implementation

// 定义一个reactive函数,传入一个目标对象
function reactive(target) {
    
    
  // 判断当前的目标对象是不是object类型(对象/数组)
  if (target && typeof target === 'object') {
    
    
    // 对数组或者是对象中所有的数据进行reactive的递归处理
    // 先判断当前的数据是不是数组
    if (Array.isArray(target)) {
    
    
      // 数组的数据要进行遍历操作0
      target.forEach((item, index) => {
    
    
        // 如果数组中还有数组
        // 使用递归
        target[index] = reactive(item);
      });
    } else {
    
    
      // 再判断当前的数据是不是对象
      // 对象的数据也要进行遍历的操作
      Object.keys(target).forEach(key => {
    
    
        target[key] = reactive(target[key]);
      });
    }
    return new Proxy(target, reactiveHandler);
  }
  // 如果传入的数据是基本类型的数据,那么就直接返回
  return target;
}

// 定义一个ref函数
function ref(target) {
    
    
  target = reactive(target);
  return {
    
    
    _is_ref: true, // 标识当前的对象是ref对象
    // 保存target数据保存起来
    _value: target,
    get value() {
    
    
      console.log('劫持到了读取数据');
      return this._value;
    },
    set value(val) {
    
    
      console.log('劫持到了修改数据,准备更新界面', val);
      this._value = val;
    }
  }
}

2. Function call

const ref2 = ref({
    
    
      name: '小明',
      car: {
    
    
        color: 'red'
      }
});
console.log(ref2.value);
// 劫持到
ref2.value = '==';
// 劫持到
ref2.value.car = '==';

vue3 handwritten shallowRef, shallow ref

1. Function implementation

// 定义一个shallowRef函数
function shallowRef(target) {
    
    
  return {
    
    
    // 保存target数据保存起来
    _value: target,
    get value() {
    
    
      console.log('劫持到了读取数据');
      return this._value;
    },
    set value(val) {
    
    
      console.log('劫持到了修改数据,准备更新界面', val);
      this._value = val;
    }
  }
}

2. Function call

const ref1 = shallowRef({
    
    
      name: '小明',
      car: {
    
    
        color: 'red'
      }
});
console.log(ref1.value);
// 劫持到
ref1.value = '==';
// 劫持不到
ref1.value.car = '==';

vue3customRef

1. Concept

Create a custom ref with explicit control over its dependency tracking and update triggering.


2. Code example
Requirements

Example of using customRef to implement debounce.


<template>
  <h2>CustomRef的使用</h2>
  <input type="text" v-model="keyword" />
  <p>{
   
   { keyword }}</p>
</template>

import {
    
     customRef, defineComponent, ref } from "vue";
// 自定义hook防抖的函数
// value传入的数据,将来数据的类型不确定,所以,用泛型,delay防抖的间隔时间.默认是200毫秒
function useDebouncedRef<T>(value: T, delay = 200) {
    
    
  // 准备一个存储定时器的id的变量
  let timeOutId: number;
  return customRef((track, trigger) => {
    
    
    return {
    
    
      // 返回数据的
      get() {
    
    
        // 告诉Vue追踪数据
        track();
        return value;
      },
      // 设置数据的
      set(newValue: T) {
    
    
        // 清理定时器
        clearTimeout(timeOutId);
        // 开启定时器
        timeOutId = setTimeout(() => {
    
    
          value = newValue;
          // 告诉Vue更新界面
          trigger();
        }, delay);
      },
    };
  });
}

export default defineComponent({
    
    
  name: "App",
  setup() {
    
    
    // const keyword = ref('abc')
    const keyword = useDebouncedRef("abc", 500);
    return {
    
    
      keyword,
    };
  },
});

vue3readonly与shallowReadonly

1. Concept

readonly
○Deep read-only data.
○ Get an object (reactive or plain object) or ref and return a read-only proxy of the original proxy.
○Read-only proxies are deep: any nested properties accessed are also read-only.
shallowReadonly
○Shallow read-only data.
○ Create a proxy that makes its own properties read-only, but does not perform deep read-only conversions of nested objects.
应用场景
○In some specific cases, we may not want to update the data, so we can package and generate a read-only proxy object to read Data can be retrieved but cannot be modified or deleted.


2. Sample code

<template>
  <h2>readonly和shallowReadonly</h2>
  <h3>state:{
   
   { state2 }}</h3>
  <hr />
  <button @click="update">更新数据</button>
</template>

import {
    
     defineComponent, reactive, readonly, shallowReadonly } from "vue";

export default defineComponent({
    
    
  name: "App",
  setup() {
    
    
    const state = reactive({
    
    
      name: "佐助",
      age: 20,
      car: {
    
    
        name: "奔驰",
        color: "yellow",
      },
    });
    // 只读的数据---深度的只读
    // const state2 = readonly(state)
    // 只读的数据---浅只读的
    const state2 = shallowReadonly(state);
    const update = () => {
    
    
      // state2.name += '==='
      // state2.car.name += '=='

      // state2.name+='==='
      state2.car.name += "===";
    };
    return {
    
    
      state2,
      update,
    };
  },
});

vue3toRaw and markRaw

1. Concept

toRaw
Returns a plain object converted into a reactive proxy by reactive or readonly methods.
This is a restore method that can be used for temporary reads, access will not be proxied/tracked, and interface updates will not be triggered when writing.
markRaw
Marks an object so that it will never be converted to a proxy. Returns the object itself.
应用场景
Some values ​​should not be set reactive, such as complex third-party class instances or Vue component objects.
Skipping proxy conversion can improve performance when rendering large lists with immutable data sources.


2, example example
html

<template>
  <h2>toRaw和markRaw</h2>
  <h3>state:{
   
   { state }}</h3>
  <hr />
  <button @click="testToRaw">测试toRaw</button>
  <button @click="testMarkRaw">测试markRaw</button>
</template>

JavaScrip

import {
    
     defineComponent, markRaw, reactive, toRaw } from "vue";

interface UserInfo {
    
    
  name: string;
  age: number;
  likes?: string[];
}

export default defineComponent({
    
    
  name: "App",
  setup() {
    
    
    const state = reactive<UserInfo>({
    
    
      name: "小明",
      age: 20,
    });

    const testToRaw = () => {
    
    
      // 把代理对象变成了普通对象了,数据变化,界面不变化
      const user = toRaw(state);
      user.name += "==";
      console.log("哈哈,我好帅哦");
    };
    const testMarkRaw = () => {
    
    
      // state.likes = ['吃', '喝']
      // state.likes[0] += '=='
      // console.log(state)
      const likes = ["吃", "喝"];
      // markRaw标记的对象数据,从此以后都不能再成为代理对象了
      state.likes = markRaw(likes);
      setInterval(() => {
    
    
        if (state.likes) {
    
    
          state.likes[0] += "=";
          console.log("定时器走起来");
        }
      }, 1000);
    };
    return {
    
    
      state,
      testToRaw,
      testMarkRaw,
    };
  },
});

vue3 handwritten reactive, deep hijacking, deep monitoring, deep response data

1. Function implementation

// 定义一个reactive函数,传入一个目标对象
function reactive(target) {
    
    
  // 判断当前的目标对象是不是object类型(对象/数组)
  if (target && typeof target === 'object') {
    
    
    // 对数组或者是对象中所有的数据进行reactive的递归处理
    // 先判断当前的数据是不是数组
    if (Array.isArray(target)) {
    
    
      // 数组的数据要进行遍历操作0
      target.forEach((item, index) => {
    
    
        // 如果数组中还有数组
        // 使用递归
        target[index] = reactive(item);
      });
    } else {
    
    
      // 再判断当前的数据是不是对象
      // 对象的数据也要进行遍历的操作
      Object.keys(target).forEach(key => {
    
    
        target[key] = reactive(target[key]);
      });
    }
    return new Proxy(target, reactiveHandler);
  }
  // 如果传入的数据是基本类型的数据,那么就直接返回
  return target;
}

// 定义一个reactiveHandler处理对象
const reactiveHandler = {
    
    
  // 获取属性值
  get(target, prop) {
    
    
    if (prop === '_is_reactive') return true;
    const result = Reflect.get(target, prop);
    console.log('拦截了读取数据', prop, result);
    return result;
  },
  // 修改属性值或者是添加属性
  set(target, prop, value) {
    
    
    const result = Reflect.set(target, prop, value);
    console.log('拦截了修改数据或者是添加属性', prop, value);
    return result;
  },
  // 删除某个属性
  deleteProperty(target, prop) {
    
    
    const result = Reflect.deleteProperty(target, prop);
    console.log('拦截了删除数据', prop);
    return result;
  }
}

2. Call function

const proxyUser2 = reactive({
    
    
      name: '小明',
      car: {
    
    
        color: 'red'
      }
});
// 拦截到了读和修改的数据
proxyUser2.name += '==';
// 拦截到了读和修改的数据
proxyUser2.car.color = '==';
// 拦截了删除
delete proxyUser2.name;
// 拦截到了读和拦截到了删除
delete proxyUser2.car.color;

Vue3's ref gets the element

1. Concept

Use the ref function to get the label element in the component.


2. Sample code
Functional requirements

Let the input box automatically gain focus.


<template>
  <h2>ref的另一个作用:可以获取页面中的元素</h2>
  <input type="text" ref="inputRef" />
</template>

import {
    
     defineComponent, onMounted, ref } from "vue";
export default defineComponent({
    
    
  name: "App",

  // 需求:当页面加载完毕后,页面中的文本框可以直接获取焦点(自动获取焦点)

  setup() {
    
    
    // 默认是空的,页面加载完毕,说明组件已经存在了,获取文本框元素
    const inputRef = ref<HTMLElement | null>(null);
    // 页面加载后的生命周期组合API
    onMounted(() => {
    
    
      inputRef.value && inputRef.value.focus(); // 自动获取焦点
    });
    return {
    
    
      inputRef,
    };
  },
});

vue3 handwritten reactive, deep hijacking, deep monitoring, deep response data

1. Function implementation

// 定义一个reactive函数,传入一个目标对象
function reactive(target) {
    
    
  // 判断当前的目标对象是不是object类型(对象/数组)
  if (target && typeof target === 'object') {
    
    
    // 对数组或者是对象中所有的数据进行reactive的递归处理
    // 先判断当前的数据是不是数组
    if (Array.isArray(target)) {
    
    
      // 数组的数据要进行遍历操作0
      target.forEach((item, index) => {
    
    
        // 如果数组中还有数组
        // 使用递归
        target[index] = reactive(item);
      });
    } else {
    
    
      // 再判断当前的数据是不是对象
      // 对象的数据也要进行遍历的操作
      Object.keys(target).forEach(key => {
    
    
        target[key] = reactive(target[key]);
      });
    }
    return new Proxy(target, reactiveHandler);
  }
  // 如果传入的数据是基本类型的数据,那么就直接返回
  return target;
}

// 定义一个reactiveHandler处理对象
const reactiveHandler = {
    
    
  // 获取属性值
  get(target, prop) {
    
    
    if (prop === '_is_reactive') return true;
    const result = Reflect.get(target, prop);
    console.log('拦截了读取数据', prop, result);
    return result;
  },
  // 修改属性值或者是添加属性
  set(target, prop, value) {
    
    
    const result = Reflect.set(target, prop, value);
    console.log('拦截了修改数据或者是添加属性', prop, value);
    return result;
  },
  // 删除某个属性
  deleteProperty(target, prop) {
    
    
    const result = Reflect.deleteProperty(target, prop);
    console.log('拦截了删除数据', prop);
    return result;
  }
}

2. Call function

const proxyUser2 = reactive({
    
    
      name: '小明',
      car: {
    
    
        color: 'red'
      }
});
// 拦截到了读和修改的数据
proxyUser2.name += '==';
// 拦截到了读和修改的数据
proxyUser2.car.color = '==';
// 拦截了删除
delete proxyUser2.name;
// 拦截到了读和拦截到了删除
delete proxyUser2.car.color;

vue3 handwritten readonly, deep read-only

1. Function implementation

// 定义了一个readonlyHandler处理器
const readonlyHandler = {
    
    
  get(target, prop) {
    
    
    if (prop === '_is_readonly') return true;
    const result = Reflect.get(target, prop);
    console.log('拦截到了读取数据了', prop, result);
    return result;
  },
  set(target, prop, value) {
    
    
    console.warn('只能读取数据,不能修改数据或者添加数据');
    return true;
  },
  deleteProperty(target, prop) {
    
    
    console.warn('只能读取数据,不能删除数据');
    return true;
  }
}

// 定义一个readonly函数
function readonly(target) {
    
    
  // 需要判断当前的数据是不是对象
  if (target && typeof target === 'object') {
    
    
    // 判断target是不是数组
    if (Array.isArray(target)) {
    
    
      // 遍历数组
      target.forEach((item, index) => {
    
    
        target[index] = readonly(item);
      });
    } else {
    
    
      // 判断target是不是对象
      // 遍历对象
      Object.keys(target).forEach(key => {
    
    
        target[key] = readonly(target[key]);
      });
    }
    return new Proxy(target, readonlyHandler);
  }
  // 如果不是对象或者数组,那么直接返回
  return target;
}

2. Function call

const proxyUser4 = readonly({
    
    
      name: '小明',
      cars: ['奔驰', '宝马']
});
// 拦截到了读取
console.log(proxyUser4.name);
console.log(proxyUser4.cars[0]);
// 只读的
proxyUser4.name = '哈哈';
// 只读的
proxyUser4.cars[0] = '哈哈';
delete proxyUser4.name;
delete proxyUser4.cars[0];

vue3 handwritten shallowReactive, shallow hijacking, shallow monitoring, shallow response data

1. Function implementation

// 定义一个reactiveHandler处理对象
const reactiveHandler = {
    
    
  // 获取属性值
  get(target, prop) {
    
    
    if (prop === '_is_reactive') return true;
    const result = Reflect.get(target, prop);
    console.log('拦截了读取数据', prop, result);
    return result;
  },
  // 修改属性值或者是添加属性
  set(target, prop, value) {
    
    
    const result = Reflect.set(target, prop, value);
    console.log('拦截了修改数据或者是添加属性', prop, value);
    return result;
  },
  // 删除某个属性
  deleteProperty(target, prop) {
    
    
    const result = Reflect.deleteProperty(target, prop);
    console.log('拦截了删除数据', prop);
    return result;
  }
}

// 定义一个shallowReactive函数,传入一个目标对象
function shallowReactive(target) {
    
    
  // 判断当前的目标对象是不是object类型(对象/数组)
  if (target && typeof target === 'object') {
    
    
    return new Proxy(target, reactiveHandler);
  }
  // 如果传入的数据是基本类型的数据,那么就直接返回
  return target;
}

2. Function call

const proxyUser1 = shallowReactive({
    
    
      name: '小明',
      car: {
    
    
        color: 'red'
      }
});
// 拦截到了读和写的数据
proxyUser1.name += '==';
// 拦截到了读取数据,但是拦截不到写的数据
proxyUser1.car.color + '==';
// 拦截到了删除数据
delete proxyUser1.name;
// 只拦截到了读,但是拦截不到删除
delete proxyUser1.car.color;

vue3provide and inject, realize communication between cross-level components, ancestor and grandchild components

1. Grandpa component (page)
1.1. html part

<template>
  <h2>provide 与 inject</h2>
  <p>当前的颜色:{
   
   { color }}</p>
  <button @click="color = 'red'">红色</button>
  <button @click="color = 'yellow'">黄色</button>
  <button @click="color = 'green'">绿色</button>
  <hr />
  <Son />
</template>

1.2. Typescript part

import {
    
     defineComponent, provide, ref } from "vue";
import Son from "./components/Son.vue";
export default defineComponent({
    
    
  name: "App",
  components: {
    
    
    Son,
  },
  setup() {
    
    
    // 响应式的数据
    const color = ref("red");
    // 提供数据
    provide("color", color);
    return {
    
    
      color,
    };
  },
});

2, father composition
2.1, html part

<template>
  <h3>Son子级组件</h3>
  <hr />
  <GrandSon />
</template>

2.2. Typescript part

import {
    
     defineComponent } from "vue";
import GrandSon from "./GrandSon.vue";
export default defineComponent({
    
    
  name: "Son",
  components: {
    
    
    GrandSon,
  },
});

3. Sun Tzu component
3.1. HTML part

<template>
  <h3 :style="{ color }">GrandSon孙子组件</h3>
</template>

3.2. Typescript part

import {
    
     defineComponent, inject } from "vue";
export default defineComponent({
    
    
  name: "GrandSon",
  setup() {
    
    
    // 注入的操作
    const color = inject("color");
    return {
    
    
      color,
    };
  },
});

vue3shallowReactive与shallowRef

1. Concept

shallowReactive: A responsive style that only processes the outermost attributes of the object, that is, a shallow responsive style.
shallowRef: Only handles the responsiveness of value, and does not perform reactive processing of objects.
●When should I use shallow responsiveness?
○Generally, use ref and reactive.
○If the structure of an object data is relatively deep, but only the outer attributes change when changing, use shallowReactive.
○If there is an object data, a new object will be generated later to replace it shallowRef.


2. Sample code

<template>
  <h2>shallowReactive和shallowRef</h2>
  <h3>m1:{
   
   { m1 }}</h3>
  <h3>m2:{
   
   { m2 }}</h3>
  <h3>m3:{
   
   { m3 }}</h3>
  <h3>m4:{
   
   { m4 }}</h3>
  <hr />
  <button @click="update">更新数据</button>
</template>

import {
    
    
  defineComponent,
  reactive,
  ref,
  shallowReactive,
  shallowRef,
} from "vue";

export default defineComponent({
    
    
  name: "App",
  setup() {
    
    
    // 深度劫持(深监视)----深度响应式
    const m1 = reactive({
    
    
      name: "鸣人",
      age: 20,
      car: {
    
    
        name: "奔驰",
        color: "red",
      },
    });
    // 浅劫持(浅监视)----浅响应式
    const m2 = shallowReactive({
    
    
      name: "鸣人",
      age: 20,
      car: {
    
    
        name: "奔驰",
        color: "red",
      },
    });
    // 深度劫持(深监视)----深度响应式----做了reactive的处理
    const m3 = ref({
    
    
      name: "鸣人",
      age: 20,
      car: {
    
    
        name: "奔驰",
        color: "red",
      },
    });
    // 浅劫持(浅监视)----浅响应式
    const m4 = shallowRef({
    
    
      name: "鸣人",
      age: 20,
      car: {
    
    
        name: "奔驰",
        color: "red",
      },
    });
    const update = () => {
    
    
      // 更改m1的数据---reactive方式
      // m1.name += '=='
      // m1.car.name += '=='
      // 更改m2的数据---shallowReactive
      // m2.name += '=='
      // m2.car.name += '==='
      // 更改m3的数据---ref方式
      // m3.value.name += '==='
      // m3.value.car.name += '==='
      // 更改m4的数据---shallowRef方式
      // m4.value.name += '==='
      // m4.value.name += '==='
      console.log(m3, m4);
    };
    return {
    
    
      m1,
      m2,
      m3,
      m4,
      update,
    };
  },
});

vue3toRefs

1. Concept

Convert a responsive object into a normal object. Each property of the normal object is a ref.
应用:ToRefs is very useful when returning a reactive object from a composite function, so that the consuming component can decompose the returned object without losing the reactivity.
问题:All attribute values ​​taken out by the reactive object are non-responsive.
解决:Use toRefs to convert all original properties of a responsive reactive object into responsive ref properties.


2. Sample code

<template>
  <h2>toRefs的使用</h2>
  <!-- <h3>name:{
    
    { state.name }}</h3>
  <h3>age:{
    
    { state.age }}</h3> -->

  <h3>name:{
   
   { name }}</h3>
  <h3>age:{
   
   { age }}</h3>

  <h3>name2:{
   
   { name2 }}</h3>
  <h3>age2:{
   
   { age2 }}</h3>
</template>

import {
    
     defineComponent, reactive, toRefs } from "vue";

function useFeatureX() {
    
    
  const state = reactive({
    
    
    name2: "自来也",
    age2: 47,
  });
  return {
    
    
    ...toRefs(state),
  };
}

export default defineComponent({
    
    
  name: "App",
  setup() {
    
    
    const state = reactive({
    
    
      name: "自来也",
      age: 47,
    });
    // toRefs可以把一个响应式对象转换成普通对象,该普通对象的每个 property 都是一个 ref
    // const state2 = toRefs(state)
    const {
    
     name, age } = toRefs(state);
    // console.log(state2)
    // 定时器,更新数据,(如果数据变化了,界面也会随之变化,肯定是响应式的数据)
    setInterval(() => {
    
    
      // state.name += '=='
      // state2.name.value+='==='
      name.value += "===";
      console.log("======");
    }, 1000);

    const {
    
     name2, age2 } = useFeatureX();
    return {
    
    
      // state,
      // 下面的方式不行啊
      // ...state // 不是响应式的数据了---->{name:'自来也',age:47}
      // ...state2  toRefs返回来的对象
      name,
      age,
      name2,
      age2,
    };
  },
});

Guess you like

Origin blog.csdn.net/weixin_51157081/article/details/123181627