2-组件的创建和使用以及组件之间的通信

210 阅读2分钟

组件的创建和使用

一个组件就是一个对象(html+css+js),组件分为全局组件局部组件。(组件须在创建Vue实例之前创建)

全局组件:创建之后就可以直接使用。
局部组件:创建之后需要挂载才能使用,且只能在挂载的组件或Vue实例中使用。

全局组件

全局组件通过Vue.component('组件名',{})创建,{}是一个对象,它和Vue实例一样有着datamethodscomputedtemplate等属性。其中template中可以设计我们想要的组件,需要注意的是它是用反引号``,且最外层用<div></div>将里面的内容包裹起来。同时这里的data和Vue实例中的有区别,它是一个函数,这个函数返回一个对象(方便后期维护,每一个组件只需要维护它自己的一个实例),在这个对象内可以写需要的属性。

<body>
    <div id="app">
        <Vcontent></Vcontent>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        Vue.component('Vcontent', {
            data() {
                return {
                    msg: 'hello 全局组件'
                }
            },
            template: `
            <div>
                我是全局组件
                <h2>{{ msg }}</h2>
                <button @click='handleClick'>点我</button>
            </div>
            `,
            methods: {
                handleClick(){
                    alert('hello 全局组件');
                }
            },
        })

        new Vue({
            el: '#app',
        })
    </script>
</body>

局部组件

使用局部组件需要牢记三个步骤:创建、挂载、使用。

局部组件通过const 组件名 = {}声明创建,Vue实例有一个components属性,将创建的局部组件挂载在其中即可在这个Vue实列绑定的元素中使用,同时也可以继续在局部组件的components属性中挂载其他的局部组件。

注意:创建全局组件使用的是component,而用于挂载局部组件的是components,这边稍不注意可能写错。

<body>
    <div id="app">
        <App></App>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        const App = {
            data() {
                return {
                    msg: 'hello 局部组件'
                }
            },
            template: `
            <div>
                我是局部组件
                <h2>{{ msg }}</h2>
                <button @click='hanldeClick'>点我</button>
            </div>
            `,
            methods: {
                hanldeClick() {
                    alert('hello 局部组件')
                }
            },
            components: {
                //可挂载其他组件
            }
        }

        new Vue({
            el: '#app',
            components: {
                App
            }
        })
    </script>
</body>

组件的通信

父传子(props)

  1. 在子组件的props中声明属性,接收从父组件中传入的数据
  2. 该属性可在子组件的template中任意使用
  3. 在父组件中的子组件标签上为子组件props中声明的属性绑定父组件需要传入的数据
<body>
    <div id="app">
        <App></App>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        Vue.component('Child',{
            template:`
            <div>{{ appMsg }}</div>
            `,
            props:['appMsg']
        },)

        const App = {
            data() {
                return {
                    msg: 'hello 子组件'
                }
            },
            //通过绑定将msg传入子组件
            template: `
            <div>
                <Child :appMsg='msg'></Child>
            </div>
            `,
        }

        new Vue({
            el: '#app',
            components: {
                App
            }
        })
    </script>
</body>

子传父

  1. 在父组件中的子组件标签上绑定自定义事件
  2. 在子组件中触发原生的事件,在事件函数中通过this.$emit()触发自定义事件
<body>
    <div id="app">
        <App></App>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        Vue.component('Child', {
            template: `
            <div>
                <input type='text' @input='handleInput'/>
            </div>
            `,
            methods: {
                handleInput(e) {
                    const v = e.target.value;
                    //this.$emit()触发事件
                    this.$emit('inputHandle', v)
                }
            },
        })

        const App = {
            data() {
                return {
                    newVal: ''
                }
            },
            template: `
            <div>
                <div>子组件传入的数据:{{ newVal }}</div>
                <Child @inputHandle='input'></Child>
            </div>
            `,
            methods: {
                input(v) {
                    this.newVal = v;
                }
            },
        }

        new Vue({
            el: '#app',
            components: {
                App
            }
        })
    </script>
</body>

平行组件通信(兄弟组件通信)

通过new Vue()创建一个中央事件总线,在A组件的生命周期函数created()中通过中央事件总线$on绑定事件函数。在B组件中的事件函数中通过中央事件总线$emit触发绑定的事件函数。

<body>
    <div id="app">
        <App></App>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        const bus = new Vue();

        Vue.component('A', {
            data() {
                return {
                    count: 0
                }
            },
            template: `
            <div>
                {{ count }}
            </div>
            `,
            created() {
                bus.$on('add', (n) => {
                    this.count += n;
                })
            },
        })

        Vue.component('B', {
            template: `
            <div>
                <button @click='handleClick'>加入购物车</button>
            </div>
            `,
            methods: {
                handleClick() {
                    bus.$emit('add', 1);
                }
            },
        })

        const App = {
            data() {
                return {

                }
            },
            template: `
            <div>
                <A></A>
                <B></B>
            </div>
            `,
        }

        new Vue({
            el: '#app',
            components: {
                App
            }
        })
    </script>
</body>

组件通信的其他方式(provide和inject)

在App组件的provide中声明要传递的数据,provide是一个函数,返回一个对象,在App组件的孙子组件B中通过inject来接收想要的数据。同时还有this.$parentthis.$children等可获取父组件、子组件。

<body>
    <div id="app">
        <App></App>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        Vue.component('A', {
            template: `
            <div>
                <B></B>
            </div>
            `,
            created() {
                //获取父组件
                console.log(this.$parent.title);
                //获取子组件(此时B还没有创建所以取0索引时拿不到)
                console.log(this.$children);
            },
        })

        Vue.component('B', {
            template: `
            <div>
                {{ msg }}
            </div>
            `,
            inject: ['msg'],
            created() {
                //方法中使用加this
                console.log(this.msg);
            }
        })

        const App = {
            data() {
                return {
                    title: 'App'
                }
            },
            provide() {
                return {
                    msg: '我是你爷爷'
                }
            },
            template: `
            <div>
                <A></A>
            </div>
            `,
        }

        new Vue({
            el: '#app',
            components: {
                App
            }
        })
    </script>
</body>