学习Vue 3.0

setup 函数

定义

  1. 理解:Vue3 中新增的一个配置项,值为一个函数

  2. setup 是所有 Composition API(组合式 API) 表演的舞台

  3. 组件中所用到的数据、方法等均要匹配值在 setup 中,通过 setup 函数返回的对象中的属性来获取的

  4. setup 函数的有两种返回值

  • 如果返回值是一个对象,则该对象的属性、方法等,在模板中均可直接使用
  • 如果返回值是一个渲染函数,则该渲染函数的返回值将作为组件的模板
  1. 执行时机:beforeCreate 之前执行一次,this 是 undefined

setup 接收到的参数

  • props:值为对象,包含组件外部传递过来,且组件内部声明接收的属性
  • context:上下文对象
    • attr: 值为对象,包含组件外部传递过来,但没有在组件内部声明接收的属性,相当于this.$attr
    • emit:分发自定义事件的函数,相当于this.$emit
    • slots:收到的插槽内容,相当于this.$slots
// xxx.vue
<template>
  {{msg}}
</template>

<script>
export default {
  // setup(props,context) {
  setup(props,{emit, attr, slots}) {
    ......
    let msg = 'hello world'
    const setValue = () => {
      msg.value = 'hello'
    };
    return {
      msg,
      setValue
    }
  }
}
</script>
  • 尽量不要与 Vue2 配置混用

ref 函数

  1. 定义一个响应式数据
  2. 语法

<template>
  <div> {{ a }} </div>
  <div> {{ obj.msg }} </div>
</template>

<script>
export default {
  setup() {
    ....
    // 创建一个包含响应式数据的 引用对象`(reference 对象,称 ref 对象)
    let a = ref(1);
    let obj = {
      msg: 'hello',
      num: 2
    };
    const setValue = () => {
      // 取值 xxx.value
      console.log(a.value); // 1
      console.log(obj.value.msg); // hello
      // 设置值  xxx.value = newValue
      a.value = 2;
      obj.value.msg = 'world';
    };
    ....
    return {
      a,
      obj,
      setValue
    }
  }
}
</script>
  • 接收的数据: 基本数据类型、 对象类型
  • 基本类型数据:响应式靠 Object.defineProperty()getset 实现
  • 对象类型数据:内部使用 vue3.0 的新函数 reactive() 实现

reactive 函数

  1. 定义一个对象类型的响应式数据 (基本类型数据要是用 ref 实现)

  2. 语法: const 代理对象 = reactive(原始对象)接收一个对象(或数组)作为参数,返回一个代理对象(Proxy 对象)

const obj = reactive({
  a: 1,
  b: 2
});
  1. reactive 定义的响应式数据是‘深层次的’

  2. 内部基于 ES6 Proxy 实现,通过代理对象操作原始对象内部数据

reactive 与 ref

  1. 从定义数据
  • ref 用来定义: 基本类型数据
  • reactive 用来定义: 对象类型数据

ref 也可以用来定义对象类型数据,它内部会自动通过 reactive 转为代理对象

  1. 从原理
  • ref 通过 object.defineProperty()getset 来实现响应式(数据劫持)
  • reactive 通过 Proxy 实现响应式(数据劫持),并通过 Reflect 操作原始对象内部数据
  1. 从使用
  • ref 定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value

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

toRef 与 toRefs

  1. toRef作用: 创建一个 ref 对象,其 value 值指向另一个对象中某个属性
  2. 语法:
const obj = reactive({
  a: 1,
  b: 2
});
const a = toRef(obj, a);
  1. 应用场景: 要将响应式中的某个属性单独提供给外部使用时
  2. toRefstoRef 功能一致,但是可以批量创建多个 ref 对象
const obj = reactive({
  a: 1,
  b: 2
});
const { a, b } = toRefs(obj);

Vue3.0 中的响应式原理

Vue 2.x 中的响应式原理

  • 对象类型:通过 Object.defineProperty() 对属性的读取、修改进行拦截(数据劫持)

  • 数组类型:通过重写更新数组的一系列方法来实现拦截(对数组的变更方法进行了包裹)

let person = {
  name: '张三',
  age: 18
};

let p = {};

defineProperty(p, 'name', {
  get() {
    return person.name;
  },
  set(newValue) {
    person.name = newValue;
  }
});

Vue 3.x 中的响应式原理

  • 通过 Proxy(代理):拦截对象中任意属性的变化,包括属性值的读写、属性的添加、属性的删除等

  • 通过 Reflect(反射):对源对象的属性进行操作,包括属性的读取、属性的添加、属性的删除等

let person = {
  name: '张三',
  age: 18
};

const p = new Proxy(person, {
  // 读取某个属性时调用
  get(target, key) {
    return Reflect.get(target, key);
    // return target[key];
  },
  //  新增或修改属性时调用
  set(target, key, value) {
    return Reflect.set(target, key, value);
    // target[key] = value;
  },
  // 删除属性时调用
  deleteProperty(target, key) {
    return Reflect.deleteProperty(target, key);
    //  return delete target[key];
  }
});

shallowRef 与 shallowReactive

  • shallowReactive: 只处理对象最外层属性的响应式(浅响应式)
  • shallowRef:只处理基本数据类型的响应式
  • 使用场景
    • 如果一个对象数据,数据结构比较深,但变化时,只是最外层属性变化,可以使用 shallowReactive
    • 如果一个对象数据,后续功能不会修改该对象中的属性,而是生成新的对象来替换,可以使用 shallowRef

readonly 与 shallowReadonly

  • readonly: 让一个响应式数据变为只读的(深只读)
  • shallowReadonly: 让一个响应式数据变为只读的(浅只读)
  • 应用场景: 不希望数据被修改时

toRaw 与 markRaw

  • toRaw

    • 将 reactive 生成响应式对象转换为普通对象
    • 用于读取响应式对象对象的普通对象,这个普通对象的所有操作不会引起页面更新
  • markRaw

    • 标记一个对象,使其永远不会成为响应式对象
    • 有些值不应被设置成响应式,例如三方类库
    • 当渲染局部不可变数据源的大列表时,跳过响应式可以提高性能

customRef

  • 创建一个自定义 ref,并对其依赖项跟踪和更新触发进行显式控制
// 实现一个延迟的 ref
const delayRef = (value.delay)=> {
  let timer = null;
  return customRef((track,trigger) => {
    return {
      get(){
        track();
        return value;
      },
      set(newValue){
        clearTimeout(timer);
        timer = setTimeout(() =>{
          value = newValue;
          trigger();
        }, delay);
      }
    }
  })
}

provide 与 inject

  • 适用于 跨级组件(祖孙组件通信)

  • 父组件有一个 provide 选项提供数据,子组件通过 inject 选项获取并使用数据

// 父组件

import { provide } from 'vue';

setup(){
  ....
  let person = {
    name: '张三',
    age: 18
  };
  provide('person', person);
  ....
}

// 后代组件

import { inject } from 'vue';

setup(){
  ....
  const student = inject('person');
  ....
  return{
    student
  }

}

响应式数据判断

  • isRef: 判断一个值是否是 ref 对象
  • isReactive: 判断一个值是否是 reactive 响应式代理
  • isReadonly: 判断一个值是否是 readonly 创建的只读代理
  • isProxy: 判断一个值是否是 reactive 或 readonly 方法创建的代理

Composition API 的优势

  • Options API 缺点

    新增或者修改一个需求,就需要分别在 data、methods、computed、watch 中添加对应的配置项

  • Composition API 优势

    可以更加优雅的组织代码、函数,让相关功能更加有序的组织在一起

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值