Vue 组件 + 组件之间传值 + 组件插槽

Posted 鲸渔要加油

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 组件 + 组件之间传值 + 组件插槽相关的知识,希望对你有一定的参考价值。

组件

组件就是把各自独立的积木拼成一个整体然后进行数据交互


一、组件注册


1. 全局注册

组件注意事项

  • 全局组件 注册后,任何 vue实例 都可以用
  • 组件参数的data值必须是函数同时这个函数要求返回一个对象
  • 组件模板必须是单个根元素
  • 组件模板的内容可以是模板字符串
 Vue.component('组件名称', {
     data: function () {return{}},	// data 在这里是函数
     template: '模板'
 })

就是相当于封装了一个模板,然后任何 vue实例 都可以用它自定义的名字来调用它


2. 局部注册

  • 只能在当前注册它的vue实例中使用
 let aaa = {
     data() {
         return {
             ppp: 'ppp'
         }
     },
     template: `<div>{{ppp}}</div>`
 }
 // Vue 组件
 const vm = new Vue({
     el: '#box',
     components: {
         'xxx': aaa  // 使用 <xxx></xxx>
     }
 })


二、组件之间传值


1. 父组件向子组件传值

父组件在子组件的模板标签里面,使用属性传值给子组件的 props 接收,子组件直接template 定义模板里面使用

  • 父组件发送的形式是以属性的形式绑定值到子组件身上,有静态和加 : 的动态两种形式
  • 然后子组件用属性 props 接收
  • 在 props 中使用驼峰形式,模板中需要使用短横线的形式字符串形式的模板中没有这个限制

props 属性值类型

  • 字符串 String
  • 数值 Number
    静态绑定是传字符串,: 动态绑定是数值
  • 布尔 Boolean
    静态绑定是传字符串,: 动态绑定是布尔
  • 数组 Array
  • 对象 Object
<body>
    <div id="box">
        <ce-shi :pstr='pstr' :pnum='10' :pboo='true' :parr='parr' :pobj='pobj'></ce-shi>
    </div>

    <script src="../vue.js"></script>
    <script>
        Vue.component('CeShi', {
            props: ['pstr', 'pnum', 'pboo', 'parr', 'pobj'],
            template: `
            <div>
                <div>{{pstr}}</div>
                <div>{{pnum + 10}}</div>
                <div>{{pboo}}</div>
                <ul>
                    <li :key='index' v-for='(item,index) in parr'>{{item}}</li>
                </ul>
                <div>
                    <span>{{pobj.name}}</span>
                    <span>{{pobj.age}}</span>
                    <span>{{pobj.like}}</span>
                </div>
            </div>
            `
        })

        const vm = new Vue({
            el: '#box',
            data: {
                pstr: 'yjy',
                parr: [1, 2, 3],
                pobj: {
                    name: '远近渔',
                    age: 18,
                    like: 'me'
                }
            }
        })
    </script>
</body>

2. 子组件向父组件传值

虽然可以从子组件传数据到父组件,但别用
props 传数据的原则:单项数据流,只能父传子,不要子传父

  • 子组件调用 $emit() 方法触发事件
  • $emit() 第一个参数为自定义的事件名称,第二个参数为需要传递的数据
  • 父组件用 v-on 监听子组件的事件
<body>
    <div id="box">
        <ce-shi @big='dadada'></ce-shi>
        <div :style='{fontSize: font + "px"}'>{{parr}}</div>
    </div>

    <template id="moban">
        <div>
            <button @click='$emit("big")'>扩大</button>
        </div>
    </template>
    <script src="../vue.js"></script>
    <script>
        Vue.component('CeShi', {
            template: `#moban`,
        })

        const vm = new Vue({
            el: '#box',
            data: {
                parr: '远近渔',
                font: 10
            },
            methods: {
                dadada() {
                    this.font += 5
                }
            }
        })
    </script>
</body>

$event是固定写法

<body>
    <div id="box">
        <ce-shi @big='bbb($event)'></ce-shi>
        <div :style='{fontSize: font + "px"}'>{{msg}}</div>
    </div>

    <template id="moban">
        <div>
            <button @click='$emit("big", 100)'>变大</button>
        </div>
    </template>
    <script src="../vue.js"></script>
    <script>
        Vue.component('CeShi', {
            template: `#moban`,
        })

        const vm = new Vue({
            el: '#box',
            data: {
                msg: '远近渔',
                font: 10
            },
            methods: {
                bbb(v) {
                    this.font += v
                }
            }
        })
    </script>
</body>

3. 兄弟组件间传值

  • 兄弟之间传递数据需要通过 事件中心
    let hub = new Vue() 来作为 事件中心

  • 传递数据通过一个事件 触发 hub.$emit(名, 传递的数据)

  • 接收数据 ,在 mounted(){} 钩子中触发 hub.$on(名, (接收的值)=>{做的事}) 方法

  • 销毁事件 ,在父组件中通过 hub.$off(名) 方法名销毁之后无法进行传递数据

