Vue组件的事件、内容插槽、组件间的通信的介绍与案例

组件的事件

流程:外部绑定自定义事件、外部写事件处理函数、内部事件绑定,内部写触发函数

    <div id="box">

            <input type="button" v-bind:value="str" @click="fn" />
            <!-- 自定义标签需要自定义事件 -->
            <!-- 正常绑定事件,事件名自定义 -->
            <book :name="bookObj.name" @myclick="fn02"></book>

        </div>

let vm =new Vue({
        el:"#box",
        // 局部注册组件
        components:{
            "book":book
        },
        data:{
            bookObj:{
                name:"三国演义",
            },
            str:"ddd"
        },
        methods:{
            //自定义标签的事件函数也在这里调用
            fn(e){
                console.log("fn",e);
            },
            fn02(str){
            //参数str由内部组件触发函数传过来
                console.log("fn02",str);
            }

        }
    });

子组件中

    template:`
            <div>
                <h1>{{title}}</h1>
                <p @mouseover="myclickHandle">书名:{{name}}</p>
                <p>作者:{{author}}</p>
                <p>价格:{{price}}</p>
            </div>
        `,
        data:function(){       
            return {
              title:"书籍详情"  
            };
        },
        methods:{
            //触发事件
            myclickHandle(){
                // 触发组件的自定义事件(绑定的事件名)
                this.$emit("myclick",this.title);
            }
        }


组件的内容插槽

组件的内容就是innerHTML,vue使用slot分发内容

流程:props用来处理标签的属性,sloat用来处理标签的内容

单个插槽

<div id="app">
        <person>
            <div>我是div</div>
        </person>        
    </div>

let person = {      
        template:`<div>
                        <hr/>
                            <p>我是上p</p>
                            <slot></slot>
                            <p>我是下p</p>
                        <hr/>
                    </div>`
    };

    new Vue({
        el:"#app",
        components:{
            person
        }
    });

具名插槽(多个插槽需要使用名字)

如果父级给子级传来了好多DOM(HTML元素),而且需要把不同的DOM放在子组件不同位置时,就需要给slot起名字,这就是具名插槽。slot元素可以用一个特殊的属性name 来配置如何分发内容。

<div id="">
            <p>三生膳食</p>
            <book>
                <!-- 给要插入的标签起slot名字,父模板放到子组件里面,是分发的概念 -->
                <p slot="s1">嘿嘿</p>
                <p slot="s2">嘿嘿哈哈</p>
            </book>
        </div>

    template: `
            <div>
                <h1>{{title}}</h1>
                <slot name="s1"></slot>
                <p>价格:{{price}}</p>
                <slot name="s2"></slot>
            </div>
        `,


编译作用域

父组件模板的内容在父组件作用域内编译,子组件模板的内容在子组件作用域内编译

换句话说:子组件模板的数据来自于子组件的配置项,在html中的模板数据来自于父组件的配置项,模板是谁的,数据就来源于谁


组件间的通信

组件之间传递数据,根据关系(父子,兄弟)会有不同的方式

父传子(父改子)

1:使用props

2:使用refs

子传父

1:使用事件

兄弟:

1:事件总线

2:集中管理

refs

标签就是组件,组件就是对象,获取标签就是获取对象,就可以对里面的数据进行操作

如果某个标签使用了ref属性,在vue对象中,就能用this.$refs访问,就可以操作该dom

     <div id="">
            <input type="button" name="" id="" value="" @click="fun"/>
            <book :name="bookObj.name" :author="bookObj.author" :price="bookObj.price" ref="bookid"></book>
            <p ref="p1">我是p</p>
        </div>

let book = {
        props: ["name", "author", "price"],
        template: `<div>
                <h1>{{title}}</h1>
                <p>书名:{{name}}</P>
                 <p>作者:{{author}}</p>
              <p>价格:{{price}}</p>
                </div>`,
        data() {
            return {
                title: "书籍信息"
            }
        },
        methods:{
            chuan(str){
                console.log(str)
            }
        }
    }

let vm = new Vue({
        el: "div",
        components: {
            "book": book
        },
        data: {
            bookObj: {
                name: "三国",
                author: "嘿嘿",
                price: 25
            }
        },
        methods: {
            fun() {
                this.$refs.p1.style = "font-size:25px",
                this.$refs.p1.innerHTML="我确实累了",
                //获取的是dom,dom是子组件,就是获取的组件对象
                this.$refs.bookid.chuan("heihei")

            }
        }
    })

兄弟组件间传值(事件总线)

通过一个空的vue实例作为桥梁,实现兄弟组件间的通信,传值的兄弟绑定触发事件,接值的兄弟绑定事件,和事件处理函数

    <div id="box">
            <person></person>
            <hr />
            <dog></dog>
        </div>

    // 定义一个事件总线对象(就是vue对象)
    // 全局变量
    let bus = new Vue();

let person = {
        template: `
            <div>
                <h1>我是人</h1>
                <input type="button" value=" 传 " @click="fn">   
            </div>
        `,
        data() {
            return {
                msg: "hi,小可爱!"
            }
        },
        methods: {
            fn() {
                // 触发事件
                bus.$emit("eclick", this.msg);
            }
        }
    };

    // dog里绑定事件
    let dog = {
        template: `
            <div>
                <h1>我是小可爱</h1>
            </div>
        `,
        data() {
            return {
                name: ""
            }
        },
        created() {
            // 绑定事件的另一种方式  ---给bus绑定事件和事件处理函数
            bus.$on("eclick", (str) => {
                this.name = str;
                console.log("str", str);
            })
        }

    };

    let vm = new Vue({
        el: "#box",
        // 局部注册组件
        components: {
            person,
            dog
        }
    });

集中管理($root)兄弟间传值

把数据存到根实例的data中,其他组件可以直接修改和使用

子改父,父改子实现传递

定义:

new Vue({
  data:{
      a:1
  }
})

使用

//子组件内部
this // 子组件本身
this.$root // vm 根实例
this.xx //组件内部数据
this.$root.a //根实例数据

 <div id="box">
            <person></person>
            <hr />
            <dog :str="msg"></dog>
        </div>

let person = {
        template: `
        <div>
            <h1>我是人</h1>
            <p>{{$root.msg}}</p>
            <input type="button" value=" 传 " @click="fn">   
        </div>
    `,
        methods: {
            fn() {
                this.$root.msg = "小可爱,我爱你!";
            }
        }
    };

    let dog = {
        props: ["str"],
        template: `
        <div>
            <h1>我是小可爱</h1>
            <p>{{str}}</p>
        </div>
    `
    };

    let vm = new Vue({
        el: "#box",
        // 局部注册组件
        components: {
            person,
            dog
        },
        data: {
            msg: "hi,我的小可爱"
        }
    });


动态组件

实现在不同组件之间进行动态切换

使用<component :is="自定义标签名">实现

<div id="app">
        <span @click="show(0)">娱乐</span>|
        <span  @click="show(1)">八卦</span>|
        <span @click="show(2)">体育</span>
        <div>
            <component :is="currCom"></component>
        </div>
</div>

let yuLe = {
    template:"<div>娱乐新闻</div>"
}

let eightGua = {
    template:"<div>八卦新闻</div>"
}

let sports = {
    template:"<div>体育新闻</div>"
}

new Vue({
    el:"#app",
    data:{
        currCom:"yuLe",
        coms:["yuLe","eightGua","sports"]
    },
    methods:{
        show(index){
            this.currCom = this.coms[index];
        }
    },
    components:{
        yuLe,eightGua,sports
    }
});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值