Vue学习记录04-组件

参考Vue实战、官网

一、组件基础

1、组件概念

实现代码最高的复用性。引入了组件的概念。

2、基本使用

与指令、过滤器类似,需要注册后使用。同样注册有全局注册和局部注册两种。全局注册后任何Vue示例都可以使用。示例如下:

<body>
    <script src="./vue.js"></script>

    <!-- 使用组件 -->
    <div id="app">
        <my-component></my-component>
    </div>

    <script>
        // 注册一个全局组件,第一个参数是标签名
        Vue.component("my-component",{
            template:`<div>全局组件</div>`
        });

        // 创建实例
        var app = new Vue({
            el:"#app",
        });

        //说明:
        //    template 必须是DOM结构
    </script>
</body>
3、HTML限制

Vue组件模板可能会受到HTML限制,如

标签只允许
等表格标签。这时直接使用组件是无效的。

这是可以使用is属性来挂载组件。示例如下:

<table>
  <tbody is="my-component"></tbody>
</table>

tbody 在渲染时,会被替换为组件的内容。常见的限制元素还有

    1. 、。

4、数据选项
  • data必须被定义为一个函数。
  • data函数的返回值为一个对象

示例:

<body>
    <script src="./vue.js"></script>

    <!-- 使用组件 -->
    <div id="app">
        <my-component></my-component>
        <my-component></my-component>
        <my-component></my-component>
    </div>

    <script>
        // 注册一个全局组件,第一个参数是标签名
        Vue.component("my-component",{
            template:`<button @click="counter++">{{counter}}</button>`,
            data: function(){
                return {counter:0};
            }
        });

        // 创建实例
        var app = new Vue({
            el:"#app",
        });

        //说明:
        //    data必须被定义为一个函数。
        //    data函数的返回值为一个对象
    </script>
</body>

二、props传递数据

1、基本使用

1)基本示例

父组件子组件 正向传递数据的过程通过props来实现。props的取值可以是字符串数组或者对象。

示例如下:

<body>
    <script src="./vue.js"></script>

    <div id="app">
        <my-component message="来自父组件的数据"></my-component>
    </div>

    <script>
        Vue.component("my-component",{
            template:`<div>{{message}}</div>`,
            props:['message'],
        });

        var app = new Vue({
            el:"#app",
        });
    </script>
</body>

渲染结果为:

<div id="app"><div>来自父组件的数据</div></div>

2)注意事项

由于HTML特性不区分大小写,当使用DOM模板时,驼峰命名的props名称要转为短横杠命名。

props:["warningText"]
<my-component warning-text="提示信息"></my-component>

如果使用的是字符串模板可以忽略这些限制。

3)动态props

来自父组件的动态数据可以使用指令v-bind来动态绑定props的值。

示例:使用v-model绑定数据。父组件的数据子组件实时响应并更新模板。

<body>
    <script src="./vue.js"></script>

    <div id="app">
        <input type="text" v-model="parentMessage">
        <my-component :message="parentMessage"></my-component>
    </div>

    <script>
        Vue.component("my-component",{
            template:`<div>{{message}}</div>`,
            props:['message'],
        });

        var app = new Vue({
            el:"#app",
            data:{
                parentMessage:"",
            }
        });
    </script>
</body>
2、单向数据流

略。

3、数据验证

对props传入的类型进行检查。

三、子组件与父组件通信

组件通信

  • 子组件向父组件通过自定义事件通信。
  • 子组件使用$emit()来触发事件,父组件用$on()来监听子组件的事件。
  • 父组件也可以直接在子组件的自定义标签上使用v-on来监听子组件触发的自定义事件。
1、v-on监听子组件

如果子组件$emit()触发的是一个自定义事件,那么父组件只能使用v-on监听。

示例:

<body>
    <script src="./vue.js"></script>

    <div id="app">
        <p>总数:{{ total }}</p>
        <my-component @increase="handleGetTotal" @reduce="handleGetTotal">
        </my-component>
    </div>

    <script>
        Vue.component("my-component", {
            template: `
               <div>
                    <button @click="handleIncrease">+1</button>
                    <button @click="handleReduce">-1</button>
               </div>
            `,
            data: function () {
                return {
                    counter: 0,
                }
            },
            methods: {
                handleIncrease: function () {
                    this.counter++;
                    this.$emit('increase', this.counter);
                },
                handleReduce: function () {
                    this.counter--;
                    this.$emit('reduce', this.counter);
                }
            }
        });

        var app = new Vue({
            el: "#app",
            data: {
                total: 0,
            },
            methods: {
                handleGetTotal: function (total) {
                    this.total = total;
                }
            }
        });
    </script>
</body>

渲染结果:

<div id="app"><p>总数:-3</p> <div><button>+1</button> <button>-1</button></div></div>
2、v-model监听子组件

