[Vue3] reactive、ref、shallowReactive 和 shallowRef 的区别

reactive

reactive 函数的返回了一个 Proxy 代理对象,添加 set 和 get 拦截,把 tracktrigger 两个函数加入进来。

file:[reactive 伪代码]
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key)
      return target[key]
    },
    set(target, key, value) {
      target[key] = value
      trigger(target, key)
    }
  })
}

如果传递的对象有多层嵌套,那就需要递归创建,否则就没有 Proxy 去代理嵌套对象,实现响应式。

也就是说,对象嵌套得越多,递归的次数就越多,但这种消耗根据文档的意思来说,不是特别大。若要创建不递归的响应式对象,通过 shallowReactiveshallowRef 来创建。

shallowRef

shallowRef 不主动更新视图,需要通过 triggerRef。或者,强制性替换原对象的值让视图更新。

file:[src/App.vue]
let state = shallowRef({
  foo: {
    bar: 1
  },
  foobar: 2
});

function changeState() {
  // 自加不会触发页面更新
  state.value.foo.bar++;
  state.value.foobar++;

  // 替换 state.value 的根对象页面才会更新
  const replace = {
    foo: {
      bar: state.value.foo.bar
    },
    foobar: state.value.foobar
  };

  state.value = replace;
}

changeState 替换原对象的值,视图更新

推荐通过 triggerRef 更新视图。

file:[src/App.vue]
function triggerUpdate() {
  state.value.foo.bar++;
  state.value.foobar++;

  triggerRef(state);
}

ref 和 reactive

ref 得到一个对象类型(Map、Object 等)时,是通过 reactive 创建的响应式数据。所以,遇到对象类型,可以直接用 reactive

或者,统一都用 ref 创建响应式数据。

shallowRef 场景

如果你希望修改数据的时候视图不立即更新,可通过 shallowRef 来实现,在需要的时候通过 triggeRef 来更新视图。

如上图所示,当我展开表格编辑时,这些输入框会导致视图立即更新,界面重新渲染,导致打开的界面被关闭。

表格的数据是由 ref 创建,是深层次响应式数据。所以,shallowRef 创建的浅层响应式数据可能会让界面的发生变化,但至少不会重新渲染界面。

posted @ 2023-03-19 20:39  Himmelbleu  阅读(147)  评论(0编辑  收藏  举报