Vue的自定义组件、自定义指令、自定义事件、组件通信

1. 自定义组件( 插件 )

案例: 封装一个 Loading 组件
Loading是用来做什么的?
基于用户体验
loading使用方式很多

  1. 第三方的ui库/组件库
  2. 自定义封装
    1. 过程:
    2. 创建一个目录文件夹,称之为Loading
    3. 在loading中创建一个叫做component目录,用来放模板
    4. 在Loading目录下创建一个index.js
      import Vue from 'vue'
      import tpl from './component/index.html'
      const Loading = {
        // 自定义封装组件,这个loading对象中必须有一个关键key
        install () {//一定要用install方法
          Vue.component( 'Loading', {
            template: tpl
          })
        }
      }
    
    
      export default Loading
    
    1. 使用:

2. 自定义指令

  1. 指令是用来操作DOM

  2. 指令的使用形式: 属性

  3. 自定义指令方式有两种:

    • 全局注册指令
      • Vue.directive( 指令的名称, 指令的配置项 )
    • 局部注册指令
      • directives: {
        ‘指令名称’: 指令的配置项
        }
  4. 研究:

    • 指令的配置项提供了5个钩子函数
    • 以及钩子函数中的参数
      • console.log( ‘el’,el ) // el 指令绑定的元素
      • console.log( ‘binding’,binding ) // 指令的详细信息
      • console.log( ‘vnode’, vnode ) // 当前绑定元素的信息
      • console.log( ‘oldVnode’,oldVnode ) // 上一个绑定元素的信息
  5. 案例: 打开网页,input自动获得焦点

 <div id="app">
 <div class="box">
  <button  @click = 'flag = false'> 点击 </button>
  <input type="text"  v-if = "flag" v-focus.yyb v-model = "msg">
  <input type="text"  v-if = "flag" v-focus v-model = "msg">
 </div>
</div> 
 Vue.directive( 'focus',{//全局注册指令
 bind ( el,binding,vnode,oldVnode ) { //调用一次,指令一绑定在元素身上就会触发
   // console.log( 'bind focus' )
   // console.log( 'el',el  ) // el 指令绑定的元素
   // console.log( 'binding',binding ) // 指令的详细信息
   // console.log( 'vnode', vnode )  // 当前绑定元素的信息
   // console.log( 'oldVnode',oldVnode ) // 上一个绑定元素的信息
   // el.style.background = 'red'
 },
 inserted (  el,binding,vnode,oldVnode ) { // 当前绑定的元素插入父节点时调用
   el.focus()
   if( binding.modifiers.yyb ){
     el.style.color = 'green'
   }else{
     el.style.color = 'red'
   }
   console.log( binding )
   console.log( 'inserted ' )
 },
 update ( el, binding, vnode, oldVnode ) {  // 当前指令绑定的元素发生改变
   console.log( 'update' )
   console.log( 'el',el  ) // el 指令绑定的元素
   console.log( 'binding',binding ) // 指令的详细信息
   console.log( 'vnode', vnode )  // 当前绑定元素的信息
   console.log( 'oldVnode',oldVnode ) // 上一个绑定元素的信息
 },
 componentUpdated ( el,binding,vnode,oldVnode) { //当前绑定元素发生改变,或是子元素发生改变
   console.log( 'componentUpdated' )
 },
 unbind ( el,binding,vnode,oldVnode) { // 组件销毁时触发
   console.log( 'unbind' )
 }
})

new Vue({
 el: '#app',
 data: {
   msg: 1000,
   flag: true
 },
 directives: {//局部注册指令
   'focus': {
     bind () {

     },
     inserted () {

     },
     update () {

     },
     componentUpdated () {

     },
     unbind () {
       
     }
   }
 }
})

3. 自定义的事件

  • v-on:click = ‘aa’
  • v-on:yyb = ‘aa’
  • v-on:before-enter: ‘’
  • v-on:aa = ‘fn’
  1. 自定义事件
    事件的发布
    事件的订阅
    <div id="app"></div>
    
     var vm = new Vue({
      el: '#app'
    })
    vm.$on(事件的名称,事件的回调)
    //事件的发布
    vm.$on('aa',function(){
      alert( 'aa' )
    })
    // 事件的订阅
    // vm.$emit(事件的名称)
    vm.$emit( 'aa' )
    
  2. 自定义事件的使用形式
    1. 组件生命周期中发布事件,通过某一个事件处理程序调用
  <div id="app">
    <button @click = 'fn'> 点击 </button>
  </div>
   var vm = new Vue({
     el: '#app',
     methods: {
       fn () {
         this.$emit('aa')
       }
     },
     mounted () {//组件生命周期中发布事件,通过某一个事件处理程序调用
       this.$on('aa',function(){
         alert('aa')
       })
     }
   })

  1. 绑定在组件身上 , 通过 v-on 绑定,可以实现子父组件通信

