inshua / d2js

d2js - 前后端web数据框架; jssp - Javascript Server Page;
MIT License
19 stars 10 forks source link

molecule 如何处理“全局”数据(状态)? #1

Open kalxd opened 7 years ago

kalxd commented 7 years ago

淘宝“宝贝详情页”上,有个跟卖家聊天的按钮,点击之后可以跟卖家直接聊天。 现在考虑这样一个场景,如果点击聊天之后,卖家下面的“联系我”变成“正在联系”,然后弹出聊天窗口,关闭聊天窗口后恢复成“联系我”。

从redux方面来看,它像个巨大的观察者,不管是界面变化还是用户变化,它都会进行观察,如果需要对应的数据,只要订阅到需要的部分就行了,这个过程发生在组件中。

例如点击按钮:

// “详情页”
this.watch("change", prop => {
    if ("chatting" === prop.chat) {
        this.$chat.text("正在联系");
    }
    else {
       this.$chat.text("联系我");
    }
});

this.$chatBtn.click(_ => dispatch({ type: "chat", value: "chatting" }));
// 聊天按钮
this.watch("change", prop => {
    if ("chatting" === prop.chat) {
        this.$window.show();
    }
    else {
        this.$window.hide();
    }
});

this.$window.close(_ => dispatch({ type: "chat", value: "hide"}));

react-redux实际应用跟上面相差很多,不过差不多就是这个意思,把watch换成render就很接近了。虽然不怎么喜欢redux,但感觉也是有可取之处,那么molecule会怎样处理这种情况?

inshua commented 7 years ago

这个是事件处理+数据渲染的典型应用,只要掌握 jQuery 的事件就可以很好的解决这个问题。

jQuery 事件可以层层冒泡到顶层,只要把事件处理函数挂在 document 级别即可。

// “详情页” ——一个 molecule 组件,或不作为组件纯 html 也可,这是其中的事件捕获
$(document).on("chat", (evt, state)=> {
    this.render(state);   
});

// 文字label:
// <span data="chating" dict="ChatDict" or dict="{yes:'聊天中', no:'联系我'}" renderer="dict|std"></span>

// 聊天按钮与前面的相似,但不要触发事件。

聊天窗口可以做成一个 molecule,其show 时 使用 this.$el.trigger('chat', {chating: 'yes'}) 发出事件,其 close 时也发出一个事件通知 this.$el.trigger('chat', {chating: 'no'}) 。

也可以将聊天窗口组件作为数据。

<span data="chat" dict="ChatDict" or dict="{yes:'聊天中', no:'联系我'}" renderer="dict|std">

则调用

$el.render(chatWindow.state)

也可以达到更新显示的效果。

这里 render 等是 d2js 数据绑定的内容。

kalxd commented 7 years ago

如果依靠事件来处理的话,要不要考虑下这个

RxJS虽然在这个情景里并不好用,无法像jQuery那样方便的事件代理。它把事件当成“流”,也可以算作一种数据吧。

如果最后都变成stream,最后跟cycle.js很像了。

inshua commented 7 years ago

但是为什么要搞成流??

对象是属性方法事件的总和,我觉得这种理解很好啊,把复杂的订阅问题通俗化了。

对比把事件处理成流,程序理解为 parser 的往象牙塔走的思路,我更倾向于这种能够用一个简单概念涵盖复杂思维的。