vue 字符串分割_嗯哼vue组件taginput包教不包会
5分鐘實現一個Tag-Input(標簽)組件
前言
本文是wo寫組件設計的第一篇文章(處女作),之所以會寫組件設計相關的文章,是因為作為一名優秀的前端工程師,面對各種繁瑣而重復的工作,我們不應該按部就班的去辛(dao)勤(gen)勞(huo)動(zhong),而是要根據已有前端的開發經驗,總結出一套自己的高效開發的方法。作為數據驅動的領導者vue等MVVM框架的出現,幫我們減少了工作中大量的冗余代碼,一切皆組件的思想深得人心。所以,為了讓工程師們有更多的時間去考慮業務和產品迭代,我們不得不掌握高質量組件設計的思路和方法。所以筆者將花時間去總結各種業務場景下的組件的設計思路和方法,并用原生框架的語法去實現各種常用組件的開發,希望等讓前端新手或者有一定工作經驗的朋友能有所收獲。
正文
在開始組件設計之前希望大家對css3和js有一定的基礎。我們先看看實現后的組件效果:TagInput是一種可編輯的輸入框,通過回車或者空格分割每個標簽,用 vue來實現還是比較簡單的。
先看效果圖,下面會一步一步實現他。由視頻演示可以知道tag-input組件可以自定義顏色主題(color theme), 可以手動關閉標簽。
組件設計思路
我們第一步是要確認需求,一個tag標簽組件一般都會有如下需求點:
需求收集好之后,作為一個有追求的程序員,會得出如下線框圖:
vue有自帶的屬性檢測方式,這里就不介紹了.
開工
?注:以下代碼需要vue-cli環境才能執行
”新建文件夾及相關文件
在src/components/目錄中創建Tag-Input目錄,并且創建Tag-Input.vue文件和index.js文件。如下圖:
布局
搭建基本結構:
<template><div?class="tag-input">
??
??<div?class="tag-item"?v-for="item?in?tags"?:key="item">{{?item?}}div>
??
??<input?class="tag-input"?@keyup.space="generateTag"?v-model="value"?type="text">
div>
template>
書寫基本邏輯:
代碼如下:
export?default?{??name:?'Tag-Input',
??data?()?{
????return?{
??????tags:?[],
??????value:?''
????}
??},
??methods:?{
????generateTag?()?{
????//?判定value是否合法?不能唯空
??????if?(this.value.trim().length?>?0)?{
????????this.tags.push(this.value)
??????}
??????//?還原input的輸入狀態
??????this.value?=?''
????}
??}
}
外觀
我們讓循環出來的tag和input出于同一行內,并且去掉input的border/out-line/和background,讓最外層的div.tag-input被模擬成一個input的感覺。
個人覺得element-ui的tag組件蠻漂亮的,所以借鑒。畢竟讀書人不能叫竊取而是叫借鑒。傳送門
.tag-input-warp{????width:?80%;
????height:?150px;
????border-radius:?5px;
????border:?1px?solid?#666;
????margin:?auto;
????padding:?24px;
??}
??.tag-item,?.tag-input{
????display:?inline-block;
??}
??.tag-item{
????padding:?10px?14px;
????font-size:?14px;
????background-color:?#f2f9ec;
????color:?#84c259;
????border:?1px?solid?#e4fada;
????text-align:?center;
????margin:?6px;
????/*vertical-align:?middle;*/
??}
??.tag-input{
????border:?none;
????outline:?none;
??}
??.tag-text{
????vertical-align:?middle;
??}
??.tag-icon__close{
????cursor:?pointer;
????vertical-align:?middle;
????display:?inline-block;
????width:?16px;
????height:?16px;
????background-size:?contain;
????background-repeat:?no-repeat;
????background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAYAAAAj6qa3AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAAjdJREFUaN7t1t9LU2EcBvDndRtKR6YX4UQCJevCi26k6CI0vYluBAeObZgEUdFNSjfhRNtGh04qBHUKN6iLfkjtUFANTE7E8OxClzLIbqSZrMARNEr6gTr1vF2tiyLQ9e5sg/fzB7x8n4fzft8DcBzHcRzHcWwEA3OzZ89YLKzP9dJYY/d5q/Wq9FJ1dFVVsTq3jN2AEXqSVld/vrE68P3T/Pzl5mizO9jZySq4+UPGps9MTm7uqrCb5WCw6Arwk3Zyl6ysYJYeAhSFpOgJDCmK+Cr6zXXJbt/peaP31AM9NYJgebC+sHUhHCbPqBVf6+pMvZs/9Nr+flZz5434Uxtwd/j9Yq12zV2TyWy3iGxw8b624VqamhKva8fd+5JJiUaokzY0FDpX3oooVHBidBFoxG7EPB6Mk9P0nNNZvrx6xBJQ1XVSEd+YmZjAF3SQY/X1pt6tF3qirc1D2kmIJJMlX8A/i9iD/fRdIoEe3CIHBcGo4FnMluB2lT9ZC5tjIyPwkCVYUym8xRsSbWoqG6c34ZAko4IbXkD2jv/+1EEXAQCn8JTKsqx/JM9xR5ZzfTWKtoC/gv9xxwfHWuceqX19eI80DksSuultEgiFjC4ib8F3utVzfT6LRvbPTfRpR13R6elcn7OSK4JVcKOLYLYDzBfXxnTRZoOAxySl61hAmu5tafnfrT4otF55GPZ68ZosIj48jFEaJ2mfT1EUxeEwmVjNXzK8NEIdXZWVhZ6D4ziO47jS9wur727+lgG2ewAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0wNS0yOFQyMjowMzoyNiswODowMBt9NI0AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMDUtMjhUMjI6MDM6MjYrMDg6MDBqIIwxAAAASHRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9ob21lL2FkbWluL2ljb24tZm9udC90bXAvaWNvbl92dXY4bmVpeTFjL2NoYWhhby5zdmc0h1nOAAAAAElFTkSuQmCC");
??}
實際效果如下:
感覺還行。。。
v-model語法糖
把內部的tag傳遞出去:
Vue內置了v-model指令,v-model 是一個語法糖,可以拆解為 props: value 和 events: input。就是說組件只要提供一個名為 value 的 prop,以及名為 input 的自定義事件,滿足這兩個條件,使用者就能在自定義組件上使用 v-model;
// v-model語法糖?關鍵this.$emit('input',?this.tags)
//?使用方法
<tag-input?v-model="res">
//?通過res獲取內部狀態
組件的export
相信很多人在用Vue使用別人的組件時,會用到 Vue.use() 。例如:Vue.use(VueRouter)、Vue.use(MintUI)。那這是為什么吶?
接下來我們自定義一個需要 Vue.use() 的組件,也就是有 install 的組件。
//?index.jsimport?TagInput?from?'./Tag-Input.vue';
/*?istanbul?ignore?next?*/
TagInput.install?=?function(Vue)?{
??Vue.component(TagInput.name,?TagInput);
};
export?default?TagInput;
Tag-Input的全局注冊
// 引入組件import TagInput from '@/components/Tag-Input';
Vue.use(TagInput)
完整代碼
<template><div?class="tag-input-warp">
??
??<div?class="tag-item"?v-for="(item,?index)?in?tags"?:key="index">
????<span?class="tag-text">{{?item?}}span>
????<span?class="tag-icon__close"?@click="deleteTagByIndex(index)">span>
??div>
??
??<input?class="tag-input"?@keyup.space="generateTag"?autofocus?v-model="value"?type="text">
div>
template>
<script>export?default?{name:?'Tag-Input',
??data?()?{return?{tags:?[],value:?''
????}
??},methods:?{
????generateTag?()?{if?(this.value.trim().length?>?0)?{this.tags.push(this.value)// v-model語法糖?關鍵this.$emit('input',?this.tags)
??????}this.value?=?''
????},
????deleteTagByIndex?(index)?{this.tags.splice(index,?1)
????}
??}
}script>
<style?scoped>.tag-input-warp{width:?80%;height:?150px;border-radius:?5px;border:?1px?solid?#666;margin:?auto;padding:?24px;
??}.tag-item,?.tag-input{display:?inline-block;
??}.tag-item{padding:?10px?14px;font-size:?14px;background-color:?#f2f9ec;color:?#84c259;border:?1px?solid?#e4fada;text-align:?center;margin:?6px;/*vertical-align:?middle;*/
??}.tag-input{border:?none;outline:?none;color:?#666666;
??}.tag-text{vertical-align:?middle;
??}.tag-icon__close{cursor:?pointer;vertical-align:?middle;display:?inline-block;width:?16px;height:?16px;background-size:?contain;background-repeat:?no-repeat;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgEAYAAAAj6qa3AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAAjdJREFUaN7t1t9LU2EcBvDndRtKR6YX4UQCJevCi26k6CI0vYluBAeObZgEUdFNSjfhRNtGh04qBHUKN6iLfkjtUFANTE7E8OxClzLIbqSZrMARNEr6gTr1vF2tiyLQ9e5sg/fzB7x8n4fzft8DcBzHcRzHcWwEA3OzZ89YLKzP9dJYY/d5q/Wq9FJ1dFVVsTq3jN2AEXqSVld/vrE68P3T/Pzl5mizO9jZySq4+UPGps9MTm7uqrCb5WCw6Arwk3Zyl6ysYJYeAhSFpOgJDCmK+Cr6zXXJbt/peaP31AM9NYJgebC+sHUhHCbPqBVf6+pMvZs/9Nr+flZz5434Uxtwd/j9Yq12zV2TyWy3iGxw8b624VqamhKva8fd+5JJiUaokzY0FDpX3oooVHBidBFoxG7EPB6Mk9P0nNNZvrx6xBJQ1XVSEd+YmZjAF3SQY/X1pt6tF3qirc1D2kmIJJMlX8A/i9iD/fRdIoEe3CIHBcGo4FnMluB2lT9ZC5tjIyPwkCVYUym8xRsSbWoqG6c34ZAko4IbXkD2jv/+1EEXAQCn8JTKsqx/JM9xR5ZzfTWKtoC/gv9xxwfHWuceqX19eI80DksSuultEgiFjC4ib8F3utVzfT6LRvbPTfRpR13R6elcn7OSK4JVcKOLYLYDzBfXxnTRZoOAxySl61hAmu5tafnfrT4otF55GPZ68ZosIj48jFEaJ2mfT1EUxeEwmVjNXzK8NEIdXZWVhZ6D4ziO47jS9wur727+lgG2ewAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMC0wNS0yOFQyMjowMzoyNiswODowMBt9NI0AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjAtMDUtMjhUMjI6MDM6MjYrMDg6MDBqIIwxAAAASHRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9ob21lL2FkbWluL2ljb24tZm9udC90bXAvaWNvbl92dXY4bmVpeTFjL2NoYWhhby5zdmc0h1nOAAAAAElFTkSuQmCC");
??}style>
寫在最后
本文寫到這里其實還有一些功能沒有實現,希望大家留言討論;后續我將會繼續發布button/dialog/icon/toast等等的組件的包教不包會系列, 來復盤我多年的組件化之旅。歡迎各位轉發收藏。
總結
以上是生活随笔為你收集整理的vue 字符串分割_嗯哼vue组件taginput包教不包会的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win7 网络端口怎么设置_教你win7
- 下一篇: mysql排序两位数_MySQL_Mys