首页 > 解决方案 > 你可以使用 backdraftjs watchable 让组件完全重新渲染吗?

问题描述

这是一个人为的示例,但它类似于现实生活中的情况,例如,您可能有一个链接列表,这些链接是根据您从服务器进行 AJAX 处理的数据构建的。

import {Component, e, render} from './node_modules/bd-core/lib.js';
            
// a list of strings that for alert when you click them
class AlertLinkList extends Component.withWatchables('data') {
    handleClick(event){
        alert(event.target.innerHTML);
    }
    
    bdElements() {
        return e.div(
            {
                // bdReflect: ?????
            },
            ['yes', 'no', 'maybe'].map(
                txt => e.div({bdAdvise: {click: 'handleClick'}}, txt)
            )
        )
    }
}

var linkList = render(AlertLinkList, {}, document.body);

// I would like to change the strings but this (obviously) does nothing
linkList.data = ['soup', 'nuts', 'fish', 'dessert'];

我想不出一个直接的方法来解决这个问题。

bdReflect我认为仅适用于可写 DOM 属性,因此例如我可以使用它来替换组件的 innerHTML,但随后我认为我丢失了链接上的 bdAdvise 分配(而且它看起来也有点笨拙)。

有任何想法吗?

标签: javascriptbackdraftjs

解决方案


好的,这是一种适用于此的模式......

  • 摆脱可观看的内容AlertLinkList
  • 相反,使用 kwargs 填充列表
  • 将列表包装在另一个组件中,只要内容发生变化(例如,从服务器获取新内容后),该组件就会使用新内容重新渲染列表
// a list of strings that  alert when you click them
class AlertLinkList extends Component {
    handleClick(event){
        alert(event.target.innerHTML);
    }
    
    bdElements() {
        return e.div(
            this.kwargs.items.map(
                txt => e.div({bdAdvise: {click: 'handleClick'}}, txt)
            )
        )
    }
}

// a wrapper that provides/retrieves data for AlertLinkList
class LinkListWrapper extends Component {
    bdElements() {
        return e.div(
            {},
            e.a(
                {bdAdvise: {click: 'updateList'}},
                'Click to Update List',
            ),
            e.div({bdAttach: 'listGoesHere'}),
        );
    }

    updateList(event) {
        // the data below would have been retrieved from the server...
        const resultRetrievedFromServer = ['soup', 'nuts', 'fish', 'dessert'];
        this.renderList(resultRetrievedFromServer)
    }

    renderList(items) {
        render(AlertLinkList, {items}, this.listGoesHere, 'only')
    }

    postRender() {
        const initialData = ['yes', 'no', 'maybe']
        this.renderList(initialData);
    }
}

var linkList = render(LinkListWrapper, {}, document.body);

我在这里看到的唯一问题是,如果只有一小部分数据发生更改,则重新渲染整个包装组件可能不是最优的,尽管我想你可以围绕它进行设计。


推荐阅读