组件双向绑定

组件的v-model指令是如下语法的语法糖:

  1. <Component v-model="propName" />
  2. =>
  3. <Component
  4. value={self.get('propName')}
  5. ev-$change:value={function(c, value) {
  6. self.set('propName', value);
  7. }}
  8. />

所以只要组件接受value属性,并且当value改变时,触发$change:value事件,就可以给该组件使用v-model指令进行数据的双向绑定。事实上:组件只需要支持value属性即可,而$change:value事件是组件的默认事件,无需显式触发。

  1. <button ev-click={self.add}>+1</button>
  1. var Component = Intact.extend({
  2. template: template,
  3. defaults: function() {
  4. return {value: 0};
  5. },
  6. add: function() {
  7. this.set('value', this.get('value') + 1);
  8. }
  9. });
  1. var Component = self.Component;
  2. <div>
  3. <Component v-model="count" />
  4. count属性值为:{self.get('count')}
  5. </div>
Intact.extend({
    template: template,
    defaults: function() {
        return {count: 0};
    },
    _init: function() {
        this.Component = Component;
    }
});

甚至我们可以在子组件初始化,而父组件没有定义绑定的属性时,强制初始化父组件的属性值。要达到这个目的,只需要在组件的_init()生命周期函数中,触发$change:value即可。

<button ev-click={self.add}>+1</button>
var Component = Intact.extend({
    template: template,
    defaults: function() {
        return {value: 0};
    },
    _init: function() {
        // 组件初始化时,如果父组件传入的绑定属性值为undefined
        // 则立即设置为默认值0,让其触发$change:value事件
        if (this.get('value') === undefined) {
            this.set('value', 0);
        }
    },
    add: function() {
        this.set('value', this.get('value') + 1);
    }
});
var Component = self.Component;

<div>
    <Component v-model="count" />
    count属性值为:{self.get('count')}
</div>
Intact.extend({
    template: template,
    _init: function() {
        this.Component = Component;
    }
});

通过上例可以看到,即使使用组件Component时,绑定的属性未定义,依然能将count初始化为0。这在使用组件操作表单时,能提供便利性,你无需为每一个元素初始化属性值。当然在v2.2.0版本中,我们还以通过$receive事件,在组件更新再次接收到undefined值时,将它设为0

由于v-model被编译成了ev-$change:value,所以我们不能再次添加该属性,如果你需要确实需要在属性变更后,执行某个方法,可以在组件中通过on监听绑定的属性变更事件,或者大多数情况下,我们也可以通过$changed:value事件达到类似的目的。