在平时工作中,免不了需要我们根据业务需求去封装相应的组件,那这篇我们就来封装一个 YuSidebar 组件,关键是 install 方法
记重点:
- 如果需要写一个vue的插件
- 就向外输出一个对象
- 这个对象必须要有一个方法,方法名为install
- 外面调用插件,Vue.use(插件模块)
- 内部install方法就会执行
以下就是我封装的 YuSidebar 的说明文档以及代码实现:
说明文档 readme
引入
import Vue from 'vue'
import {YuSidebar, YuSidebarItem} from './plugin'
Vue.use(YuSidebar).use(YuSidebarItem);
代码演示
基础用法
<yu-sidebar v-model="activeKey">
<yu-sidebar-item title="标签 1"></yu-sidebar-item>
<yu-sidebar-item title="标签 2"></yu-sidebar-item>
<yu-sidebar-item title="标签 3"></yu-sidebar-item>
<yu-sidebar-item title="标签 4"></yu-sidebar-item>
</yu-sidebar>
export default {
data(){
return {
activeKey: 2
}
}
}
提示信息
<yu-sidebar v-model="activeKey">
<yu-sidebar-item title="标签 1"></yu-sidebar-item>
<yu-sidebar-item title="标签 2" info="5"></yu-sidebar-item>
<yu-sidebar-item title="标签 3" dot></yu-sidebar-item>
<yu-sidebar-item title="标签 4" info="99+"></yu-sidebar-item>
</yu-sidebar>
禁用选项
<yu-sidebar v-model="activeKey">
<yu-sidebar-item title="标签 1" disabled></yu-sidebar-item>
<yu-sidebar-item title="标签 2"></yu-sidebar-item>
<yu-sidebar-item title="标签 3"></yu-sidebar-item>
<yu-sidebar-item title="标签 4"></yu-sidebar-item>
</yu-sidebar>
切换导航项添加自定义事件,得到索引
<yu-sidebar v-model="activeKey" @change="changeAction">
<yu-sidebar-item title="标签 1"></yu-sidebar-item>
<yu-sidebar-item title="标签 2" @click="clickAction"></yu-sidebar-item>
<yu-sidebar-item title="标签 3"></yu-sidebar-item>
<yu-sidebar-item title="标签 4"></yu-sidebar-item>
</yu-sidebar>
export default {
data(){
return {
activeKey: 2
}
},
methods: {
// 点击返回当前点击的 index
changeAction(index) {
console.log('sideBar当前点击的是' + index);
},
// 当前点击的 索引
clickAction(index) {
console.log('sidebarItem 中点击的' + index);
}
}
}
url跳转 / 路由跳转
<yu-sidebar v-model="activeKey" @change="changeAction">
<yu-sidebar-item title="标签 1"></yu-sidebar-item>
<yu-sidebar-item title="标签 2" info="5" @click="clickAction" :to="{ path: 'home' }"></yu-sidebar-item>
<yu-sidebar-item title="标签 3" dot url="http://www.baidu.com"></yu-sidebar-item>
<yu-sidebar-item title="标签 4" info="99+" to="'home'" replace></yu-sidebar-item>
</yu-sidebar>
API
Sidebar Props
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
v-model | 当前导航项的索引 | string / number(类型) | 0 |
Sidebar Events
事件名 | 说明 | 回调参数 |
---|---|---|
change | 切换导航项时触发 | index当前导航项的索引(回调参数) |
SidebarItem Props
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
title | 内容 | string | ‘’ |
dot | 是否显示右上角小红点 | boolean | false |
info | 右上角徽标的内容 | string / number | - |
disabled | 是否禁用该项 | boolean | false |
url | 点击后跳转的链接地址 | string | - |
to | 点击后跳转的目标路由对象 | string / object | - |
replace | 是否在跳转时替换当前页面历史 | boolean | false |
SidebarItem Events
事件名 | 说明 | 回调参数 |
---|---|---|
click | 点击时触发 | index 当前导航项的索引 |
以上就是使用方法,那我们在 App.vue 中使用一下
<template>
<div id="app">
<yu-sidebar v-model="activeKey" @change="changeAction">
<yu-sidebar-item title="标签 1" disabled></yu-sidebar-item>
<yu-sidebar-item title="标签 2" info="5" @click="clickAction" :to="{ path: 'home' }"></yu-sidebar-item>
<yu-sidebar-item title="标签 3" dot url="http://www.baidu.com"></yu-sidebar-item>
<yu-sidebar-item title="标签 4" info="99+" to="'home'" replace></yu-sidebar-item>
</yu-sidebar>
</div>
</template>
<script>
import Vue from 'vue'
import {YuSidebar, YuSidebarItem} from './plugin'
Vue.use(YuSidebar).use(YuSidebarItem);
export default {
data(){
return {
activeKey: 2
}
},
methods: {
// 点击返回当前点击的 index
changeAction(index) {
console.log('sideBar当前点击的是' + index);
},
// 当前点击的 索引
clickAction(index) {
console.log('sidebarItem 中点击的' + index);
}
}
}
</script>
<style>
html, body {
width: 100%;
height: 100%;
}
#app {
width: 100%;
height: 30%;
}
</style>
出来以下图示效果:
封装组件代码实现:
YuSidebar.vue
<template>
<nav class="yuSidebar">
<slot />
</nav>
</template>
<script>
export default {
name: 'yu-sidebar',
props: {
value: {
type: Number,
default: 0
},
},
data() {
return {
}
},
methods: {
// 根据下标来选中
selectByIndexAction(flag) {
// 触发外部的 input 事件 双向绑定
this.$emit('input', flag);
// 除外外部的 change 事件,传入索引
this.$emit('change', flag);
// 循环遍历子节点,改变当前 flag active
this.$children.forEach((child, index) => {
if(index === flag) { //选中
child.isActive = true;
}else { // 不选中
child.isActive = false;
}
});
}
},
mounted() {
// 开始默认的选中下标
this.$children[this.value].isActive = true;
// 给每个 SidebarItem 添加下标 --- 索引
this.$children.forEach((child, index) => {
child.index = index;
});
}
}
</script>
<style scoped>
.yuSidebar {
width: 85px;
margin-left: 16px;
display: flex;
flex-direction: column;
}
</style>
YuSidebarItem.vue
<template>
<a :href="url" class="yuSidebarItem" @click="!disabled && selectAction()"
:class="{active: isActive, disabled: disabled}">
<span>
{{title}}
<em class="yu-info yu-info-dot" v-if="dot" ></em>
<em class="yu-info" v-if="info">{{info}}</em>
</span>
</a>
</template>
<script>
export default {
name: 'yu-sidebar-item',
props: {
title: String, // 标签名
disabled: {
type: Boolean,
default: false
},
dot: {
type: Boolean,
default: false
},
info: {
type: [Number, String],
default: '',
},
url: {
type: String,
default: 'javascript:;'
},
to: {
type: [String, Object],
default: ''
},
replace: {
type: Boolean,
default: false
}
},
data() {
return {
isActive: false, // 是否选中
}
},
methods: {
// 点击的时候选中
selectAction() {
this.$parent.selectByIndexAction(this.index);
this.$emit('click', this.index);
// 根据传进来的路由跳转
if(to != '') {
if(replace) {
// 使用 replace 而不是使用 push
this.$router.replace(this.to);
}else {
this.$router.push(this.to);
}
}
}
}
}
</script>
<style scoped>
.yuSidebarItem {
text-decoration: none;
display: block;
flex: 1;
color: #555;
list-style: none;
background-color: #fafafa;
padding: 20px 12px 20px 8px;
box-sizing: border-box;
border-left: 3px solid transparent;
overflow: hidden;
font-size: 14px;
line-height: 20px;
word-wrap: break-word;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
.yuSidebarItem span {
position: relative;
display: inline-block;
font-size: 14px;
line-height: 20px;
/* padding: 4px; */
}
/* 选中的样式 */
.yuSidebarItem.active {
border-color: #ee0a24;
color: #323233;
font-weight: 500;
background-color: #fff;
}
/* 不能点击的样式 */
.yuSidebarItem.disabled {
color: #c8c9cc;
}
/* 小红点的样式 */
.yu-info {
position: absolute;
top: 0;
right: 0;
-webkit-transform: translate(50%, -50%);
transform: translate(50%, -50%);
box-sizing: border-box;
min-width: 16px;
padding: 0 3px;
color: #fff;
font-weight: 500;
font-size: 12px;
font-family: PingFang SC, Helvetica Neue, Arial, sans-serif;
line-height: 14px;
text-align: center;
border: 1px solid #fff;
-webkit-transform-origin: 100%;
transform-origin: 100%;
background-color: #ee0a24;
border-radius: 16px;
}
.yu-info-dot {
width: 8px;
min-width: 0;
height: 8px;
background-color: #ee0a24;
border-radius: 100%;
}
</style>
封装插件 index.js
// 如果需要写一个vue的插件。
// 就向外输出一个对象
// 这个对象必须要有一个方法,方法名为install
// 外面调用插件,Vue.use(插件模块)
// 内部install方法就会执行
import yuSidebar from './YuSidebar.vue'
import yuSidebarItem from './YuSidebarItem.vue'
export default {
install(Vue){
Vue.component(yuSidebar.name, yuSidebar);
Vue.component(yuSidebarItem.name, yuSidebarItem);
}
}
export const YuSidebar = {
install(Vue){
Vue.component(yuSidebar.name, yuSidebar);
}
};
export const YuSidebarItem = {
install(Vue){
Vue.component(yuSidebarItem.name, yuSidebarItem);
}
};
好啦,一个自定义的 sidebar 组件就封装好啦,下次再见 ~