博客
关于我
ASP.NET三层架构详解
阅读量:800 次
发布时间:2019-03-25

本文共 4202 字,大约阅读时间需要 14 分钟。

Vue 3_Ref响应性实现深度解析

Vue 3 中,针对基础类型和引用类型数据的响应性实现方式存在显著差异。本文将从 Ref 实现原理、代码解析以及实际应用场景等多个方面展开全面探讨。

Ref 的响应性实现机制

Ref 是 Vue 3 提供的一种强式响应式简写语法,其核心实现目标是可以只通过 .value 属性修改业务逻辑,强化开发体验。在实现上,ref_v_isRef 标志位的判断逻辑plays大角色。

代码剖析:RefImpl 类

RefImpl 是 Ref 实现的核心类,主要属性包括 _rawValue_value,分别代表原始值和被包装的值。以下是关键代码段:

class RefImpl {  constructor(_rawValue, _shallow = false) {    this._rawValue = _rawValue;    this._shallow = _shallow; // shallowRef 标志位    this.__v_isRef = true;    this._value = _shallow ? _rawValue : convert(_rawValue);  }    get value() {    track(toRaw(this), 'get', 'value');    return this._value;  }    set value(newVal) {    if (hasChanged(toRaw(newVal), this._rawValue)) {      this._rawValue = newVal;      this._value = this._shallow ? newVal : convert(newVal);      trigger(toRaw(this), 'set', 'value', newVal);    }  }}
  • getvalue 方法:组合了 track 函数,触发响应式更新。
  • setvalue 方法:根据是否浅层模式决定直接赋值或经过 convert 转换。
Ref与Reactive的关系

值得注意的是,基础类型的 Ref 与 Reactive 没必然联系,引用类型的 Ref 则会_embryos_一个 Reactive 实例:

// 基础类型 const refCount = ref(0) // backingValue 直接已一个数值 // 引用类型 const refObject = ref({ value: 0 }) // backingValue 是一个包含 value 属性的对象// 在 value 属性上挂解重新应性 // 其背后为一个 Reactve 实例 {//   value: 0 // }
浅层 Ref 与深层 Ref 的差异

ShallowRef 实现仅对 .value 属性进行响应式追踪,深层结构则完全不响应变化:

// 浅层 Ref const srefCount = shallowRef(0)// 全深层引用类型 const srefObject = shallowRef({ value: 0 })// 嵌套对象 const srefObjectMore = shallowRef({ value: { a: 'jyk' } })
triggerRef 调用示例

当涉及到嵌套对象的响应式修改时,通常需要手动调用 triggerRef

// 修改嵌套对象的属性 const setObjectProp = () => {  srefObjectMore.value.value.a = new Date().getTime()  triggerRef(srefObjectMore)}// 修改嵌套对象的 .value const setObjectMore = () => {  srefObjectMore.value = {     value: {       a: new Date().getTime()     }   }  triggerRef(srefObjectMore)}

toRef 与 toRefs 的实际应用

toReftoRefs 作为辅助函数,主要用于将 Reactve 实例中的特定属性转为 Ref 类型,同时保持响应式连接。两者均依赖于 ObjectRefImpl 内部实现:

// 单个属性 Ref const refName = toRef(person, 'name')// 多个属性 Ref const personToRefs = toRefs(person)
  • toRef:返回一个 Ref 实例,仅关注目标属性的变化。
  • toRefs:返回一个包含多个 Ref 实例的对象,每个属性都对应目标属性。
toRef 源码分析
function toRef(object, key) {  const objKey = object[key];  return isRef(objKey)    ? objKey    : new ObjectRefImpl(object, key);}// ObjectRefImpl 实现结构class ObjectRefImpl {  constructor(_object, _key) {    this._object = _object;    this._key = _key;    this.__v_isRef = true;  }  get value() {    return this._object[this._key];  }  set value(newVal) {    this._object[this._key] = newVal;  }}
toRefs 源码分析
function toRefs(object) {  if (!isProxy(object)) {    console.warn('pegp');  }  const ret = isArray(object) ? new Array(object.length) : {};  for (const key in object) {    if (hasOwn(object, key)) {      ret[key] = toRef(object, key);    }  }  return ret;}

延迟响应用 case:v-model 应用

延迟响应控制台是一个实际场景,常见于搜索输入等交互:

const useDebouncedRef = (value, delay = 200) => {  let timeout;  return customRef((track, trigger) => ({    get() {      track()      return value;    },    set(newVal) {      clearTimeout(timeout);      timeout = setTimeout(() => {        value = newVal;        trigger();      }, delay);    }  }));}
自定义 Ref 示例
const myComputed = (_get, _set) => {  return customRef((track, trigger) => ({    get() {      track();      if (typeof _get === 'function') {        return _get();      } else {        console.warn('未配置 get 方法')      }    },    set(newVal) {      if (typeof _set === '-function') {        _set(newVal)        trigger();      } else {        console.warn('未配置 set 方法')      }    }  }));}
计算属性实现
// 简单计算属性const myCom = myComputed(() => refCount.value + 1)// 完整计算属性const setRef = () => {  // 直接修改 Ref 的 .value  refCount.value += 1}
Vue 原生计算属性

Vue 原生计算属性实现通过 computed factory函数构建,比 Ref 更强大灵活:

function computed(getterOrOptions) {  let getter;  let setter;  if (isFuncton(getterOrOptions)) {    getter = getterOrOptions;    setter = () => {      console.warn('不可读写')    }  } else {    getter = getterOrOptions.get;    setter = getterOrOptions.set;  }  return new ComputedRefImpl(getter, setter, isFunction(getterOrOptions) || (!getterOrOptions.set));}

总结

Vue 3 的 Ref 和 Reactve 几乎完全不同 redraw机制。Ref 对简单类型实现原生响应式,而对复杂对象,只有通过引用对象的属性变化才能触发。

在实际应用中, mastering RefAndReactive 的关系规则是核心技能之一。

通过以上理解,我们可以更合理地选择 Ref 与 Reactve 的结合方式,从而充分发挥 Vue.js 的响应式能力。

转载地址:http://wltyk.baihongyu.com/

你可能感兴趣的文章
MySQL 快速创建千万级测试数据
查看>>
mysql 快速自增假数据, 新增假数据,mysql自增假数据
查看>>
MySql 手动执行主从备份
查看>>
Mysql 批量修改四种方式效率对比(一)
查看>>
mysql 批量插入
查看>>
Mysql 报错 Field 'id' doesn't have a default value
查看>>
MySQL 报错:Duplicate entry 'xxx' for key 'UNIQ_XXXX'
查看>>
Mysql 拼接多个字段作为查询条件查询方法
查看>>
mysql 排序id_mysql如何按特定id排序
查看>>
Mysql 提示:Communication link failure
查看>>
mysql 插入是否成功_PDO mysql:如何知道插入是否成功
查看>>
Mysql 数据库InnoDB存储引擎中主要组件的刷新清理条件:脏页、RedoLog重做日志、Insert Buffer或ChangeBuffer、Undo Log
查看>>
mysql 数据库中 count(*),count(1),count(列名)区别和效率问题
查看>>
mysql 数据库备份及ibdata1的瘦身
查看>>
MySQL 数据库备份种类以及常用备份工具汇总
查看>>
mysql 数据库存储引擎怎么选择?快来看看性能测试吧
查看>>
MySQL 数据库操作指南:学习如何使用 Python 进行增删改查操作
查看>>
MySQL 数据库的高可用性分析
查看>>
MySQL 数据库设计总结
查看>>
Mysql 数据库重置ID排序
查看>>