iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >vue定义在computed的变量无法更新如何解决
  • 278
分享到

vue定义在computed的变量无法更新如何解决

2023-07-04 23:07:05 278人浏览 安东尼
摘要

今天小编给大家分享一下Vue定义在computed的变量无法更新如何解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。vue

今天小编给大家分享一下Vue定义在computed的变量无法更新如何解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

    vue定义在computed的变量无法更新

    情境是这是线上商城的详情页面,商品详情是items数组,点击分类页面的商品,路由跳转到详情页面,路由参数是商品在items中的序号。

    但是问题是只有第一次点击商品i的时候可以正常加载items[i]的数据到html中,退出后点击商品j,发现加载的还是商品i的信息,只有刷新后才会更新成商品j的信息。

    部分代码:

            <shopPanel            :key = "nums"            :Goodname="item.text"            :tag="item.tag"            :sale="item.sale"            :price="item.price"            :ori="item.ori_price"        >        </shopPanel>

    和computed定义的,注意这里定义的数据item,是不能够修改的,想修改只能用set来修改。

    我这里测试时发现明明item关联的两个属性this.focus和this.idx改变了,那为什么item没有改变呢?

    而且是刷新后就能改变。

            computed: mapState({            items:'items', //商品详情信息            item(){                console.log(this.focus+" "+this.idx);                return this.items[this.focus].children[this.idx]            }        }),

    最后的原因竟然是定义路由的时候选择了keepalive,页面不会销毁,改成false就行。

            path: '/item/item01',        name:'itemdetail',        meta: {            title: '商品1',            keepAlive: false,            showTab: false        },        component: (resolve) => require(['../page/itemdetail/item01'], resolve),

    vue computed依赖收集与更新原理

    今天面了家小公司,上来直接问 computed 底层原理,面试官是这样问的,data 中定义了 a 和 b 变量。computed 里面定义了 c 属性,c 的结果依赖与 a 和 b,模板中使用了变量 c。假设改变了 a,请问底层是如何收集依赖,如何触发更新的?

    <div>{{ c }}</div>
    data(){    return {        a: 'foo',        b: 'bar'    }},computed: {    c() {         return this.a + ' - ' + this.b;     }},mounted(){    setTimeout(() => { this.a = 'FOO' }, 1000)}

    页面效果:先显示了 foo - bar,一秒之后显示 FOO - bar

    这里查源码后,对computed原理简述如下

    initState 函数中初始化了 initComputed

    export function initState (vm: Component) {  vm._watchers = []  const opts = vm.$options  if (opts.props) initProps(vm, opts.props)  if (opts.methods) initMethods(vm, opts.methods)  if (opts.data) {    initData(vm)  } else {    observe(vm._data = {}, true )  }  if (opts.computed) initComputed(vm, opts.computed)  if (opts.watch && opts.watch !== nativeWatch) {    initWatch(vm, opts.watch)  }}

    initComputed 函数中遍历 computed 中每一个属性,并且 new Watcher(computed watcher),可以看到传入 Watcher 构造函数的 cb 是 noop,它是一个空函数。并且 defineComputed

    function initComputed (vm: Component, computed: Object) {  // $flow-disable-line  const watchers = vm._computedWatchers = Object.create(null)  // computed properties are just getters during SSR  const isSSR = isServerRendering()  for (const key in computed) {    const userDef = computed[key]    const getter = typeof userDef === 'function' ? userDef : userDef.get    if (process.env.node_ENV !== 'production' && getter == null) {      warn(        `Getter is missing for computed property "${key}".`,        vm      )    }    if (!isSSR) {      // create internal watcher for the computed property.      watchers[key] = new Watcher(        vm,        getter || noop,        noop,        computedWatcherOptions      )    }    // component-defined computed properties are already defined on the    // component prototype. We only need to define computed properties defined    // at instantiation here.    if (!(key in vm)) {      defineComputed(vm, key, userDef)    } else if (process.env.NODE_ENV !== 'production') {      if (key in vm.$data) {        warn(`The computed property "${key}" is already defined in data.`, vm)      } else if (vm.$options.props && key in vm.$options.props) {        warn(`The computed property "${key}" is already defined as a prop.`, vm)      } else if (vm.$options.methods && key in vm.$options.methods) {        warn(`The computed property "${key}" is already defined as a method.`, vm)      }    }  }}

    defineComputed 中使用了 Object.defineProperty 对属性进行劫持,获取是返回对应的 getter 即 createComputedGetter

    export function defineComputed (  target: any,  key: string,  userDef: Object | Function) {  const shouldCache = !isServerRendering()  if (typeof userDef === 'function') {    sharedPropertyDefinition.get = shouldCache      ? createComputedGetter(key)      : createGetterInvoker(userDef)    sharedPropertyDefinition.set = noop  } else {    sharedPropertyDefinition.get = userDef.get      ? shouldCache && userDef.cache !== false        ? createComputedGetter(key)        : createGetterInvoker(userDef.get)      : noop    sharedPropertyDefinition.set = userDef.set || noop  }  if (process.env.NODE_ENV !== 'production' &&      sharedPropertyDefinition.set === noop) {    sharedPropertyDefinition.set = function () {      warn(        `Computed property "${key}" was assigned to but it has no setter.`,        this      )    }  }  Object.defineProperty(target, key, sharedPropertyDefinition)}function createComputedGetter (key) {  return function computedGetter () {    const watcher = this._computedWatchers && this._computedWatchers[key]    if (watcher) {      if (watcher.dirty) {        watcher.evaluate()      }      if (Dep.target) {        watcher.depend()      }      return watcher.value    }  }}

    看到这里,我们大致可以理解,Vue 组件在初始化时,initState -> initComputed -> new Watcher() 计算watcher,传入的 callback 是 computer 属性的 getter,由于 computed 是 lazy: true watcher,所以 new Watcher 时并不会立即执行 watcher 实例上的 get(), 而是在 defineComputed 函数里面调用 createComputedGetter 函数,在 createComputedGetter 函数执行了 watcher.evaluate() 进而执行了 watcher.get().

    执行 watcher.get() 首先 pushTarget(this),将 Dep.target 赋值为当前的 computed watcher,然后执行 this.getter也就是执行 computer 属性配置的 getter,执行getter 就会访问所依赖的每一个值,就会被 Object.defineProperty 劫持到进入 get ,执行 dep.depend() , 会为每一个属性对应的 dep 实例添加一个 computed watcher,同时这个 computed watcher 也会保存对应的 dep。

    说了这么多都在讲 computed watcher,那修改 this.a 页面为什么会发生更新呢?

    答案:因为 this.a 的依赖中不仅有 computed watcher 还有一个 render watcher

    原因:

    $mount 是会执行 mountComponent,会创建一个 render watcher,它会立即执行 cb(目前 Dep.target 是 render watcher),调用 render 函数在底层编译模板,最后访问属性计算属性 c,访问计算属性 c 就必定会访问 a,当访问 a 时会触发 defineComputed 中的 Object.defineProperty 进而劫持调用 createComputedGetter,进而调用 watcher.depend(),这个 watcher 是 computed watcher

    function createComputedGetter (key) {  return function computedGetter () {    const watcher = this._computedWatchers && this._computedWatchers[key]    if (watcher) {      if (watcher.dirty) {        watcher.evaluate()      }      if (Dep.target) {        watcher.depend()      }      return watcher.value    }  }}
    // Watcher.jsdepend () {  let i = this.deps.length  while (i--) {    this.deps[i].depend()  }}

    调用 watcher.depend() , this 指的是 computed watcher,会将 computed watcher 里面的 deps 保存在所有依赖调用 deps[i].depend(),进而调用 Dep 类中的 Dep.target.aDDDep(this),使得 render watcher 中保存了当前的 dep,dep 中同时保存了 render watcher。

    dep 中同时保存了 render watcher。就可以看出,示例中的属性 a 的 dep 中也会保存 render watcher,所以 a 属性的 dep 中有两个 watcher: [computedWatcher, renderWatcher]

    所以,修改 a 属性的值,最后 notify 会清空这个 保存 watcher 的队列,进行页面更新!Okay! 

    以上就是“vue定义在computed的变量无法更新如何解决”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网精选频道。

    --结束END--

    本文标题: vue定义在computed的变量无法更新如何解决

    本文链接: https://www.lsjlt.com/news/348244.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • vue定义在computed的变量无法更新如何解决
      今天小编给大家分享一下vue定义在computed的变量无法更新如何解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。vue...
      99+
      2023-07-04
    • vue定义在computed的变量无法更新问题及解决
      目录vue定义在computed的变量无法更新vue computed依赖收集与更新原理这里查源码后,对computed原理简述如下总结vue定义在computed的变量无法更新 情...
      99+
      2023-01-10
      vue computed变量 computed变量无法更新 vue computed
    • Vue无法访问.env.development定义的变量值问题及解决
      目录Vue无法访问.env.development定义的变量值vue中.env | .env.development | .env.production使用vue-cli-servi...
      99+
      2023-01-10
      Vue无法访问.env.development .env.development .env.development定义变量值
    • win101607系统无法改变更新如何解决
      这篇文章主要讲解了“win101607系统无法改变更新如何解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“win101607系统无法改变更新如何解决”吧!在Windows10系统,在打开系...
      99+
      2023-07-01
    • vb变量未定义如何解决
      如果在VB中出现变量未定义的错误,可以尝试以下几种方法解决:1. 定义变量:确保所有变量在使用之前都已经定义。可以使用`Dim`语句...
      99+
      2023-09-13
      vb
    • win102004无法更新如何解决
      本篇内容主要讲解“win102004无法更新如何解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“win102004无法更新如何解决”吧!win102004无法更新解决方法:按下“win+r”打...
      99+
      2023-07-01
    • windows 80072f78无法更新如何解决
      这篇文章主要介绍“windows 80072f78无法更新如何解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“windows 80072f78无法更新如何解决”文...
      99+
      2023-01-29
      windows
    • ubuntu无法更新apt如何解决
      如果Ubuntu无法更新apt,您可以尝试以下解决方法:1. 清除apt缓存:运行以下命令清除APT缓存。```shellsudo ...
      99+
      2023-09-13
      ubuntu
    • win7无法搜索新更新如何解决
      这篇文章主要介绍“win7无法搜索新更新如何解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“win7无法搜索新更新如何解决”文章能帮助大家解决问题。解决方法按下“win+R”打开运行,输入“ser...
      99+
      2023-07-04
    • Vue绑定对象与数组变量更改后无法渲染问题解决
      项目场景: 在页面显示上有一个<ul>标签,我们需要动态进行列表数据的展示,而由于我们的页面上除了列表值,还有其他的值要进行展示,因此列表数据的数据结构是某个对象下面的数...
      99+
      2024-04-02
    • win11更新提示无法更新分区如何解决
      这篇“win11更新提示无法更新分区如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“win11更新提示无法更新分区如何...
      99+
      2023-07-01
    • win10更新安装失败,无法更新如何解决
      当我们更新win10系统时,出现了win10更新一直失败无法更新的情况,win10更新已经安装失败无法更新该如何解决?就到我这里整理了相关内容,大家一起来看看win10更新一直失败不能更新的解决方法介绍。win10更新安装失败,无法更新如何...
      99+
      2023-07-18
    • Android SDK Manager无法更新如何解决
      如果Android SDK Manager无法更新,可以尝试以下解决方法:1. 检查网络连接:确保计算机连接到互联网,并且网络连接正...
      99+
      2023-08-17
      Android
    • keras.layers.Layer中无法定义name如何解决
      本篇内容介绍了“keras.layers.Layer中无法定义name如何解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!keras.la...
      99+
      2023-07-05
    • win101909无法完成更新正在撤销如何解决
      本篇内容主要讲解“win101909无法完成更新正在撤销如何解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“win101909无法完成更新正在撤销如何解决”吧!快捷键【Win】+【R】打开运行...
      99+
      2023-07-01
    • win10无法更新到最新版本如何解决
      如果您的Windows 10无法更新到最新版本,可以尝试以下几个解决方法:1. 检查网络连接:确保您的计算机有稳定的互联网连接。可以...
      99+
      2023-09-12
      win10
    • mkall_cache_1.php无法更新栏目如何解决
      这篇文章主要讲解了“mkall_cache_1.php无法更新栏目如何解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mkall_cache_1.php无法更新栏目如何解决”吧!mkall...
      99+
      2023-07-04
    • win101909更新后无法上网如何解决
      本文小编为大家详细介绍“win101909更新后无法上网如何解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“win101909更新后无法上网如何解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。第一种解决方法...
      99+
      2023-07-01
    • win11更新后无法启动如何解决
      本文小编为大家详细介绍“win11更新后无法启动如何解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“win11更新后无法启动如何解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。首先按住shift键然后强制重...
      99+
      2023-07-01
    • 如何理解Shell脚本定义变量和重新赋值
      本篇内容主要讲解“如何理解Shell脚本定义变量和重新赋值”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解Shell脚本定义变量和重新赋值”吧!Shell支持自定义变量。定义变量定义变量时...
      99+
      2023-06-09
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作