第7 章 组件详解

第7 章 组件详解(要重读)

7.1 组件与复用
7.1.1 为什么使用组件
Vue.js组件就是提高重用性的。
7.1.2 组件用法
组件需要注册后才可以使用,注册有全局注册和局部注册两种方式。
template的DOM结构必须被一个元素包含。
在使用data时,和实例稍有区别,data必须是函数,然后将数据return出去。

7.2 使用props传递数据
7.2.1 基本用法
传递数字、布尔值、数组、对象,如果不适用v-bind,传递的仅仅是字符串。

7.2.2 单向数据流
通过props传递数据是单向的了。
当使用DOM模板时,驼峰命名的props名称要转为短横分隔命名。
需要修改prop的情况:
一种是父组件传递初始值进来,子组件将它作为初始值保存起来,在组件的作用域下可以随意使用和修改;
另一种情况就是prop作为需要被转变的原始值传入,用计算属性。

7.2.3 数据验证
当prop需要验证时,就需要对象写法。
在浏览器控制台弹出警告,有什么用?

7.3 组件通信
7.3.1 自定义事件
当子组件需要向父组件传递数据时,就要用到自定义事件。子组件用 emit() e m i t ( ) 来 触 发 事 件 , 父 组 件 用 on()来监听子组件的事件。
父组件也可以直接在子组件的自定义标签上使用v-on来监听子组件触发的自定义事件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        {{ total }}
        <my-component @increase="handleGetTotal" @reduce="handleGetTotal"></my-component>
    </div>
    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    <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>
</html>

这里写图片描述

7.3.2 使用v-model
在自定义组件上使用v-model指令。
组件$emit()的事件名是特殊的input,在使用组件的父级,并没有使用@input=”handler”,而是直接用了v-model绑定的一个数据total。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        {{ total }}
        <my-component v-model="total"></my-component>
    </div>

    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    <script>
        Vue.component('my-component',{
            template : '\
            <div>\
                <button @click="handleIncrease">+1</button>\
            </div>',
            data : function () {
                return {
                    counter : 0
                }
            },
            methods : {
                handleIncrease : function () {
                    this.counter++;
                    this.$emit('input',this.counter);
                }
            }
        });
        var app = new Vue({
            el : "#app",
            data : {
                total : 0
            }
        });
    </script>
</body>
</html>

7.3.3 非父子组件通信
1)中央事件总线bus

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        {{ message }}
        <my-component></my-component>
    </div>

    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    <script>
        var bus = new Vue();
        Vue.component('my-component',{
            template : '\
            <button @click="handleEvent">传递事件</button>\
            ',
            methods : {
                handleEvent : function () {
                    bus.$emit("on-message","this message come from my-component");
                }
            }
        });
        var app = new Vue({
            el : "#app",
            data : {
                message : 'init'
            },
            mounted : function () {
                var _this = this;
                bus.$on("on-message",function (msg) {
                    _this.message = msg;
                });
            }
        });
    </script>
</body>
</html>

这种方法实现了任何组件间的通信,可以扩展bus实例,给它添加data、methods、computed等选项,实现信息共享(用户登录信息、授权token等)

2)父链
子组件使用this. parent访使this. p a r e n t 可 以 直 接 访 问 该 组 件 的 父 实 例 或 组 件 , 父 组 件 使 用 t h i s . children访问它所有的子组件,而且可以递归向上或向下无限访问。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        {{ message }}
        <my-component></my-component>
    </div>

    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    <script>
        //var bus = new Vue();
        Vue.component('my-component',{
            template : '\
            <button @click="handleEvent">传递事件</button>\
            ',
            methods : {
                handleEvent : function () {
                    //bus.$emit("on-message","this message come from my-component");
                    this.$parent.message="this message come from my-component through $parent";
                }
            }
        });
        var app = new Vue({
            el : "#app",
            data : {
                message : 'init'
            }
            /*,
            mounted : function () {
                var _this = this;
                bus.$on("on-message",function (msg) {
                    _this.message = msg;
                });
            }*/
        });
    </script>
</body>
</html>

3)子组件索引
在父组件模板中,子组件标签上使用ref指定一个名称,并在父组件内通过this.$refs来访问指定名称的子组件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <button @click="getChildMsg">获得子组件内容</button>
        <component-a ref="comA"></component-a>
    </div>

    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    <script>
        Vue.component('component-a',{
            template : '<div>子组件</div>',
            data : function () {
                return {
                    message : '子组件内容'
                }
            }
        });
        var app = new Vue({
            el : '#app',
            methods : {
                getChildMsg : function () {
                    var message = this.$refs.comA.message;
                    alert(message);
                }
            }
        });
    </script>
</body>
</html>

7.4 使用slot分发内容

7.4.1 什么是slot
当需要让组件组合使用,混合父组件的内容和子组件的模板时,就会用到slot,这个过程叫作内容分发。
props传递参数、events触发事件和slot内容分发就构成了Vue组件的3个API来源。

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

7.4.3 slot用法
1)单个slot
在子组件内使用特殊的元素就可以为这个子组件开启一个slot(插槽),在父组件模板里,插入在子组件标签内的所有内容将替代子组件的标签及它的内容。
2)具名slot

