话不多说,我们现在就开始实现这两个组件,首先你得搭好一个架子,架子具体实现请参考github,这个是我组件库开发的地址,通过修改vue-cli脚手架,将开发与展示放在一块,利于我前期的一个开发,examples下是展示实例,packages是包所在的文件目录,如果你感觉通过修改vue-cli脚手架太麻烦的话,也可以通过链接引入vue,然后对这两个组件进行注册,当然这也是可以的。
我们先来实现单选框组件
originOptions
和selected
这两个数据,我们通过方法queryData
来添加我们想要的数据,冰鞋我们需要设定一个回掉函数singleCallback,来处理我们子组件返回的值,大概是父组件中需要这样写代码,并且我们父组件的html部分需要这样写。<script>
export default{
data(){
return {
single:{
originOptions: [],
selected: {}
}
}
},
mounted :function() {
this.queryData();
},
methods: {
queryData: function(){
var mySelf = this
//do ajax here
// 单选
mySelf.single.originOptions = [{"id":"1","name":"lemon"},{"id":"2","name":"mike"},{"id":"3","name":"lara"},{"id":"4","name":"zoe"},{"id":"5","name":"steve"},{"id":"6","name":"nolan"}];
mySelf.single.selected = {"id":"4","name":"zoe"}
this.$nextTick(function(){
//dom更新之后,执行一些其他操所。
})
},
singleCallback: function(data){
this.single.selected = data;
console.log('父级元素调用singleCallback 选中的是' + JSON.stringify(data))
}
}
}
script>
//部分,请自行放在合适位置
<w-single-input v-bind:optionsdata="single.originOptions" v-bind:selecteddata="single.selected" @selected="singleCallback" >w-single-input>
props: ['optionsdata','selecteddata'],
来获取父元素传给子组件的值,并且我们还需要通过watch来监听数据的变化watch: {
//监听选项值和选中值得变化
optionsdata: function (val, oldVal) {
this.originOptions = val;
this.show = false;
// 默认值
if (this.selected.id == ''){
this.selected = this.originOptions[0];
}
},
selecteddata: function(val, oldVal){
this.selected = val
}
},
我们根据需要在data函数里面添加我们需要的数值.具体功能已经标明。
data: function() {
return{
originOptions: [],//从父组件接受回来的数据
displayOptions: [],//需要展现的列表(查询的时候列表会变化)
show: false,
search: '',//查询input框中的数据
selected: { //选中的选项
id: "",
name: ""
}
}
},
<div class="functional-select-wrapper" @click.stop="singleFocus()">
<label class="display-container clearfix" :class="(show)?'single-selected-focus':''">
<p v-show="selected.id == ''">
<span v-if="originOptions.length != 0">请选择span>
<span v-else>没有选项span>
p>
<p class="single-selected">{{ selected.name }}p>
<i class="drop" :class="(show)?'drop-up':''">▼i>
label>
<div class="options-container" v-show="show">
<div class="search-container">
<input placeholder="search here" class="search-input" v-model="search" @keyup="singleSearch" @click.stop />
div>
<ul class="options-ul-list">
<li v-show="displayOptions.length == 0">没有查询到数据li>
<li v-for="item in displayOptions" @click.stop.prevent="singleSelect(item.id)" :class="(item.id == selected.id)?'selected':''">{{ item.name }}li>
ul>
div>
div>
singleFocus()
函数实现单选框数据下拉展示,并且获得焦点,我们通过此函数调用函数searchInputFocus()
来设定搜索框的焦点,这里面使用了this.$nextTick回掉函数,下一次数据更新之后重新获取焦点,singleSelect()
函数则是根据我当前的id,从displayOptions
数组中寻找对应的选项,并且赋值给selected
,最后一个就是搜多功能函数了singleSearch
我们通过用户输入的值来作正则匹配 displayOptions
数组中的值,我们值发生变化后,列表会自动更新搜索的内容。整个script标签中的的代码如下。 export default {
name:'w-single-input',
props: ['optionsdata','selecteddata'],
data: function() {
return{
originOptions: [],
displayOptions: [],
show: false,
search: '',
selected: {
id: "",
name: ""
}
}
},
mounted: function(){
//设置点击其他区域关闭选项
window.addEventListener('click',this.blur);
},
watch: {
//监听选项值和选中值得变化
optionsdata: function (val, oldVal) {
this.originOptions = val;
this.show = false;
// 默认值
if (this.selected.id == ''){
this.selected = this.originOptions[0];
}
},
selecteddata: function(val, oldVal){
this.selected = val
}
},
methods:{
singleFocus: function(){
if (!this.show){
document.body.click();
console.log('single show');
this.show = true;
this.singleSearch();
this.searchInputFocus();
}
else{
this.blur();
}
},
searchInputFocus: function(){
let searchInput = this.$el.getElementsByClassName('search-input')[0];
this.$nextTick(function(){
//下一次dom更新之后使得searchInput获得焦点
searchInput.focus();
})
},
singleSelect: function(id){
let mySelf = this;
let displayOptions = mySelf.displayOptions;
for (let i=0; ilet item = displayOptions[i];
//在展示数组里找 找到后1.添加到selected
if (item.id == id){
let selected = mySelf.selected;
selected.id = item.id;
selected.name = item.name
}
}
//关闭下拉框,清除search输入的值。
mySelf.show = false;
this.search = '';
//传递给父级组件
this.$emit('selected',this.selected);
//console.log('选中的是' + JSON.stringify(this.selected));
},
singleSearch: function(){
let mySelf = this;
let search = mySelf.search;
//根据用户输入值做正则
let REG_RULE = new RegExp(search,"i");
let originOptions = mySelf.originOptions;
//将展示列表置空 然后用正则去原始列表中匹配
mySelf.displayOptions = [];
for (let i=0;ilet item = originOptions[i];
if (REG_RULE.test(item.name)){
mySelf.displayOptions.push(item)
}
}
},
blur: function(){
this.show = false;
this.search = '';
}
}
}
</script>
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
optionsdata | 可选值列表 | Array | 自定义 | null |
selected | 指定当前选中的值 | Json | 可选列表中出现的值 | null |
selected
转变为selectedList
数组,并且我们需要在子组件中,需要设定选项的移除功能,其余的功能和单选框差不多,我们在这里给出关键代码,并进行解释。checkboxRemove:function(name){
console.log(name);
let myself = this;
let optionName = name;
let selectedList = myself.selectedList;
for(let i=0;ilet item = selectedList[i];
if(item.id == optionName){
let index = selectedList.indexOf(item);
selectedList.splice(index,1);//删除index对应的选项
myself.checkboxInitSearch();//初始化搜索框
myself.checkboxSearch();//调用搜索框
myself.searchInputFocus();//获取焦点
myself.dispatchData();//通过$emit来触发当前实例上的selected,并且将选中数据当作参数返回给父组件。
}
}
},
<p class="multiple-selected-item" v-for="item in selectedList" track-by="$index">
{{ item.name }}
<i @click.stop.prevent="checkboxRemove(item.id)">×i>
p>
整个变化就在一块,整体实现代码请点击这里
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
options-data | 可选值列表 | Array | 自定义 | null |
selected-data | 指定当前选中值得列表 | Array | 可选列表中出现的值 | null |
注意:写代码过程中遇到的问题有这么几个
1. 最后我们通过props:[]去接收参数,一般我采用的都是驼峰命名法,我们在html中写成驼峰命名法会报警告,所以这块我们父组件设定参数的时候通过短线连接符实现,如果你感觉很麻烦,两边都用小写是可以的,但是为了命名过长的话还是建议采用短线连接符来命名,感觉还是编码规范问题,刚一开始就得养成一个好习惯。
2. 通过$emit来触发当前实例上的事件,并传递参数回去。注会主要用在,我们选中值之后我们需要调用各自的回掉函数,我们通过其触发selected事件,并将参数返回给父组件,这样就实现了我们预期的一个效果,子组件选中之后,父组件通过callback显示对应信息,进行后续操作。
npm install wvue-ui
全局注册
import WVUE from 'wvue-ui' // 引入组件库
Vue.use(WVUE)
使用单个组件
import { w-button } from 'wvue-ui'
export default {
components: {
w-button
}
}
在模板中,用
自定义标签的方式使用组件(按钮)
<template>
<div>
<w-button>这是一个按钮w-button>
div>
template>