04-Vue.js组件通信、slot插槽、过渡效果、过滤器、自定义指令

一、组件的通信

1、为什么通信?

  • 组件是一个聚合体,合并项目后,各个组件之间需要建立联系

2、分类
<1>父子组件通信

  • data选项为什么是一个函数?
    • 因为组件是一个聚合体,也是一个整体,它需要一个独立的作用空间,它的数据是需要独立的。目前JS最大的特点是函数式编程,而函数恰好提供了一个独立作用域,所以data在除了根组件外的组件里都是函数
  • 为什么data函数需要一个返回值,并且返回的是对象?
    • Vue通过es5的Object.definedPerproty属性对一个对象进行getter和setter设置,而data选项作为Vue深入响应式核心的选项
  • 过程:
    • 父组件将自己的数据同v-bind绑定在子组件上
    • 子组件通过props选项接收
  • 数据验证
    • props属性数据验证
      • 验证数据类型
      • 验证数据大小(返回判断条件)
    • 第三方验证
      • TypeScript
      • Vue-validator 插件
    <template id="father">
        <div>
            <p>父组件</p>
            <Son :num='num'></Son>
        </div>
    </template>

  <template id="son">
        <div>
            <p>子组件</p>
            <p>父组件给了我{{num}}</p>
        </div>
    </template>
    Vue.component("Father", {
        template: "#father",
            data() {
            return {
                num: 100
            }
        }
    })
    Vue.component("Son", {
        template: "#son",
        // props: ['num']
        // props: {
        //     num: Number
        // }
        props: {
            num: {
                validator(val) {
                    return val > 200 //数据验证
                }
            }
        }
    })

<2>子父组件通信

  • 通过自定义事件$emit
  • 事件的发布(通过绑定元素实现)
  • 事件的订阅(通过this.$emit触发)
    <div id="app">
        <Father></Father>
    </div>

    <template id="father">
        <div>
            <p>父组件</p>
            <p>子组件给了我{{fNum}}</p>
            <Son @give='fn'></Son>
        </div>
    </template>
    <template id="son">
        <div>
            <p>子组件</p>
            <p></p>
            <button @click='giveNum'>给父组件num</button>
        </div>
    </template>
    Vue.component("Father", {
        template: "#father",
        data() {
            return {
                fNum: 0
            }
        },
        methods: {
            fn(val) {
                this.fNum = val;
            }
        }
    })
    Vue.component("Son", {
        template: "#son",
        data() {
            return {
                num: 1234
            }
        },
        methods: {
            giveNum() {
                this.$emit("give", this.num);
            }
        }
    })

<3>非父子组件通信

  • 通信方式1:
    <template id="father">
        <div>
            <p>父组件</p>
            <Son @fn="fn"></Son>
            <Daughter ref="daughter"></Daughter>
        </div>
    </template>
    <template id="son">
        <div>
            <p>子组件1</p>
            <button @click="send">给子组件2发消息</button>
        </div>
    </template>
    <template id="daughter">
        <div>
            <p>子组件2</p>
            <p v-show='flag'>子组件1给了我发消息了</p>
        </div>
    </template>
    Vue.component("Father", {
        template: "#father",
        methods: {
            fn() {
                this.$refs.daughter.changeFlag() //!!!!!!!!!
            }
        }
    })
    Vue.component("Son", {
        template: "#son",
        methods: {
            send() {
                this.$emit('fn')//!!!!!!!!
            }
        }
    })
    Vue.component("Daughter", {
        template: "#daughter",
        data() {
            return {
                flag: false
            }
        },
        methods: {
            changeFlag() {
                this.flag = !this.flag
            }
        }
    })
  • 通信方式2:bus
    <template id="father">
        <div>
            <p>这是父组件</p>
            <Son></Son>
            <Daughter></Daughter>
        </div>
    </template>

    <template id="son">
        <div>
            <p>这是子组件1</p>
            <button @click="send">给子组件2发送消息</button>
        </div>
    </template>

    <template id="daughter">
        <div>
            <p>这是子组件2</p>
            <p v-if='flag'>我收到了子组件1传来的消息</p>
        </div>
    </template>
    var bus = new Vue();//!!!!!!!!!!!!!
    Vue.component("Father", {
        template: "#father",
    })
    Vue.component("Son", {
        template: "#son",
        methods: {
            send() {
                bus.$emit("get")//!!!!!!!!!!!!1
            }
        }
    })
    Vue.component("Daughter", {
        template: "#daughter",
        data() {
            return {
                flag: false
            }
        },
        mounted() {  //表示组件挂载结束。可在视图中看到该组件
            var that = this;
            bus.$on("get", function () {//!!!!!!!
                return that.flag = !that.flag;
            })
        }
    })

