我们从一个例子来学习组件,
这个例子用到其他组件,对于初学者来说,一下子要了解那么多组件的使用,会变得一头雾水。所以我把这个例子改写了一下,只需要依赖 vue.
然后最好 FQ 安装一个 chrome 的扩展 vue-devtools,这样可以更好看到组件的内容
组件(Component)是 vue.js 最强大的功能之一。组件可以扩展 html 元素,封装可重用的代码。
在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。
父子组件的关系可以总结为 props down, events up 。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。
SLOT 的理解: 子组件有名字的 slot, 将会给父组件同名的 slot 替换掉, 子组件匿名的 slot, 将会给父组件的其他没 slot 名字的内容替换掉.
- 'tab1'>
- "../assets/images/ic_tab_home_normal.png" alt="" slot="icon-normal">
- "../assets/images/ic_tab_home_active.png" alt="" slot="icon-active">
- 首页
子组件模板:
- class="m-tabbar-item" :class="{'is-active':isActive}" @click="$parent.$emit('input',id)">
- class="m-tabbar-item-icon" v-show="!isActive">"icon-normal">
- class="m-tabbar-item-icon" v-show="isActive">"icon-active">
- class="m-tabbar-item-text">
最终生成的 HTML:
- <a class="m-tabbar-item">
- <span class="m-tabbar-item-icon">
- <img src="../assets/images/ic_tab_home_normal.png" alt="">
- </span>
- <span class="m-tabbar-item-icon" style="display: none;">
- <img src="../assets/images/ic_tab_home_active.png" alt="">
- </span>
- <span class="m-tabbar-item-text">
- 首页
- </span>
- </a>
- <img src="../assets/images/ic_tab_home_normal.png" alt="" slot="icon-normal">
- 会替换掉
- <slot name="icon-normal">
- </slot>
- <img src="../assets/images/ic_tab_home_active.png" alt="" slot="icon-active"
- />
- 会替换掉
- <slot name="icon-active">
- </slot>
- ,并把slot的名字去掉
- 首页 会替换掉 这个匿名的.
- 整个页面的代码如下:
- .m-tabbar
- {
- display: flex;
- flex-direction: row;
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0;
- width: 100%;
- overflow: hidden;
- height: 50px;
- background: #fff;
- border-top: 1px solid #e4e4e4;
- }
- .m-tabbar-item
- {
- flex: 1;
- text-align: center;
- }
- .m-tabbar-item-icon
- {
- display: block;
- padding-top: 2px;
- }
- .m-tabbar-item-icon img
- {
- width: 28px;
- height: 28px;
- }
- .m-tabbar-item-text
- {
- display: block;
- font-size: 10px;
- color: #949494;
- }
- .is-active
- {
- color: #42bd56;
- }
- 首页
- 书影音
- 广播
- 小组
- 我的
- Vue.component("m-tabbar", {
- props: ['value'],
- template:''
- });
- Vue.component("m-tabbar-item", {
- props: ['id'],
- computed: {
- isActive(){
- if(this.$parent.value===this.id){
- return true;
- }
- else
- return false;
- }
- },
- template:''
- });
- var app = new Vue({
- el: '#app',
- data: {
- select:"tab1"
- }
- });
- m-tabbar组件的双向绑定 v-model="select" 说明m-tabbar暴露出的属性value是和data里的select字段关联的,页面默认选中的是第一个tab,它的Id是tab1.
- m-tabbar-item组件里有一个判断 this.$parent.value===this.id,父组件的value等于子组件的Id,则该子组件为选中的。
- @click="$parent.$emit(\'input\',id)" 这个方法, 请参考这里
- <m-tabbar v-model="select">
- 等价于
- <m-tabbar v-bind:value="select" v-on:input="select=arguments[0]">
- 所以要让组件的 v-model 生效,它必须:
- 接受一个 value 属性
- 在有新的 value 时触发 input 事件
所以 @click="$parent.$emit(\'input\',id)" 这个方法就是在子组件 click 的事件,触发父组件的 input 事件把子组件的 Id 传个父组件的 value 属性
- 问题来了:为什么父组件有个input事件呢? 它只是个div而已,我可以把这个事件名字改成其他的吗?
- 改成下面的代码,把事件名改成abcdef,是可以通过的
- abcdef="tabSelect">
- Vue.component("m-tabbar", {
- props: ['value'],
- template:'',
- mounted: function () {
- console.log("m-tabbar mounted");
- }
- });
- Vue.component("m-tabbar-item", {
- props: ['id'],
- mounted: function () {
- console.log("m-tabbar-item mounted");
- },
- computed: {
- isActive(){
- if(this.$parent.value===this.id){
- return true;
- }
- else
- return false;
- }
- },
- template:'abcdef\',id)">'
- +''
- +''
- + ''
- +''
- });
- var app = new Vue({
- el: '#app',
- data: {
- selectId:"tab1"
- },
- methods:{
- tabSelect:function(Id){
- console.log("tabSelect");
- this.selectId= Id;
- }
- }
- });
是任意名字都可以吗? 不是的,我试过有 2 个是不行的。 当事件名里有包含 Select 或者 Index 这 2 个词时,父组件就监听不到这个事件了。 难道这 2 个是什么保留字, 有人知道吗?
来源: http://www.cnblogs.com/zitjubiz/p/6520584.html