组件通信、过滤器、自定义指令等

7 篇文章 0 订阅

组件通信、过滤器、自定义指令等

组件的通信

组件是一个聚合体,合并项目,组件之间通过数据通信建立联系。

父子组件通信
<template id="father">
    <div>
        <h3> 这里是father </h3>
        <!-- 父组件将自己的数据绑定给子组件身上 -->
        <Son :money = "money"></Son>  
    </div>
</template>

<template id="son">
    <div>
        <h3> 这里是son </h3>
        <p> 我收到了父亲给的 {{ money }} </p>
    </div>
</template>

<script>
  Vue.component('Father',{
    template: '#father',
    data () {
      return {
        money: 10000
      }
    }
  })

  Vue.component('Son',{
    template: '#son',
    props: ['money'] //子组件通过props属性接受
  })

  new Vue({
    el: '#app'
  })
</script>
  • data选项是一个函数

  • 组件是一个聚合体,也是一个整体,它需要一个独立的作用空间,也就是它的数据需要是独立的,目前js的最大特点是函数式编程,而函数恰好提供了一个独立作用域,所以我们data在出根组件外都是函数

  • data函数需要一个返回值

    • Vue通过es5的Object.definePerproty属性对一个对象进行getter和setter设置,而data选项是作为Vue深入响应式核心的选项
  • 过程

      1. 父组件将自己的数据同 v-bind (:)绑定在 子组件身上
      2. 子组件通过 props属性接收
    • props属性数据验证
      • 验证数据类型
      • 验证数据大小【 判断条件 】
    // props: ['money']
    // 数据验证
    // props: {
    //   'money': Number 
    // }
    props: {
        'money': {
            validator ( val ) { // 验证函数
                return val > 2000
            }
        }
    }
    
    • 第三方验证:
      • TypeScript [ TS ]
      • 插件 vue-validator 等
子父组件通信
<body>
  <div id="app">
    <Father></Father>
  </div>
  <template id="father">
    <div>
      <h3> 这里是father </h3>
      <p> 我现在有 {{ gk }} </p>
      <Son @give = "fn"></Son>
    </div>
  </template>

  <template id="son">
    <div>
      <h3> 这里是son </h3>
      <button @click = "giveHongbao"> 给父亲红包 </button>
    </div>
  </template>
</body>
<script>
   Vue.component('Father',{
    template: '#father',
    data ( ) {
      return {
        gk: 0
      }
    },
    methods: {
      fn ( val ) {
        this.gk = val  
      }
    }
  })

  Vue.component('Son',{
    template: '#son',
    data () {
      return {
        money: 5000        //要传给父组件的数据
      }
    },
    methods: {
      giveHongbao () {
        this.$emit('give',this.money)  //触发give事件,传入的参数为this.money
      }
    }
  })
  new Vue({
    el: '#app'
  })
</script>
  • 是通过自定义事件
    • 事件的发布
      • 通过绑定元素身上实现
    • 事件的订阅
      • 通过this.$emit触发
非父子组件通信
  • ref链
<body>
  <div id="app">
    <Father></Father>
  </div>
</body>

<template id="father">
  <div>
    <h3> 这里是父组件 </h3>
    <Girl @fn = "fn"></Girl>
      <!-- 父组件获得son组件 -->
    <Son ref = "son"></Son>   
  </div>
</template>

<template id="son">
  <div>
    <h3> 这里是son组件 </h3>
    <p v-show = "flag"> o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o o(╥﹏╥)o </p>
  </div>
</template>

<template id="girl">
  <div>
    <h3> 这里是girl组件 </h3>
    <button @click = "kick"> 揍 </button>
  </div>
</template>