<4>非常规通信

  • 可以实现子父通信
  • 方式1:
    • 父组件通过v-bind绑定一个方法给子组件
    • 子组件通过props选项接收这个方法,然后直接调用
    <template id="father">
        <div>
            <p>这是父组件</p>
            <p>{{fnum}}</p>
            <Son :fn="fn"></Son>
        </div>
    </template>
    <template id="son">
        <div>
            <p>这是子组件</p>
            <button @click="fn(num)">给父组件发消息</button>
        </div>
    </template>
    
    Vue.component("Father", {
        template: "#father",
        data() {
            return {
                fnum: 0
            }
        },
        methods: {
            fn(val) {
                this.fnum = val
            }
        }
    })
    Vue.component("Son", {
        template: "#son",
        data() {
            return {
                num: 12345
            }
        },
        props: ['fn']
    })
  • 方式2:
    • 父组件通过v-bind绑定一个对象类型数据给子组件
    • 子组件直接调用,如果更改这个数据,父组件的数据也更改(因为引用同一个地址,但违背了单向数据流)
    <template id="father">
        <div>
            <p>这是父组件</p>
            <p>{{fnum.num}}</p>
            <Son :fnum="fnum"></Son>
        </div>
    </template>
    <template id="son">
        <div>
            <p>这是子组件</p>
            <input type="text" name="" id="" v-model="fnum.num">
        </div>
    </template>
    Vue.component("Father", {
        template: "#father",
        data() {
            return {
                fnum: {
                    num: 1112222
                }
            }
        }
    })
    Vue.component("Son", {
        template: "#son",
        props: ["fnum"]
    })

二、slot 插槽

1、分类:

  • 普通插槽
  • 具名插槽 (给slot加一个name属性)
//Vue2.5的使用形式
<div d="app">
    <Hello>
        <header slot="header"></header>
        <footer slot="footer"></footer>
    </Hello>
</div>
<template id="hello">
    <div>
        <slot name="header"></slot>
        <slot name="footer"></slot>
    </div>
</template>

2、v-slot指令:可以将组件的数据在组件的内容中使用

//Vue2.6x的使用形式
//v-slot指令
    <div id="app">
        <Hello>
            <template v-slot:csq="Orange">
                <div>
                    <p>我在里面</p>
                    {{Orange.info}}
                </div>
            </template>
        </Hello>
    </div>
    <template id="hello">
        <div>
            <p>我在外面</p>
            <slot :info="info" name="csq"></slot>
        </div>
    </template>
    Vue.component("Hello", {
        template: "#hello",
        data() {
            return {
                info: "发送进来了"
            }
        }
    })

三、过渡效果

Vue框架使用css3和js实现过度效果
1、实现方式

  • 在 CSS 过渡和动画中自动应用 class
    Vue内部提供了<transition></transition>
    使用transition组件包裹过渡元素,会自动给过渡元素添加6个类名,8个钩子函数
    默认类名以v开头
    如果有name属性,则以name属性值开头
  • 可以配合使用第三方 CSS 动画库,如 Animate.css
    引入animate外部文件
    在animate官网查找动画效果,作为类名成对加在transition组件上
  • 在过渡钩子函数中使用 JavaScript 直接操作 DOM
    Vue提供了8个JS钩子,需要自定义JS动画
  • 可以配合使用第三方 JavaScript 动画库,如 Velocity.js

四、过滤器

1、作用
对已存在的数据做数据格式化

2、定义

//全局定义
//Vue.filter(过滤器名称:function(){
//}

//局部定义
    filters: {
      'imgFilter': function ( val ) { //val表示需要格式化的数据
        return val.replace( 'w.h', '128.180')
      }
    },

3、使用
<img :src = "item.img | imgFilter "/>

五、自定义指令

1、 定义形式

  • 全局定义
  • 局部定义
 //Vue.directive("自定义指令名",选项)
    Vue.directive("focus",{
        bind(el,binding,vnode,oldVnode){
            //当自定义指令和元素绑定时触发
        },
        inserted(el,binding,vnode,oldVnode){
            //当自定义指令绑定的元素插入到页面时触发
        },
         updated () { 
            // 当自定义指令的元素或是他的子元素发生变化式触发
        },
        componentUpdate () { 
            //当自定义指令的元素或是他的虚拟子节点 发生变化式触发
        },
        unbind () { 
            // 当自定义指令绑定的元素解绑时触发
        }
    })

2、使用

// Vue.directive('focus',{
  //   inserted ( el,binding,vnode,oldVnode ) { 
  //     if ( binding.modifiers.a ) {
  //       el.style.background = 'red'
  //     } else {
  //       el.style.background = 'blue'
  //     }
  //     el.value = binding.expression
  //     el.focus()

  //   },
  // })

  new Vue({
    el: '#app',
    directives: {
      'focus': {
        inserted ( el ) {
          el.focus()
        }
      }
    }
  })

六、swiper

swiper是一个实现滑动操作的第三方库
官网:swiper官网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值