4. 组件通信 单项数据流 >9种

  1. 父子组件通信:父组件将自己的数据传递给子组件

    1. 子组件把父组件的数据通过属性绑定的形式传递给自己,单项数据绑定

      <Son :aa = "money"></Son>

    2. 子组件在自己的配置项中通过 props 来接收这个属性

        Vue.component('Son',{
          template: '#son',
          // props: ['aa'],
          props: {
            // 属性: 属性的数据类型  给数据做属性验证,验证数据类型
            'aa': Number 
          }
        })
    
    1. 这个属性可以直接向全局变量一样使用
      <p> 我老爸给了我:{{ aa }} 钱 </p>
    
  2. 子父组件通信 :子组件将数据发送给父组件

    1. 方法1,自定义事件

      • 流程:
      1. 父组件中定义一个数据,然后在methods定义一个方法用来修改这个数据
        Vue.component('Father',{
           template: '#father',
           data () {
             return {
               num: 0
             }
           },
           methods: {
             add ( val ) {
               console.log('add')
               this.num += val
             }
           }
         })
      
      1. 父组件通过自定义事件的形式,将父组件的一个方法传递给子组件

        <Son @aa = 'add'></Son>

      2. 子组件可以通过 this.$emit( 自定义事件名称,参数1,参数2…) 来订阅这个自定义事件

        Vue.component('Son', {
              template: '#son',
                data () {
                    return {
                       money:1000
                   }
                },
                methods:{
                   give () {
                        this.$emit('send',this.money)//子组件通过this.$emit来订阅这个自定义事件
                    }
               }
          })
      
    2. 方法2,父组件将一个方法直接通过单向数据绑定的形式传递给子组件,子组件通过props接收,然后直接使用

    3. 方法3,父组件可以将一个对象型的数据传递给子组件,子组件修改了这个数据,父组件也同样会修改

      • 这个形式违反了单向数据流,用的少
  3. 非父子组件通信

    1. 使用ref链绑定
      • ref不仅可以绑定组件,也可以绑定普通元素
      <!-- 举例 -->
      <div id="app">
        <Brother ref="brother"></Brother>
        <hr>
        <Sister ref="sister"></Sister>
      </div>
      <template id="brother">
       <div>
            <h3>brother</h3>
            <button @click="give">传递数据</button>
           <p>brother的数据是:{{ money }}</p>
        </div>
      </template>
      <template id="sister">
        <div>
           <h3>sister</h3>
            <p>sister的数据是:{{ money }}</p>
        </div>
     </template>
    
     //非父子组件通信:通过ref链,ref链的绑定必须通过父组件来看
          Vue.component ('Brother',{
             template:'#brother',
              data () {
                 return {
                      money:1000
                  }
              },
              methods:{
                  give (){
                     this.$parent.$refs.sister.money=this.money//通过父级找到子级
                  }
             }
         })
         Vue.component ('Sister',{
             template:'#sister',
             data (){
                 return {
                      money:0
                  }
              }
          })
       new Vue({
         el: '#app',
          // mounted (){
         //     console.log(this)
          // }
        })
    
    1. 使用事件总线(bus总线)
    <!-- 举例 -->
     <div id="app">
       <Brother></Brother>
       <hr>
       <Sister></Sister>
    </div>
    <template id="brother">
       <div>
           <h3>brother</h3>
           <button @click="give">传递</button>
           <p>brother的数据是:{{ money }}</p>
       </div>
    </template>
    <template id="sister">
       <div>
           <h3>sister</h3>
           <p>sister的数据是:{{ money }}</p>
       </div>
    </template>
    
    
      //非父子组件通信:事件总线,通过事件来做
    //    事件的发布  $on(方法名称,回调函数)
    //    事件的订阅  $emit(方法名称)
    //通过new Vue开辟另外一个实例,再用这个实例上面的$on和$emit方法
    var bus = new Vue()
    Vue.component('Brother', {
       template: '#brother',
       data() {
           return {
               money: 1000
           }
       },
       methods: {
           give() {
               bus.$emit('give',this.money)//通过参数的形式传递数据
           }
       }
    })
    Vue.component('Sister', {//自己管理自己的数据
       template: '#sister',
       data() {
           return {
               money: 0
           }
       },
       mounted () {//组建一创建就要有这个数据
           bus.$on('give', (val) => {//这里要用箭头函数,否则this会丢失
               this.money += val
           })
       }
    
    })
    new Vue({
       el: '#app',
    
    })
    
  4. 多组件的状态共享 vuex( 目前不讲, 改天)

  5. 多级组件通信 ( $attr 扩展 )

  6. vue-router ( 目前不讲, 改天)

  7. 在一个组件当中,自己的数据由自己管理

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值