8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

Vue 3 反应性不是从类实例内部触发的

Timmmm 1月前

17 0

Codepen:https://codepen.io/codingkiwi_/pen/XWMBRpW假设你有一个类:class MyClass {constructor(){this.entries = [\'a\']; //=== 示例更改从内部触发

Codepen: https://codepen.io/codingkiwi_/pen/XWMBRpW

假设你有一个课程:

class MyClass {
  constructor(){
    this.entries = ["a"];

    //=== example change triggered from INSIDE the class ===
    setTimeout(() => {
      this.entries.push("c");
    }, 1000);
  }
}

在组件中你会得到该类的一个实例:

const { reactive } = Vue;

const App = {
  setup() {
    const myobject = reactive(new MyClass());

    //=== example change triggered from OUTSIDE the class ===
    setTimeout(() => {
      myobject.entries.push("b");
    }, 500);
    
    return {
      myobject
    };
  }
}

DOM 中的 myobject.entries 数组将显示条目 "a" "b" ,但不显示 "c"

帖子版权声明 1、本帖标题:Vue 3 反应性不是从类实例内部触发的
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Timmmm在本站《vue.js》版块原创发布, 转载请注明出处!
最新回复 (0)
  • DOM 中的 myobject.entries 数组将显示条目 "a" "b" ,但不显示 "c"

    这是因为 "a" 当我们使实例具有反应性时,已经在数组中,并且 "b" 通过代理从对象外部发生了推送。

    要清楚 const myobject 不包含 MyClass 实例,它包含 Proxy 处理/包装原始实例的实例!它是传递给 DOM / 模板的代理。

    推送 "c" 发生在对象内部, 而不是 通过代理。因此 "c" 将被推送到数组,但不会触发任何反应性变化。

    使固定:

    明确标记我们从类内部更改的数组,如下所示 reactive

    class MyClass {
      constructor(){
        this.entries = reactive(["a"]);
    
        //=== example change triggered from INSIDE the class ===
        setTimeout(() => {
          this.entries.push("c");
        }, 1000);
      }
    }
    

    或者尝试仅使用代理对象,如文档所建议的那样:

    这里的最佳实践是永远不要持有对原始对象的引用,而只使用反应版本:

    文档: https://v3.vuejs.org/guide/reactivity.html#proxy-vs-original-identity

  • 正如另一个答案所解释的那样, reactive 创建代理对象以启用反应性。 this 构造函数指的是原始 MyClass 实例而不是代理,因此它不能具有反应性。

    这表明代码中存在问题。 reactive 考虑了 MyClass 构造函数中发生的同步操作。在构造函数中执行异步副作用是一种反模式,原因包括可能对使用此类构造函数的代码产生影响。

    可以通过以下方法解决:

    class MyClass {
      constructor(){
        // synchronous stuff only
        this.entries = ["a"];
      }
    
      init() {
        // asynchronous stuff, probably return a promise
        setTimeout(() => {
          this.entries.push("c");
        }, 1000);
      }
    }
    

    const myobject = reactive(new MyClass());
    myobject.init() // `this` is a proxy inside `init`
    
  • 谢谢!构造函数中的反模式实际上只是在示例中 :) 在实际代码中,我遇到了这个问题,我在构造函数中定义了一个侦听器函数 this.listener = () => { this.entities.push(); }(以便能够稍后取消订阅),因此,就像您解释的那样,侦听器函数中的 \'this\' 引用了原始实例

  • 在这种情况下,解决方法是不使用箭头方法和延迟绑定方法,例如 listener 是一种常规方法,用作 event => this.listener(event) 或 this.listener.bind(this)。如果我没记错的话,如果您的设置支持,github.com/NoHomey/bind-decorator 装饰器可以做到这一点。正如另一篇文章所建议的那样,该类不一定具有硬编码的反应式以在 Vue 组件中使用,但需要考虑到这一点进行设计。

返回
作者最近主题: