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>
书写基本逻辑:
- 在组件内部维护一个
tags
数组默认为空数组 - 在组件内部维护一个
value
字符串默认为空字符串 - 书写一个方法
generateTag
,绑定给input
的keyup
事件并且给定修饰符为space/enter
,当输入为合法字符串后,将当前的value
值push
到tags
中 通过v-for
循环出来。
代码如下:
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包教不包会相关推荐
- vue java 插件开发_实习模块vue+java小型全栈开发(三)
实习模块vue+java小型全栈开发(三) --dx 背景 首先,先给自己一个答案:这篇博客我定义为(三),因为之前的两个模块页面,内容都是一样的,但是被改了几次需求,就一直拖着没有上传. 今天是真正 ...
- vue 全局排序_搞定VUE [ 一 ]
击上方 蓝字 关注我 首先.以我个人的观点,不赞成把这些东西死记下来,会使用,能上手做,有不明白的及时的去浏览.翻阅,在实战中去快速的理解和掌握,之后水到渠成式的一步步去走向深入.当然,从自身的职 ...
- vue 生命周期_深入理解Vue实例生命周期
vue实例生命周期与生命周期钩子 每个 Vue 实 例在被创建时都会经过一系列的初始化过程.例如,需要设置数据监听.编译模板.将实例挂载到 DOM 并在数据变化时更新 DOM 等. 为了让开发者在 ...
- vue 数组长度_深入理解Vue的数据响应式
什么是响应式 当一个物体对外界的变化做出反应就叫响应式的,如"我打你一拳,你会喊疼". Vue的数据响应式 就是对数据做出改变时,视图上也会做出相应的变化. 举个例子 1const ...
- python 字符串分割_如何使用python语言split方法对不同字符串分割
在JavaScript中,可以使用split()将字符串分割成字符串数组:而在python语言中,split()方法也可以将字符串进行分割,分割之后的结果放置在列表中.下面利用几个实例说明split( ...
- vue 新手指引_精通react/vue组件设计之快速实现一个可定制的进度条组件
前言 这篇文章是笔者写组件设计的第四篇文章,之所以会写组件设计相关的文章,是因为作为一名前端优秀的前端工程师,面对各种繁琐而重复的工作,我们不应该按部就班的去"辛勤劳动",而是要根 ...
- render vue 添加类_详解vue 动态加载并注册组件且通过 render动态创建该组件
基于 iview Tabs 组件实现 功能:为每个 tab 动态创建不同的.特定的组件内容,而不需要大量的 import 组件并进行 component 注册 Index.vue import loa ...
- vue 日期面板_手写Vue日历组件
export class Lunar {//初一显示月份 //节日按照优先级替换日 private dataObj: any ={ month:"", day:"&quo ...
- vue制作日历_如何使用Vue制作每月日历
vue制作日历 Have you ever seen a calendar on a webpage and thought, how the heck did they did that? For ...
最新文章
- 科普|深度解析5G与未来天线技术
- Linux安装GitLib
- 6-2 链式表的按序号查找
- HTTP basic auth
- 三星要用Exynos 9芯片打造独立VR头显
- spring jms 事务_Spring JMS:处理事务中的消息
- mfc对话框在不同计算机上显示不全
- lightswitch 添加 TreeView 控件
- python3 缺少PIP解决办法
- Linux下文件系统目录结构
- springboot 没有找到service_Spring Boot 应用程序五种部署方式
- 重磅!2020 年算法工程师技术路线图
- 【版本控制工具】svn服务器、客户端安装配置及eclipse的svn检出
- directx修复工具win7_win7蓝屏该怎么解决图文教程
- 微信公众号支付功能开发
- 广东地区经纬度Python版
- MATLAB | 绘图复刻(二) | 折线图+误差棒+柱状图+散点抖动+灰色背景+图片叠加
- 前端css解决z-index 上层元素遮挡下层元素的方法
- 南开大学20春计算机应用基础在线作业,南开大学20春学期计算机应用基础在线作业参考答案...
- (嵌入式)关于arm中的存储控制器
热门文章
- 【渝粤教育】电大中专新媒体营销实务 (13)作业 题库
- 2021年春季学期期末统一考试 劳动与社会保障法(本) 试题
- matlab 矩阵jocobi迭代_高校MATLAB被禁用,掀起中国本土软件脆弱的冰山一角
- oracle 邻接模型,【原创】MySQL 模拟Oracle邻接模型树形处理
- python怎么输入两行_python交互模式下输入换行/输入多行命令的方法
- Java实现复数Complex的加减乘除运算、取模、求幅角角度
- html selsec 文字靠右,EDA课程设计
- C语言去括号编程题,去括号 - C语言网
- Java构建子类对象时的顺序
- java 生成校验验证码_java 验证码生成与校验