<body>
    <div id="box">
        <one></one>
        <two></two>
        <button @click='c'>禁止</button>
    </div>

    <script src="../vue.js"></script>
    <script>
        let hub = new Vue()

        Vue.component('one', {
            data() {
                return {
                    num: 0
                }
            },
            template: `
            <div>
                <div>one --- {{num}}</div>
                <button @click='a'>+++2</button>
            </div>
             `,
            methods: {
                a() {
                    hub.$emit('two-b', 2)
                }
            },
            mounted() {
                hub.$on('one-a', (v) => {
                    this.num += v
                })
            }
        })

        Vue.component('two', {
            data() {
                return {
                    num: 0
                }
            },
            template: `
            <div>
                <div>two --- {{num}}</div>
                <button @click='b'>+++1</button>
            </div>
             `,
            methods: {
                b() {
                    hub.$emit('one-a', 1)
                }
            },
            mounted() {
                hub.$on('two-b', (v) => {
                    this.num += v
                })
            }
        })

        const vm = new Vue({
            el: '#box',
            methods: {
                c() {
                    hub.$off('two-b')
                    hub.$off('one-a')
                }
            }
        })
    </script>
</body>


三、组件插槽

组件插槽的作用: 父组件向子组件传递内容(模板的内容)

因为父组件在子组件的模板里面写东西无法显示,所以使用插槽把父组件标签里面的内容传到子组件


1. 匿名插槽

插槽位置
子组件的模板里面预留 <slot></slot> 位置接收父的自定义内容

插槽内容
slot 里面可以写默认的内容,父的标签里面可以自定义内容

<body>
    <div id="box">
        <aaa>有刺客</aaa>
        <aaa></aaa>
    </div>

    <script src="../vue.js"></script>
    <script>
        Vue.component('aaa', {
            template:`
            <div>
                <strong>ERROR:</strong>
                <slot>123</slot>
            </div>
            `
        })
        
        const vm = new Vue({
            el: '#box',
        })
    </script>
</body>

2. 具名插槽

  • 使用 <slot> 中的 "name" 属性绑定元素
  • 模板里面写 <slot name='abc'></slot>
  • 标签里面写 <p slot="abc">xxxxxxx</p>
  • slot 属性 只能加给子组件里面的内容标签
  • 如果元素没有绑定 slot 属性 ,则放到默认的插槽 <slot></slot>
  • 一个个加属性太麻烦,可以放到总的 <template slot="abc"><p>xxx</p></template> 里面
<body>
    <div id="box">
        <aaa>
            <p slot="abc">xxx</p>
            <p slot="ggg">yyy</p>
            <p slot="www">zzz</p>
            <p>qwerqwerqwer</p>
            <p>asdfasdfasdfasdf</p>
        </aaa>
        
        <aaa>
            <template slot="abc">
                <p>xxx</p>
                <p>qwerqwerqwer</p>
                <p>asdfasdfasdfasdf</p>
            </template>   
            <template slot="ggg">
                <p>123</p>
                <p>321</p>
                <p>213</p>
            </template>   
        </aaa>
        
    </div>

    <script src="../vue.js"></script>
    <script>
        Vue.component('aaa', {
            template:`
            <div>
                <slot></slot>
                <slot name='ggg'></slot>
                <strong>123</strong>
                <slot name='abc'></slot>
                <slot name='www'></slot>
            </div>
            `
        })
        
        const vm = new Vue({
            el: '#box',
        })
    </script>
</body>

3. 作用域插槽

  • 好处,既可以父用子组件的slot,又可以使slot内容不一致
  • 因为子组件的东西一般都是封装好的,所以我们需要用父组件来对子组件进行加工
  • 先给子组件的模板的 <slot></slot> 自定义一个属性 <slot :shuxing="item"></slot>
  • 然后在父组件的模板标签里面使用 <template slot-scope='slotProps'></template> 获取子组件的数据
    slotProps 自定义的名字,是个对象,包含子组件里面的所有 slot 的属性
<body>
    <div id="box">
        <aaa :qwer='list'>
            <template slot-scope='slotProps'>
                <strong v-if='slotProps.shuxing.id==2'>{{slotProps.shuxing.name}}</strong>
                <span v-else>{{slotProps.shuxing.name}}</span>
            </template>
        </aaa>
    </div> 

    <script src="../vue.js"></script>
    <script>
        Vue.component('aaa', {
            props: ['qwer'],
            template: `
            <div>
                <div>
                    <li :key="item.id" v-for="item in qwer">
                        <slot :shuxing="item"></slot>
                    </li>
                </div>
            </div>
            `
        })

        const vm = new Vue({
            el: '#box',
            data: {
                list: [{
                    id: 1,
                    name: '远近渔'
                }, {
                    id: 2,
                    name: '渔渔渔'
                }, {
                    id: 3,
                    name: '渔渔子'
                }]
            }
        })
    </script>
</body>

以上是关于Vue 组件 + 组件之间传值 + 组件插槽的主要内容,如果未能解决你的问题,请参考以下文章

VUE_03 组件化思想全局|局部注册组件之间传值(父传子子传父兄弟传兄弟)匿名|具名|作用域插槽

Vue组件传值及插槽

Vue组件传值及插槽

Vue组件传值及插槽

vue中组件通信的方式

vue中组件通信的方式