種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小時內與您取得聯系。