触发事件

trigger方法

组件触发事件的函数为trigger(eventName, [...args])

  • eventName 触发事件名
  • args 传给事件处理函数的参数

上例中,可以看到触发一个increase事件的方法为:this.trigger('increase')。 通过它我们还可以为事件处理函数传递数据。

  1. <li ev-click={self.likeThisBook}>{self.get('book')}</li>
  1. var Book = Intact.extend({
  2. template: template,
  3. likeThisBook: function() {
  4. // 将book传给事件处理函数
  5. this.trigger('like', this.get('book'));
  6. }
  7. });
  1. var Book = self.Book;
  2. <ul>
  3. <Book
  4. ev-like={self.like}
  5. v-for={self.get('books')}
  6. book={value}
  7. />
  8. 你喜欢的书是:{self.get('book')}
  9. </ul>
  1. var App = Intact.extend({
  2. template: template,
  3. defaults: function() {
  4. this.Book = Book;
  5. return {
  6. books: ['Javascript程序设计', '未来简史', '红楼梦']
  7. }
  8. },
  9. like: function(book) {
  10. this.set('book', book);
  11. }
  12. });
  13. Intact.mount(App, document.getElementById('apptrigger'));

组件默认事件

$change事件

Intact实例#$change事件章节,我们介绍过,组件每一次set()触发数据变更, 都会触发相应的事件。所以我们可以监听子组件某个属性的变更,而无需子组件 显式地抛出事件。

  1. <button ev-click={self.add}>+1</button>
  1. var Component = Intact.extend({
  2. template: template,
  3. defaults: function() {
  4. return {count: 0}
  5. },
  6. add: function() {
  7. this.set('count', this.get('count') + 1)
  8. }
  9. });
  1. var Component = self.Component;
  2. <div>
  3. <Component ev-$change:count={self.setCount} />
  4. 子组件被点击了{self.get('count') || 0}次
  5. </div>
  1. var App = Intact.extend({
  2. template: template,
  3. _init: function() {
  4. this.Component = Component;
  5. },
  6. setCount: function(c, count) {
  7. this.set('count', count);
  8. }
  9. });
  10. Intact.mount(App, document.getElementById('apptrigger1'));

可以看到Component组件并没有显式地抛出事件,但只要count变更,就会触发$change:count事件。

监听$change:count设置数据,还是有点麻烦,后面将介绍如何通过v-model简化操作

$receive事件

@since v2.2.0

从v2.2.0开始,组件还提供了一个$receive事件,它会在组件接收到父组件传给子组件的变更后的新属性 时触发。与$change事件不同的是,$change事件只要属性变更就会,不管属性的来源是父组件传递新属性 值导致,还是内部自己改变的。通过receive事件,我们可以很方便地修正父组件传给自己的属性值。

例如:下例中,我们将父组件传递的字符串转为数字

  1. <div>
  2. <button ev-click={self.add}>+1</button>
  3. value: {self.get('value')} type: {typeof self.get('value')}
  4. </div>
  1. var Component = Intact.extend({
  2. template: template,
  3. defaults: function() {
  4. return {value: 0}
  5. },
  6. _init: function() {
  7. // 初始化时,也修正
  8. this._fixValue();
  9. // 接收到新值时,修正
  10. this.on('$receive:value', this._fixValue);
  11. },
  12. _fixValue: function() {
  13. // 如果你打开调试工具,可以看到log信息打印的时机
  14. // 内部改变,或者数据没有变更时不会执行
  15. console.log('fix value');
  16. var value = this.get('value');
  17. this.set('value', Number(value));
  18. },
  19. add: function() {
  20. this.set('value', this.get('value') + 1)
  21. }
  22. });
  1. var Component = self.Component;
  2. <div>
  3. <Component v-model="count" />
  4. <button ev-click={self._set}>点击这里,将count设为"10"</button>
  5. </div>
  1. var App = Intact.extend({
  2. template: template,
  3. defaults: function() {
  4. this.Component = Component;
  5. return {count: '100'};
  6. },
  7. _set: function() {
  8. this.set('count', 10);
  9. }
  10. });
  11. Intact.mount(App, document.getElementById('receive'));

$receive事件只有在更新子组件传递新的属性值时触发,而不会在初始化时触发

组件生命周期事件

组件的默认事件除了$change类,还有一组跟生命周期相关的事件。详见组件生命周期

on方法

利用实例提供的on(eventName, callback)方法,我们可以给实例对象绑定事件。结合前面提到的默认事件, 我们可以实现类似watch的功能。

  • eventName 监听的事件名
  • callback 事件回调函数,默认this指向触发该事件的实例
  1. <div>
  2. <button ev-click={self.add}>被点击了{self.get('count')}次</button>
  3. 当点击5次时,会弹出alert
  4. </div>
  1. var App = Intact.extend({
  2. template: template,
  3. defaults: function() {
  4. return {count: 0}
  5. },
  6. _init: function() {
  7. // 监听count变更,等于5次时,弹出alert
  8. this.on('$change:count', function(c, count) {
  9. if (count === 5) {
  10. console.log('$change:count', $('#apptrigger2').find('button').text())
  11. alert('你点击了5次!');
  12. }
  13. });
  14. // 为了测试$change:count和$changed:count的区别
  15. this.on('$changed:count', function(c, count) {
  16. if (count === 5) {
  17. console.log('$changed:count', $('#apptrigger2').find('button').text())
  18. }
  19. });
  20. },
  21. add: function() {
  22. this.set('count', this.get('count') + 1);
  23. }
  24. });
  25. Intact.mount(App, document.getElementById('apptrigger2'));

上例中,如果你打开控制台,你可能会发现:$change:count查询到button的文案为:”被点击了4次“; 而$changed:count查询到的文案为:”被点击了5次“(alert会阻塞渲染,所以界面看不到差别)。这正是 $change$changed事件的差别,前者发生在更新前,后者发生在更新后。