Vue第9天 数据传递(子传父/插槽)

子组件如何传递数据给父组件呢?通过自定义事件来传递:

    const cpn={
        template:'#cpn',
        data(){
            return {
                categories:[
                    {id:'aaa',name:'热门推荐'},
                    {id:'bbb',name:'手机数码'},
                    {id:'ccc',name:'家电办公'},
                    {id:'ddd',name:'电脑维修'},

  子组件的的信息保存在categories中,我们在界面用button把他们展示了出来。

<template id="cpn">
    <div>
        <button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
    </div>
</template>

  可以看到每次点击子组件都能通过btnClick函数得知到底是哪个选项被点击了。可是问题是父组件不知道,我们要把这个信息传递给父组件,那么就通过这个btnClick函数来写:

            btnClick(item){
                //目标是传item到父组件
                this.$emit('itemclick',item)
            }

  这里通过$emit('事件名',传递内容)来吧内容发送给父组件,同时父组件需要进行接收:

<div id='app'>
    <cpn @itemclick="cpnClick"></cpn>
</div>

  这里通过@事件名=‘父组件方法’ 来进行接收,父组件方法cpnClick用来写接收的逻辑:

        methods:{
            cpnClick(item){
                console.log("父组件接受信息",item.name)
            }
        }

  这里就可以打印出从子组件传递过来的item对象了。

  总结一下子组件传递父组件的逻辑:1.子组件通过定义一个函数来准备发送包含传递信息的item对象。2.在这个函数中通过this.$emit('事件名',item)来发送。3.父组件中使用子组件标签的地方使用@事件名=‘父组件函数名’进行绑定。 4.父组件的函数中可以随意处理对象了。

  开发中的父访问子:

  以下是子组件的一个方法和一个子组件的name,父组件如何希望触发这个方法?

    data(){
                    return {
                        name:"我是子组件的name"
                    }
                },
    methods:{
                    showMessage(){
                        console.log('this is showMessage')
                    }
                }

  使用refs在子组件上定一个一个名字即可:

<cpn ref="aaa"></cpn>

  这样父组件就知道他有个孩子叫aaa了,直接可以使用了:

            btnClick(){
                console.log(this.$refs.aaa.name)
            }

  通过this.$refs.aaa就抓到了这个对象,然后可以随意访问了。

 

  插槽的使用:

  为什么要使用插槽?因为很多组件都需要在不同的地方进行一些改进,例如导航栏有的时候需要搜索栏,有的时候不需要搜索栏,我们为了让组件具有可扩展性,所以引入插槽。也就是预留出一些空间等待用组件进行填充。

<template id="cpn">
    <div>
        <h2>我是组件</h2>
        <slot><button>默认值</button></slot>
    </div>
</template>

  这里使用slot标签设计一个插槽,默认值是一个button,也就是说当你不给这个插槽进行定义的时候就显示一个button出来。

<div id="app">
    <cpn><button>按钮</button></cpn> 
    <cpn><span>span标签</span></cpn> 
    <cpn><i>i标签</i></cpn> 
</div>

  这里就可以看到使用的时候我们只需要在组件内部重新写一个内容就可以加载到插槽上去了。

  1.只设置一个插槽但是实现的时候写了多个组件,插槽显示? 答:全部组件。

   如何替换多个插槽呢?

<template id="cpn">
    <div>
        <slot name="left"><span>左侧插槽</span></slot>
        <slot name="center"><span>中间插槽</span></slot>
        <slot name="right"><span>右侧插槽</span></slot>
    </div>
</template>

  首先我们要给插槽进行命名,name=“xxx”的方式。当然后面的默认值可以不写。然后我们在使用插槽的时候指定名字:

<div id="app">
    <cpn><span slot="center">标题替换</span></cpn> 
    <cpn><button slot="left">左边替换</span></cpn> 
</div>

  这样就是第一个cpn的中间插槽被替换掉了,第二个cpn的左边被替换成了button:

 

 

  似乎已经换成v-slot了(弹幕说的)到时候再看一下文档。

  作用域:模版中出现了很多变量的时候,查找变量的时候并不关心组件,先去查找模版中是否有变量。组件中出现了变量,则从组件中查找变量。谁的变量去谁那里找不会跨作用域。

   既然有了作用域那么在父组件中希望插槽显示子组件的数据怎么办呢?

  

<template id="cpn">
    <div>
        <slot :aaa="pLanguages">
            <ul>
                <li v-for="item in pLanguages">{{item}}</li>
            </ul>
        </slot>
    </div>
</template>

  通过:传递内容名字=“传递内容”这样就可以在模版中的组件使用:

    <cpn>
        <template slot-scope="slot">
            <span v-for="item in slot.aaa">{{item}}-</span>
        </template>
    </cpn>

  这样slot.aaa就是传入的pLanguagues中的内容了。

posted @ 2020-04-16 22:15  灰人  阅读(794)  评论(0)    收藏  举报