如果子组件$emit()触发的是一个特殊的事件名input,那么父组件就可以使用v-model监听。

示例:

<body>
    <script src="./vue.js"></script>

    <div id="app">
        <p>总数:{{ total }}</p>
        <my-component v-model="total">
        </my-component>
    </div>

    <script>
        Vue.component("my-component", {
            template: `
            <div>
                    <button @click="handleIncrease">+1</button>
                    <button @click="handleReduce">-1</button>
               </div>
            `,
            data: function () {
                return {
                    counter: 0,
                }
            },
            methods: {
                handleIncrease: function () {
                    this.counter++;
                    this.$emit('input', this.counter);
                },
                handleReduce: function () {
                    this.counter--;
                    this.$emit('input', this.counter);
                }
            }
        });

        var app = new Vue({
            el: "#app",
            data: {
                total: 0,
            },
            methods: {
                handleGetTotal: function (total) {
                    this.total = total;
                }
            }
        });
    </script>
</body>

四、非父子组件通信

1、利用中央事件总线bus

起两个组件中介的作用。

示例:

<body>
    <script src="./vue.js"></script>

    <div id="app">
        {{ message }}
        <component-a></component-a>
    </div>

    <script>
        var bus = new Vue();

        Vue.component("component-a", {
            template: `<button @click="handleEvent">传递事件</button>`,

            methods: {
                handleEvent: function () {
                   bus.$emit('on-message', '来自组件component-a的内容');
                },
            }
        });

        var app = new Vue({
            el: "#app",
            data: {
                message: '',
            },
            mounted () {
                var _this = this;
                bus.$on('on-message',function(msg){
                    _this.message = msg;
                });
            }
        });
    </script>
</body>
2、父链
3、子组件索引

五、插槽slot

1、作用域

1)showChild 绑定的是父组件的数据 。

<body>
    <script src="./vue.js"></script>
    <div id="app">
        <child-component v-show="showChild"></child-component>
    </div>

    <script>
        Vue.component('child-component',{
            template:`<div>子组件</div>`
        });

        var app = new Vue({
            el:'#app',
            data:{
                showChild:true
            }
        });
    </script>
</body>

2)showChild 绑定的是子组件的数据

<body>
    <script src="./vue.js"></script>
    <div id="app">
        <child-component></child-component>
    </div>

    <script>
        Vue.component('child-component',{
            template:`<div v-show="showChild">子组件</div>`
        });

        var app = new Vue({
            el:'#app',
            data:{
                showChild:true
            }
        });
    </script>
</body>
2、slot用法

1)单个Slot

在子组件内使用特殊的元素就可以为这个子组件开启一个slot(插槽),在父组件模板里,插入在子组件标签内的所有内容将替换子组件的标签即它的内容。

示例:

<body>
    <script src="./vue.js"></script>
    <div id="app">
        <child-component>
            <p>分发的内容</p>
            <p>更多分发的内容</p>
        </child-component>
    </div>

    <script>
        Vue.component('child-component', {
            template: ` 
            <div>
                <slot>
                    <p>如果父组件没有插入内容,我将作为默认出现</p>
                </slot>
            </div>`,
        });

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

2)具名slot

给元素指定一个name后,可以分发多个内容,具名slot可以与单个slot共存。

示例:

<body>
    <script src="./vue.js"></script>
    <div id="app">
        <child-component>
            <h2 slot="header">标题</h2>
            <p>分发的内容</p>
            <p>更多分发的内容</p>
            <div slot="footer">底部信息</div>
        </child-component>
    </div>

    <script>
        Vue.component('child-component', {
            template: ` 
                <div class="container">
                    <div class="header">
                        <slot name="header"></slot>
                    </div>

                    <div class="main">
                        <slot></slot>
                    </div>

                    <div class="footer">
                        <slot name="footer"></slot>
                    </div>
                </div>`,
        });

        var app = new Vue({
            el: '#app',
        });
    </script>
</body>
3、作用域插槽

作用域插槽是一种特殊的slot,使用一个可以复用的模板替换已渲染元素。示例:

<body>
    <script src="./vue.js"></script>
    <div id="app">
        <child-component>
            <template scope="props">
                <p>来自父组件的内容</p>
                <p>{{ props.msg }}</p>
            </template>
        </child-component>
    </div>

    <script>
        Vue.component('child-component', {
            template: ` 
                <div class="container">
                    <slot msg="来自子组件的内容"></slot>
                </div>`,
        });

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

作用域插槽更具代表性的用例是列表组件,允许组件自定义应该如何渲染列表的每一项。

4、访问slot

略。

六、组件高级用法

1、递归组件
2、内联模板
3、动态组件
4、异步组件

最新的笔记更新在:
https://github.com/1097364388/learning

<全文结束>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值