一、思路
思路.pngeventBus.png
- 点击items改变选中的item(运用.sync修饰符,就是子组件里prop的值改变时,父组件的值也同步变化),子组件触发事件的代码一定要写上!!!相当于只是监听的形式改变了一下;(在点击item的时候tabs上的selected属性是不需要改变的)
<d-tabs :selected="selectedItem" @update:selected="selectedItem = $event">
//上一句等同于<d-tabs :selected.sync="selectedItem">
<d-tabs-head>
<d-tabs-item name="entertainment">娱乐</d-tabs-item>
<d-tabs-item name="society">社会</d-tabs-item>
<d-tabs-item name="sports">体育</d-tabs-item>
</d-tabs-head>
<d-tabs-body>
<d-tabs-pane name="entertainment">这里是娱乐</d-tabs-pane>
<d-tabs-pane name="society">这里是社会</d-tabs-pane>
<d-tabs-pane name="sports">这里是体育</d-tabs-pane>
</d-tabs-body>
</d-tabs>
-
子组件绝对不要去改父组件里的值,如果需要进行改动,扔一个事件,让父组件监听;
-
子组件自己不要去修改props里的值,它传什么进来你就只管用;你有见过一个函数参数传进来,还去改参数的吗!!(不过你可以自己声明一个变量,把props的值赋值给这个变量,然后你就可以随意改动这个变量的值了);
2、tabs-head中的<slot name="actions"></slot>,相当于tabs-head中有两个插槽;
//html中这样用
<template slot="actions">
<button>设置</button>
</template>
- vue中只有两个属性是默认合并的,class和style,其他属性都是直接覆盖;例如:你的组件本身有一个class,你在使用这个组件的时候,又添加了一个class,那么这两个class会合并;
-
下划线开头的属性不要乱用,那是私有属性,vue作者用的;你用$开头的就好;
image.png
二、通过eventBus统一管理事件
1、 tabs-items和tabs-pane上需要加个active来控制它是否被选中,那么这个active是放在data里还是props里呢?你要根据active的特性来判断了;
- data和props的区别:data不需要开发者传值,它相当于是个局部变量;props需要开发者传值进来,相当于是个参数;
- 在爷爷组件上加入
provide:{ eventBus }
,那么eventBus这个属性它的儿子孙子组件都可以直接访问,只需要在儿子孙子组件上把eventBus注入一下inject:['eventBus']
; - vue中的事件时不会冒泡的,这是跟dom事件的不同;
- vue事件要看清楚是在哪个对象上触发的; 你在哪个对象上触发就只能在哪个对象上监听;你在子组件上触发的事件是不会传到父组件那里的!!!(注意:事件不会传过去,但是父组件可以获取子组件的数据啊!是数据!!)
- 为什么
new Vue()
可以用来当一个事件中心,因为它身上有$on、$emit、$off
三个事件接口啊,所以完全可以拿来当一个事件中心来用; - <slot></slot>上不能加class,但我们可以在它外面包裹一层div;
- 给flex的子元素加
margin-left: auto
,这个子元素就会向右靠;
三、给tabs加上滑动的下border
1、在tabs-head里加个div,单独当做下划线,给它定个位;
2、我们要获取到一开始selected的那个元素实例,并把它传出来(在tabs里找);
3、还要获取到点击的那个item的元素实例,同样把它传出来(在tabs-item里找);
4、在tabs-head里监听"update:selected"事件,获得传出来的item名字和实例,并获取到实例元素的左边距和宽度,把它们赋值给下划线div;最后加个过渡事件就大功告成;
四、单元测试
1、当<d-tabs>下的子元素不是<d-head>时,应该给个警告;
-
this.$children
只能获取到子组件,不能获取到子元素;下面这个<g-tabs>的$children
是不存在的;
<d-tabs>
<div>hi</div>
</d-tabs>
网友评论