种UI库的功能都是非常强大的,尤其对于我这种不会 css 的人来说,就更是帮了大忙了。
只是嘛,如果再封装一下的话,那么用起来就会更方便了。
那么如何封装呢?
可以封装,但是原生UI库提供的强大功能不能给封装没了吧,吃了回扣可是不好滴。
那么如何做到不遗漏呢?先做一个合格的传声筒。
先看看 el-input 提供的属性:
太长了,这里只截了一半。
这么多的属性,如果一个一个都弄到 props 里面,然后再一个一个绑定上去,这就太麻烦了。
我们可以分成两部分,重要的属性做到 props 里面,其他的可以放到 $attrs 里面。
模板
<template>
<div>
<el-input
v-model="value" // 不能直接帮的属性
v-bind="$attrs" // 绑定其他属性。
>
</el-input>
</div>
</template>
代码
export default {
name: 'test-text',
inheritAttrs: false,
props: {
modelValue: [String, Number]
},
setup(props, ctx) {
const value = debounceRef(props, ctx.emit)
return {
value
}
}
}
父组件的调用代码:
模板
<inputtext
v-model="value"
v-bind="attrs"
>
</inputtext>
代码
const value = ref('222')
const attrs = reactive({
maxlength: 10,
'show-word-limit': true,
clearable: true
})
这里 modelValue 就是 props ,maxlength、show-word-limit、clearable 就变成了 $attrs 。
然后要看 el-input 是否是根元素,如果是跟元素的话,那么会自动绑定上,不需要我们手动写 v-bind="$attrs"。
如果像上面的例子不是根元素的话,需要手动写 v-bind="$attrs"。
这个是指定组件是否自动绑定 $attrs 。
默认是 true,会自动把 $attrs 绑定到根元素上面,不管根元素是啥。
这里设置为 false,那么$attrs 就不会自动绑定到 div 上面了。
这个稍微复杂一点,插槽本来就有一点绕,官网的介绍又比较含混。
我们可以找到 $slots 这个东东,但是官网的介绍(https://www.vue3js.cn/docs/zh/api/instance-properties.html#slots )却是 使用 h,这个就……
不过想要传递插槽,还是需要这个。
我们先看看 el-input 的插槽的使用。
<el-input
placeholder="请输入内容"
v-model="input3"
class="input-with-select"
>
<template #prepend>
<el-select v-model="select" placeholder="请选择">
<el-option label="餐厅名" value="1"></el-option>
<el-option label="订单号" value="2"></el-option>
<el-option label="用户电话" value="3"></el-option>
</el-select>
</template>
<template #append>
<el-button icon="el-icon-search"></el-button>
</template>
</el-input>
那么想要传递插槽的话,是不是可以这样?
<!--传递插槽-->
<template v-slot:prepend> // 给递给el-input 的插槽
<slot name="prepend"></slot> // 接收父组件传递进来的插槽
</template>
测试可以。
那么总不会一个一个写吧,这也太麻烦了。如果能够for就好了。
等等, for?那么我们是不是可以这样。
<!--传递插槽-->
<template
v-for="(item, key, index) in $slots"
:key="index"
v-slot:[key]
>
<slot :name="key"></slot>
</template>
测试可以。
完整代码
<el-input
ref="refInput"
v-model="value"
v-bind="$attrs"
>
<!--传递插槽-->
<template
v-for="(item, key, index) in $slots"
:key="index"
v-slot:[key]
>
<slot :name="key"></slot>
</template>
</el-input>
这个就简单了,啥都不用做,自动就传递出去了。el-input 是否是跟元素都可以。
测试一下:
<inputtext
ref="refInput"
v-model="value"
v-bind="props"
@clear="clear"
@my-change="myChange"
>
一直都忽略了,还有方法这个事,因为基本没用过。
使用方法嘛,就需要使用 ref,这个词 ref 非彼 ref,说不清了,还是写代码吧。
直接使用UI库组件的方法,比如 el-input 的 提供的 select:
<el-input
ref="refInput" // 注意这里的 ref
v-model="value"
v-bind="$attrs" >
</el-input>
ref 的写法,不要加冒号。
const refInput = ref(null) // 先放一个null
onMounted(() => { // 然后在 onMounted 里面才能得到值。
console.log('refinput', refInput) // 看看啥样。
refInput.value.select() // 调用方法,文本框的内容会被选中
})
先定义一个 ref,然后交给模板里的 ref,好像有点绕,这里必须使用 ref,reactive是不行滴。
在渲染后才能生效,也就是说必须在 onMounted 里面才能得到值,我们看看打印结果:(太长只能截取一部分)
很长吧。
<inputtext
ref="refInput"
v-model="value">
</el-input>
// 测试方法
const refInput = ref(null)
onMounted(() => {
console.log('refinput', refInput)
// refInput.value.$refs.refInput.select()
refInput.value.refInput.select()
})
父组件里面的用法是一样的,只是需要再套一层,才能拿到自定义组件内部的UI库组件。
看看结构:
太长了,还在下面。
这个就比较近了。
话说为啥弄得这么多属性和方法事件呀?
上面那种方式,还可以让父组件调用子组件内部定义的方法,比如内部定义一个
const setInput = () => {
value.value = new Date()
}
父组件可以这样调用
refInput.value.setInput()
其实事件和方法,并没有封装,而是直接就可以使用的。
这是 element-plus 测试的结果,其他UI库没有测试。
插槽需要写一个 v-for 就可以实现传递,而且是通用的代码。
属性 就需要规划一下了,看设计要求,哪些放在 props里面,哪些放在attrs 里面。
可以看作一种特殊字体,其展示的是图标,而不再是文字,其拥有字体的特性,比如大小、颜色、透明效果、阴影等,字体图标加载快、不变形。也可以看作是矢量格式的图标。
(1)iconmoon字体图标库:https://icomoon.io/app
(2)阿里iconfont字体图标库:https://www.iconfont.cn/
(3)font-awesome字体图标库:
以iconmoon为例
(1)选择需要的图标并下载
1)在fonts文件夹下有四种类型的字体文件,每种字体文件兼容浏览器的种类不同
a).tff格式(TrueTypeFont),美国苹果公司和微软公司共同开发的,在Windows和Mac操作系统中为默认字体;IE9+、FireFox3.5+、Chrome4+、Safari3+、Opera10+、IOS Mobile中的Safari4.2+等浏览器支持该字体。
b).woff格式(Web Open Font Format-Web开放字体格式),是一种网页所采用的字体格式标准,使用zlib压缩,文件大小一般比TTF小40%;IE9+、FireFox3.6+、Chrome6+、Safari5.1+、Opera11.1+等浏览器支持该字体。
c).eot格式(Embedded Open Type-嵌入式OpenType ),微软设计用来在网页使用的字体格式,是OpenType字体的压缩格式,IE专用,IE4+支持该字体。
d).svg格式(Scalable Vector Graphics-可缩放的矢量图形),它是一种用XML定义的语言,用来描述二维矢量及矢量/栅格图形;Chrome4+、Safari3.1+、Opera10+、IOS Mobile中Safari3.2+等浏览器支持该字体。
其他字体
e).otf格式(Open Type Font),Microsoft和Adobe公司开发的,.otf格式比.ttf更为强大,可以把PostScript字体嵌入到TrueType中。
2)字体转换
https://www.fontke.com/tool/convfont/
(2)字体图标的引入
1)把字体放到项目的相应位置
将下载解压后的fonts文件夹放到项目路径下
2)在html页面中引入字体
利用CSS的@font-face属性,引入外部字体;
在style.css文件中有如下代码,为固定用法,注意url中字体路径,其它可以不变。
在html的style标签中引入如下代码:
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?8l3wc0');
src: url('fonts/icomoon.eot?8l3wc0#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?8l3wc0') format('truetype'),
url('fonts/icomoon.woff?8l3wc0') format('woff'),
url('fonts/icomoon.svg?8l3wc0#icomoon') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}
3)为元素用该字体
span {
font-family: "icomoon";
}
4)为元素添加内容
复制demo.html中需要的图标,如下,将其作为元素的内容。
<span></span>
(3)新增字体图标的引入
当利用iconmoon选用字体图标时,如果有新增的字体图标需要加入,则需要用到.json文件,如下,在原先选择的基础上,再选择新选择的字体图标,然后再下载使用。
前端的开发过程中,需要用到大量的图片,当使用这些图片一段时间后,会发现这个过程是千篇一律的,设计,切图,适配。当然,许多人也喜欢用字体图标。时间久了,这很枯燥,作为一个前端,不就是喜欢折腾吗?不折腾不舒服斯基,那么这次就来尝试用纯css绘制动画线性icon吧。
当我第一次使用纯css线性icon的时候,那感觉就像呼吸到了新鲜空气一般,它的高可扩展性、易使用、加载速度快的特定给我留下了非常深刻的印象。
线性图标使用了什么技术呢?
其实很容易猜到,它使用了svg技术。整个开始过程其实是把svg放到一个背景中,然后用一张线性渐变的背景覆盖在上方,然后使用css的mix-blend-mode的属性来裁剪、混合。最后线性渐变背景的混合模式设置为mix-blend-mode: screen后,线性渐变会渐渐消失在白色背景上。这就形成了我们的渐变图标。
下面是具体的代码实现:
一、编写背景样式
背景图可以是亮的或是暗的,如果是暗背景,那渐变层需要设置mix-blend-mode: multiply,如果背景图是亮的,那渐变的混合属性需要设置为mix-blend-mode:screen,下面,我们选择一个亮的背景:
二、添加线性图标
<divclass="icon-background"><svgxmlns="http://www.w3.org/2000/svg"viewBox="0 0 50 62"><rectx="19"y="6"width="12"height="4"/><rectx="1"y="38"width="48"height="4"/><linex1="25"y1="1"x2="25"y2="6"/><linex1="25"y1="42"x2="25"y2="58"/><lineclass="cls-1"x1="38"y1="42"x2="44"y2="61"/><linex1="12"y1="42"x2="6"y2="61"/><linex1="8.53"y1="53"x2="41.47"y2="53"/><polygonpoints="3 38 16.75 25.99 24.59 31.99 36.92 20 47 29.82 47 37.98 3 38"/><circlecx="14"cy="18"r="3"/><polygonpoints="31 8 31 10 19 10 19 8 3 8 3 38 47 38 47 8 31 8"/></svg></div>
svg的颜色需要设置为黑色:
svg{ color:#000; position:relative; opacity:.9; width:100%; height:100%; display:block; transition:transform .3s ease;}
三、制作渐变层
该层需要紧跟着icon层,并且需要设置渐变属性
四、添加动画效果
该步骤非常简单,只要使用keyframes并配以旋转动画即可。
*请认真填写需求信息,我们会在24小时内与您取得联系。