按钮点击绑定并查看模型封装

button click binding and view model encapsulation

本文关键字:模型 封装 绑定 按钮      更新时间:2023-09-26

我想使用Ractivejs实现简单的切换按钮功能。这是代码:

function MyViewModel(model) {
    var self = this;
    self.value = false;
    self.toggleValue = function () {
        self.value = !self.value; //this will probably not update view, but it is not the point here
    };
}
var viewModel = new MyViewModel(model);
var ractive = new Ractive({ el: 'mydiv', template: '#mytemplate', data: viewModel });

这是我的模板

<script id='mytemplate' type='text/ractive'>
    <p>Value: {{value}}</p>
    <button type="button">Toggle</button>
</script>

单击按钮时如何调用MyViewModel.toggleValue函数?目前我知道两种选择:

  1. 我可以将on-click='toggle("value")'添加到button元素中。然而,让我们假设我的toggleValue函数可能更复杂,所以这个解决方案是不够的
  2. 我可以将on-click='toggleValue'添加到button元素中。但是我需要添加这个代码:

    ractive.on('oggleValue',函数(){viewModel.toggleValue();});

这意味着:

  1. 我正在编写的代码必须了解这个视图模型之外的视图模型。从封装的角度来看,这是不好的
  2. 这也意味着toggleValue对于Racive实例是全局的,而不是查看特定于模型的,这意味着迟早会出现维护问题
  3. 它在任何方面都不比使用jQuery $("button").click(myFunction)

那么我该如何正确地做呢?我需要相当于KnockoutJs的data-bind="click: toggleValue"

编辑:有关工作代码,请查看此处:http://jsfiddle.net/xak5k8rd/

您可以通过向Racive:添加原型方法来创建这种类型的语法

Ractive.prototype.bind = function(context, method){
    // if using < 0.6.1 you may encounter bug {{this}} or {{.}} not returning model root
    //context = context || this.data
    context[method].call(context, this)
}

然后在您的模板中消费为:

<button type="button" on-click="bind(this, 'toggleValue')">Toggle</button>
<ul>
{{#tab}}
    <li on-click="bind(this, 'click')">{{val}}</li>
{{/tab}}
</ul>

请参阅http://jsfiddle.net/obdk4k2o/2/

已编辑:为绑定函数添加了上下文。注意,任何模板模型值都可以传递,但this对于列表来说当然很方便。

已编辑:在0.6.1中,方法调用可以访问this.event,这意味着密钥路径和上下文都可用(因此不需要传入)。

方法变为:

Ractive.prototype.bind = function(method){
    var context = this.event.context,
        keypath = this.event.keypath
    context[method].call(context, this, keypath)
}

模板为:

<button type="button" on-click="bind('toggleValue')">Toggle</button>
<ul>
{{#tab}}
    <li on-click="bind('click')">{{val}}</li>
{{/tab}}
</ul>

在您的视图模型中:

self.click=function(ractive, keypath){
    ractive.set(keypath + ".val", !self.val);
    alert('click');
}

请参阅http://jsfiddle.net/obdk4k2o/6/

我认为第二个变体没有错。视图有元素,当有人点击按钮时,视图传播一些事件。View甚至不知道某人是否有该事件的听众,也不在乎某人是否真的有这样的听众。

IMO你们只是把事件的名称和你们的商业逻辑联系起来,让自己感到困惑。但这是错误的,IMO。View应该抛出一个一般事件,比如"一个按钮被点击了,我不在乎是否有人想对此做点什么"。国际海事组织,通过这一事件的工作足以使各层相互脱钩。

像这样:

模板:

<script id='mytemplate' type='text/ractive'>
    <p>Value: {{value}}</p>
    <button type="button" on-tap="UserMakeSomeAction">Toggle</button>
</script>

JS:

ractive.on('UserMakeSomeAction', function () { viewModel.toggleValue(); });

附言:此外,KnockoutJs的例子主要是关于将表示层与行为层耦合。您的视图应该确切地知道控制器上应该出现什么方法,知道它的名称,并调用它。IMO,基于事件的传播要好得多。