<script>
  Vue.component('Father',{
    template: '#father',
    methods: {
      fn () {
        this.$refs.son.changeFlag()   //获得son组件,通过this.$refs.son访问
      }
    }
  })
  Vue.component('Son',{
    template: '#son',
    data () {
      return {
        flag: false 
      }
    },
    methods: {
      changeFlag () {
        this.flag = !this.flag   
      }
    }
  })
  Vue.component('Girl',{
    template: '#girl',
    methods: {
      kick () {
        this.$emit('fn')  //调用父组件中的fn方法
      }
    }
  })
  new Vue({
    el: '#app'
  })
</script>
  1. 自己的数据自己更改,son组件中的flag需要用son组件中的方法changeFlag修改.
  2. 属性绑定,父组件获得son组件
  3. 父组件中定义一个方法fn,调用son组件中的changeFlag方法,用$refs
  4. Girl组件通过方法调用this.$emit(‘fn’)调用父组件中的fn方法,修改son组件中的flag数据
  • bus事件总线
  //html部分与上方一样
  var bus = new Vue() //定义全局bus

  Vue.component('Father',{
    template: '#father'
  })
  Vue.component('Son',{
    template: '#son',
    data () {
      return {
        flag: false
      }
    },
    mounted () { // 也是一个选项,表示组件挂载结束 , 也就是说我们可以在View视图中看到这个组件了
      // bus.$on(自定义事件名称,执行的事件处理程序)
      var _this = this 
      bus.$on('cry',function () {
        _this.flag = true
      })

    }
  })
  Vue.component('Girl',{
    template: '#girl',
    methods: {
      kick () {
        bus.$emit('cry') //调用cry方法
      }
    }
  })
  new Vue({
    el: '#app'
  })
非常规通信方案
  • 如果常规方案可以实现,尽量不要用非常规方案。
  1. 实现子父通信

    <body>
      <div id="app">
        <Father></Father>
      </div>
      <template id="father">
        <div>
          <h3> father组件 </h3>
          <p> {{ gk }} </p>
          <Son :fn = "fn"></Son>
        </div>
      </template>
    
      <template id="son">
        <div>
          <h3>
            son组件
          </h3>
          <button @click = "fn( money )"> 给红包 </button>
        </div>
      </template>
    
    </body>
    <script>
      // 父组件通过 v-bind 绑定一个方法给子组件
      // 子组件通过 props选项接收这个方法,然后直接调用
      Vue.component('Father',{
        template: '#father',
        data () {
          return {
            gk: 0
          }
        },
        methods: {
          fn ( val ) {
            this.gk = val
          }
        }
      })
      Vue.component('Son',{
        template: '#son',
        data () {
          return {
            money: 1000
          }
        },
        props: ['fn']  //获得上方绑定的fn方法
      })
      new Vue({
        el: '#app'
      })
    </script>
    
  2. 父组件 通过 v-bind 绑定 一个对象类型数据 给子组件

    • 子组件直接使用,如果更改这个数据,那么父组件数据也更改了
    • 违背了单向数据流
     Vue.component('Father',{
        template: '#father',
        data () {
          return {
            money: {
              num: 1000
            }
          }
        }
      })
      Vue.component('Son',{
        template: '#son',
        props: ['money']
      })
    

插槽(slot)

普通插槽
  <div id="app">
    <Hello>
      <!-- 电脑要加的内存条 -->
      <p> 这是组件的内容 </p> 
    </Hello>
  </div>

  <template id="hello">
    <div>
      <h3> hello </h3>
      <p> 又是嗨的一天 </p>
      <!-- 电脑中的卡槽 -->
      <slot></slot>
    </div>
  </template>
