Vue3.0 响应式原理

// 通过Proxy代理数据,实现对数据所有属性的set,get监听以实现数据绑定,并返回一个包装对象
      const data = {
        name: "bob",
        age: 18,
      };
      // 被代理的data元素只能为object
      const proxyData = new Proxy(data, {
        get: function (target, prop) {
          return target[prop];
        },
        set: function (target, prop, value) {
          target[prop] = value;
        },
      });
      //  proxyData 为包装对象
      console.log(proxyData);

ref()reactive()用法上的区别

两个方法都是用于为数据添加响应式绑定,ref()一般用于给基础数据添加绑定 字符串/数字绑定后使用.value访问。
reactive()一般用于给 object 等复杂类型添加动态绑定,绑定后直接访问即可。

    const a = ref({ name: 'bob', age: 18 });
    const b = reactive({ name: 'bob', age: 18 });
    console.log('a::', a, 'b::', b);

在这里插入图片描述
通过以上代码可以发现,ref()在绑定后返回了一个包装对象RefImpl,而包装对象的value属性才指向了proxy代理的观测数据,所以需要用.value访问,而通过reactive()包装的对象则没有这个副作用,如果直接通过reactive包装简单数据,数据将不会被监听。
原因:基于Proxy监听数据,只能监听对象。所以ref(null)在绑定时会将其包装成为{ value:null }再进行监听。

为什么解构赋值要用toRefs()包裹

在js中使用解构赋值时,虽然赋值方式为浅拷贝,但却无法触发Proxy包装对象的set方法,如果直接解构则会破坏对应的响应性,所以需要用toRefs重新绑定。

// 源码
function toRefs(object) {
    if ((process.env.NODE_ENV !== 'production') && !isProxy(object)) {
        console.warn(`toRefs() expects a reactive object but received a plain one.`);
    }
    const ret = isArray(object) ? new Array(object.length) : {}; // 判断传入类型
    for (const key in object) { // 将每个属性都转换为响应对象Ref
        ret[key] = toRef(object, key);
    }
    return ret;
}

function toRef(object, key) {
    return isRef(object[key])
        ? object[key]
        : new ObjectRefImpl(object, key);
}

见大佬解析

自定义组件实现v-model绑定

直接通过子组件进行调用,通过v-model绑定变量

<template>
    <SlefComponent  v-model="inputValue"/>
</template>

通过 model-value为表单传入默认值,通过监听表单内容变化 @input动态改变绑定值modelValue

<template>
    <el-input :model-value="modelValue" @input="inputChange"></el-input>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
  name:"SlefComponent ",
  props: ['modelValue'],
  setup(props, { emit }) {
    const inputChange = newVal => {
      emit('update:modelValue', newVal);
    };
    return {
      inputChange,
    };
  },
});
</script>

Vite支持TSX/JSX语法

在vite配置文件中添加@vitejs/plugin-vue-jsx插件

 tnpm i @vitejs/plugin-vue-jsx --save 
 plugins: [vue(), vueJsx()],

Script setup标签

注:其中部分属性在高版本中,会默认导入,无需再手动import

  1. props定义
<script setup>
import { defineProps } from "vue"; // 高版本已主动注入 无需引入
const props = defineProps({
  foo: {
    type: String,
    default: () => {
      return "hello自定义组件";
    },
  },
});
console.log(props.foo);// use
</script>
  1. 父组件调用子组件属性,需要子组件主动expose
<script setup>
import { ref,defineExpose } from "vue"; // 高版本已主动注入 无需引入

const testData = ref(null);
const refresh = () => {
  console.log("refresh");
}

defineExpose({
  testData,
  refresh
})
</script>

Eslint setup-compiler-macros 配置,防止出现… is not define问题

eslint-plugin-vue插件版本 提升到最新或8.4+

env:{
	'vue/setup-compiler-macros': true,
}
Logo

前往低代码交流专区

更多推荐