vue学习之组件(component)(二)

   自定义事件

    父组件使用 prop 传递数据给子组件。但子组件怎么跟父组件通信呢?这个时候 Vue 的自定义事件系统就派得上用场了。

   1. 使用 v-on 绑定自定义事件

    每个vue实例都实现了事件接口,即:

  1. 使用 $on(eventName)  监听事件
  2. 使用 $emit(eventName, optionPayload) 触发事件

   注意点: 父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件

     

<div id="example">
    {{msg}}
    <h1>this is father component</h1>
    <span>{{"儿子发来的数据:"+msgFromSon}}</span>
    <son @tofather='receiveMsg'></son>
    <!-- 2. 使用 $on(eventName) 监听事件:父组件使用v-on 来接收监听子组件触发的事件 -->
</div>
<script>

    Vue.component('son', {
        template: `<div> <h1>This is son component</h1> 
                        <input type="text" v-model="kw"/>
                        <button @click="handleClick">sendToFather</button>
                   </div>`,
        data(){
            return {
                kw:''
            }
        },
        methods:{
            handleClick(){
                console.log(this.kw);
                this.$emit('tofather', this.kw);
                //1.  $emit(eventName)触发事件,还可以发送数据kw到父组件 
            }
        }
    })
    new Vue({
        el: '#example',
        data: {
            msg: 'Hello Directive',
            msgFromSon:''
        },
        methods: {
            receiveMsg(msg) { //3. 接收从子组件传递过来的数据
                console.log('msg',msg);
                this.msgFromSon += ' '+msg;
            }

        }
    })
</script>

   2. 给组件绑定原生事件

     有时候,你可能想在某个组件的根元素上监听一个原生事件。可以使用 v-on 的修饰符 .native。例如:

    

   3.使用自定义事件的表单输入组件

   自定义事件可以用来创建自定义的表单输入组件,使用v-model来进行数据双向绑定。注意:

   

   所以在组件中使用时,它相当于下面的简写:

    

所以要让组件的v-model生效,它应该:

  1. 接受一个 value 的prop
  2. 在有新的值时触发 input 事件并将新值作为参数
          Vue.component('currency-input', {
              template: `<span>$
                              <input ref='input' :value='value' 
                                     @input='updateValue($event.target.value)'>
                          </span>`,
              props: ['value'], // 1. 接受一个value的props
              methods: {
                  updateValue(value){
                      // 删除两侧的空格符,保留2位小数,这个例子还是比较初级的。比如,用户输入多个小数点或句号也是允许的
                      var formattedValue = value.trim().slice(0, value.indexOf('.') === -1
                          ? value.length : value.indexOf('.') + 3);
                      // 如果值尚不合规,则手动覆盖为合规的值
                      if (formattedValue !== value) {
                          this.$refs.input.value = formattedValue;
                      }
                      this.$emit('input', Number(formattedValue)); // 2. 触发input事件到父组件;
                  }

              }            
          })
        new Vue({
            el: '#app',
            data() {
              return {
                    price: ''
              }
            }
        })

4. 自定义组件的 v-model

     默认情况下,一个组件的v-model会使用 value prop和 input 事件。但如单选框,复选框之类的输入类型可能会把 value 用作它用。model 选项可以避免这样的冲突:

   

   注意你仍然需要显式声明 checked 这个 prop。

   

5. 非父子组件的通信

    有时候,非父子关系的两个组件之间也需要通信。在简单的场景下,可以使用一个空的 Vue 实例作为事件总线

    

页面如下: 

<div id="example">
    <laoda></laoda>
    <hr/>
    <laoer></laoer>
</div>

<script type="text/x-template" id="laoda-template">
    <div>
        <h1>laoda</h1>
        <button @click="tellLaoer">回家吃饭</button>
    </div>
</script>
<script type="text/x-template" id="laoer-template">
    <div>
        <h1>laoer</h1>
        <span v-if="msgFromLaoDa">{{"老大说:"+msgFromLaoDa}}</span>
    </div>
</script>

JS如下: 

   

    //新建一个Vue的实例,通过bus完成事件的绑定和触发
    var bus = new Vue();

    Vue.component('laoda', {
        template: '#laoda-template',
        methods:{
            tellLaoer: function () {

                //1. 触发事件通知老二回家吃饭
                bus.$emit('eventToBrother','赶紧回家吃饭')
            }
        }
    })
    Vue.component('laoer', {
        template: '#laoer-template',
        data:function(){
            return {
                msgFromLaoDa:null
            }
        },
        mounted: function () {
            console.log(this, bus); // 3.外面的this指向laoer这个组件
            // 2. 事件的绑定
            bus.$on('eventToBrother', function (result) {
                console.log('this:', this); // 4. 里面的this原指向bus,使用bind后,就指向了组件
                this.msgFromLaoDa = result;
            }.bind(this));
        }
    })

    new Vue({
        el: '#example',
        data: {
            msg: 'Hello Directive'
        }
    })

posted on 2018-03-16 11:09  baoyadong  阅读(171)  评论(0编辑  收藏  举报

导航