7.4.4 作用域插槽

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app">
        <my-list :books="books">
            <template slot="book" scope="props">
                <li>{{props.bookName}}</li>
            </template>
        </my-list>
    </div>

    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    <script>
        Vue.component('my-list',{
            props : {
                books : {
                    type : Array,
                    default : function () {
                        return [];
                    }
                }
            },
            template : '\
            <ul>\
                <slot name="book"\
                v-for="book in books"\
                :book-name="book.name">\
                </slot>\
            </ul>'
        });

        var app = new Vue({
            el : '#app',
            data : {
                books : [
                    { name : '<<test>>'},
                    { name : '<<test2>>'},
                    { name : '<<test3>>'}
                ]
            }
        });
    </script>
</body>
</html>

7.4.5 访问slot
通过 slots访slotthis. s l o t s 可 以 访 问 某 个 具 名 s l o t , t h i s . slots.default包括了所有没有被包含在具名slot中的节点。

7.5 组件高级用法

7.5.1 递归组件

7.5.2 内联模板

7.5.3 动态组件

7.5.4 异步组件

7.6 其他.

7.6.1 $nextTick

7.6.2 X-Templates

7.6.3 手动挂载实例

7.7 实战
例子1:
这里写图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>数字输入框组件</title>
</head>
<body>
    <div id="app">
        <input-number v-model="value" :max="10" :min="0"></input-number>
    </div>

    <script src="https://unpkg.com/vue/dist/vue.min.js"></script>
    <script src="input-number.js"></script>
    <script src="index.js"></script>


</body>
</html>
var app = new Vue({
    el : '#app',
    data : {
        value : 5
    }
});
function isValueNumber (value) {
    return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/).test(value + '');
}

Vue.component('input-number',{
    template : '\
        <div class="input-number">\
            <input\
                type="text"\
                :value="currentValue"\
                @change="handleChange">\
            <button\
                @click="handleDown"\
                :disabled="currentValue <= min">-</button>\
            <button\
                @click="handleUp"\
                :disabled="currentValue >= max">+</button>\
        </div>',
    props : {
        max : {
            type : Number,
            default : Infinity
        },
        min : {
            type : Number,
            default : -Infinity
        },
        value : {
            type : Number,
            default : 0
        }
    },
    data : function () {
        return {
            currentValue : this.value
        }
    },
    watch : {
        currentValue : function (val) {
            this.$emit('input',val);
            this.$emit('on-change',val);
        },
        value : function (val) {
            this.updateValue(val);
        }
    },
    methods : {
        handleDown : function () {
            if(this.currentValue <= this.min) return;
            this.currentValue -= 1;
        },
        handleUp : function () {
            if(this.currentValue >= this.max) return;
            this.currentValue += 1;
        },
        handleChange : function (event) {
            var val = event.target.value.trim();
            var max = this.max;
            var min = this.min;
            if(isValueNumber(val)) {
                val = Number(val);
                this.currentValue = val;
                if(val > max) {
                    this.currentValue = max;
                } else if( val < min) {
                    this.currentValue = min;
                }
            } else {
                event.target.value = this.currentValue;
            }
        },
        updateValue : function (val) {
            if( val > this.max ) val = this.max;
            if( val < this.min ) val = this.min;
            this.currentValue = val;
        }
    },
    mounted : function () {
        this.updateValue(this.value);
    }
});
;

例子二:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
bindService是Android中一种组件之间进行通信的方式,它可以在两个组件之间建立一种长期的连接,使得它们可以进行交互。下面是bindService的流程详解: 1. 调用bindService方法:在客户端组件中调用bindService方法,该方法接受两个参数,第一个参数是Intent对象,用于指定要绑定的服务组件,第二个参数是ServiceConnection对象,用于指定连接建立和断开时的回调。 2. 系统查找并启动服务组件:系统会查找并启动指定的服务组件,如果服务还没有启动,则将先启动服务。 3. 创建服务组件:系统会创建服务组件,并在其中调用onCreate方法进行初始化。 4. 调用ServiceConnection的onServiceConnected方法:当服务组件创建完成后,系统会调用ServiceConnection的onServiceConnected方法,通知客户端组件连接已建立,并将IBinder对象传递给客户端组件。 5. 获取IBinder对象:客户端组件可以通过ServiceConnection的onServiceConnected方法中传递的IBinder对象与服务组件进行交互。 6. 交互:客户端组件可以通过IBinder对象调用服务组件中的方法,完成交互。 7. 断开连接:当客户端组件不再需要服务组件时,可以调用unbindService方法断开连接,系统会调用ServiceConnection的onServiceDisconnected方法通知客户端组件连接已断开。 8. 销毁服务组件:如果没有任何客户端组件绑定服务组件,系统会调用服务组件的onDestroy方法进行销毁。 总体来说,bindService的流程就是客户端组件通过Intent对象指定要绑定的服务组件,系统查找并启动服务组件,客户端组件通过IBinder对象与服务组件进行交互,当客户端组件不再需要服务组件时,调用unbindService方法断开连接,系统会调用服务组件的onDestroy方法进行销毁。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值