具名插槽
<div id="app">
    <Hello>
      <!-- 电脑要加的内存条 -->
      <header slot = "header"> 头部 </header>
      <footer slot = "footer"> 底部 </footer>
    </Hello>
  </div>

  <template id="hello">
    <div>
      <slot name = 'header'></slot>
      <h3> hello </h3>
      <p> 又是嗨的一天 </p>
      <!-- 电脑中的卡槽 -->
      <slot name = "footer"></slot>
    </div>
  </template>
  • 以上内容是Vue 2.5.x的版本

  • Vue 2.6以上使用v-slot

    • 作用:可以将组件的数据在组件的内容中使用
    <div id="app">
        <Hello>
           <!--          此处对应下方name属性                            -->  
          <template v-slot:xxx = "slotProps">
            <div>
              {{ slotProps.msg }}
            </div>
          </template>
        </Hello>
          
      </div>
    
      <template id="hello">
        <div>
          <h3> hello </h3>
          <p> 又是嗨的一天 </p>
          <slot :msg = "msg" name = "xxx"></slot>
        </div>
      </template>
    

过渡效果

Vue框架使用css3过渡效果或是js动画

Vue内部提供了一个叫做transition的过渡组件

使用transition包裹过渡元素,那么会自动添加 6 个类名 8个钩子函数

  • 默认 类名 开头 v
  • 如果有name属性,那么使用 这个name属性值作为类名开头
  <div id="app">
    <button @click = "flag = !flag"> 点击 </button>
    <transition name = "slide-fade">
      <p v-if = "flag"> 动画元素 </p>
    </transition>
  </div>

实现方式

  1. 第一种 [ 在 CSS 过渡和动画中自动应用 class 【 自己写 】 ]

  2. 第二种: animate.css 【 推荐 】第三方css动画库

    <!-- 需引入animate -->
    <div id="app">
        <button @click = "flag = !flag"> 点击 </button>
        <transition name = "slide-fade"
          enter-active-class = "animated bounceIn"
          leave-active-class = "animated bounceOut"
        >
          <p v-if = "flag"> 动画元素 </p>
        </transition>
      </div>
    
  3. 第三种: Vue提供了8个javascript钩子,我们需要自定义js动画

  4. 第四种: 使用第三方插件: Velocity.js

自定义指令

<body>
  <div id="app">
    <input type="text" placeholder="请输入" v-focus = "1000">
  </div>
</body>
<script>
  // Vue.directive(自定义指令名称,选项)

   Vue.directive('focus',{
     bind (el,binding,vnode,oldVnode) { // 当自定义指令和元素绑定时触发
      
    },
     inserted ( el,binding,vnode,oldVnode ) { // 当自定义指令绑定的元素插入到页面时触发
      //初始值为v-focus的属性值   
      el.value = binding.expression   
      // 页面开启时自动获得焦点   
      el.focus()

    },
     updated () { // 当自定义指令的元素或是他的子元素发生变化式触发

   },
    componentUpdate () { //当自定义指令的元素或是他的虚拟子节点 发生变化式触发

     },
     unbind () { // 当自定义指令绑定的元素解绑时触发
    }
  })
  new Vue({
    el: '#app',
    //上方是全局写法,此处是局部定义
    directives: {
      'focus': {
        bind () {

        },
        inserted ( el ) {
          el.focus()
        }
      }
    }
  })
</script>

过滤器

作用:对已有的数据做数据格式化 。

  • 使用格式:

    • 已有数据 | 过滤器名称(arg1,arg2)
      <img  :src = "item.img | imgFilter " >
    
    • | 称为管道符
  • 定义

   // Vue.filter(过滤器名称,function ( val ) {})
   // 全局定义
   Vue.filter('imgFilter',function ( val ) {
     //val就是需要格式化的数据
     return val.replace( reg, '……') // 要替换的数据内容
   })
  new Vue({
    el: '#app',
    data: {
      lists: []
    },
    filters: { //局部定义
      // 过滤器名称:function () {}
      'imgFilter': function ( val ) {
        return val.replace( reg, '……') // 要替换的数据内容
      }
    },
    methods: {
      getList () {
        fetch('./data/list.json')
          .then( res => res.json())
          .then( data => {
            this.lists = data.movieList
          })
          .catch( error => console.log( error ))
      }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值