宜興建設(shè)局網(wǎng)站長(zhǎng)沙seo行者seo09
前端組件庫(kù)造輪子——Input組件開發(fā)教程
前言
本系列旨在記錄前端組件庫(kù)開發(fā)經(jīng)驗(yàn),我們的組件庫(kù)項(xiàng)目目前已在Github
開源,下面是項(xiàng)目的部分組件。文章會(huì)詳細(xì)介紹一些造組件庫(kù)輪子的技巧并且最后會(huì)給出完整的演示demo。
文章旨在總結(jié)經(jīng)驗(yàn),開源分享,有問(wèn)題的話也希望路過(guò)的大佬指正。
組件開發(fā)流程
核心功能
Input組件
的核心功能其實(shí)就是實(shí)現(xiàn)v-model
,我們需要對(duì)封裝出來(lái)的組件讓他也擁有v-model
的功能。
比如舉個(gè)例子:
在vue中,我們可以直接對(duì)input標(biāo)簽使用v-model
,但是我們沒(méi)辦法對(duì)封裝的組件直接來(lái)使用v-model
// input 標(biāo)簽可以使用
<input type="text" v-model="input" />// 自定義封裝的 Input 組件 不可以使用v-model
<Input v-model="input" placeholder="請(qǐng)輸入內(nèi)容"></Input>
實(shí)現(xiàn)v-model
實(shí)現(xiàn)v-model
其實(shí)就是雙向綁定,比如我們可以利用vue提供的語(yǔ)法糖v-bind
和事件調(diào)用來(lái)實(shí)現(xiàn)
<input v-bind:value="value" v-on:input="value= $event.target.value" />
所以,原理其實(shí)是一樣的,在vue中,暴露給我們一組交互的數(shù)據(jù)
props: modelValue
emit: update:modelValue
其實(shí)就是在使用v-model
時(shí),在子組件中會(huì)用props: modelValue
來(lái)接受傳進(jìn)來(lái)的數(shù)據(jù),同時(shí)利用事件emit: update:modelValue
官方資料
具體實(shí)現(xiàn)代碼就是
<template><inputclass="input"type="text":value="text"@input.stop="handerInput" />
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
const props = defineProps({modelValue: {type: String,default: "",},
});
const emit = defineEmits(["update:modelValue"]);
const handerInput = (e: Event) => {const target = e.target as HTMLInputElement;emit("update:modelValue", target.value);text.value = target.value;
};
</script>
這樣我們就實(shí)現(xiàn)完成input
組件的雙向綁定功能。
但是還沒(méi)完,我們還需要來(lái)監(jiān)聽(tīng)數(shù)據(jù)的修改,來(lái)更新:value:text
綁定的值。
為什么要做這一步呢?
我們?cè)趧倓偲鋵?shí)只是實(shí)現(xiàn)了改變input
中的值,會(huì)修改我們v-model
綁定的值,但是并沒(méi)有實(shí)現(xiàn)了v-model
修改,來(lái)改變input
的值。
看下面這個(gè)例子
比如,我們用兩個(gè)input
同時(shí)綁定上同一個(gè)value
值,當(dāng)我修改了一個(gè)input的值同時(shí),另一個(gè)input的值一個(gè)也同步修改才對(duì)。
jcode
因此,我們還需要監(jiān)聽(tīng)modelValue
的值,同步修改text.value
watch(() => props.modelValue,(newVal) => {if (newVal == "") return (text.value = "");text.value = props.modelValue ? props.modelValue : "";},
);
這樣我們才算完成了這個(gè)核心功能
樣式更替
在組件庫(kù)開發(fā)中,我們會(huì)發(fā)現(xiàn)一個(gè)組件他是有多種樣式可以選擇的
例如在Hview-ui
中,input
組件就存在可以用size
更換大小的樣式,像這種樣式開發(fā)在組件庫(kù)開發(fā)中也是非常常見(jiàn)。
具體實(shí)現(xiàn)也是非常容易,我們需要在props
預(yù)留出我們想要的屬性,比如size
,當(dāng)然樣式也得預(yù)先設(shè)置好,這里就不多贅述了,想比對(duì)大家來(lái)說(shuō)都不是問(wèn)題。
size: {type: String,default: "medium",
},
接下來(lái)樣式更替在組件中的常用寫法,這個(gè)寫法就會(huì)把當(dāng)前props.size
的值渲染出來(lái),放回成一個(gè)class
類,接下來(lái)我們直接在template
加上這個(gè)類即可。
// template
<template><inputclass="input"type="text":value="text":class="size" // 在這里加上size類@input.stop="handerInput" />
</template>// script
const size = computed(() => {return {[`h-input-${props.size}`]: props.size,};
});
這樣當(dāng) props.size
的值為 small
時(shí),對(duì)象會(huì)被渲染成這樣,在:class
中,如果:后面為true
那么就是加上h-input-small
這個(gè)類了。
{ 'h-input-small': 'small'
}
attrs
最后介紹一下attrs
屬性,想必大家平時(shí)應(yīng)該不怎么會(huì)用到這個(gè)屬性,但是這個(gè)屬性在開發(fā)組件時(shí)相當(dāng)好用,這個(gè)attrs
屬性可以把style
,props
等屬性攔截下來(lái),把其它屬性滲透給孩子組件。
舉個(gè)例子就明白了,
在input
標(biāo)簽中自帶著placeholder
,type
等屬性,如果我們要開發(fā)Input
組件的話,總不可能把這些屬性也全自己實(shí)現(xiàn)吧,那就太麻煩了。
在這里,我們就可以利用attrs
屬性,我們把自己封裝的Input
組件結(jié)構(gòu)一下,他在Dom
渲染應(yīng)該是這樣的
<Input v-model="input" placeholder="請(qǐng)輸入內(nèi)容">// Input組件內(nèi)部<template><inputclass="input"type="text":value="text":class="size"@input.stop="handerInput" /></template>
</Input>
正常來(lái)說(shuō),我們對(duì)組件傳入placeholder
屬性,如果要獲取到placeholder
那么就需要在props
中獲取到,但是如果我們用attrs
,就可以把這個(gè)屬性直接加到input
標(biāo)簽上。
因此,我們就可以用一行代碼,把這些屬性全部實(shí)現(xiàn)了。
<template><inputclass="input"v-bind="$attrs" // +加上attrstype="text":value="text":class="size"@input.stop="handerInput" />
</template>
演示demo
完整項(xiàng)目demo
結(jié)語(yǔ)
Input
組件的核心開發(fā)功能就是上面這些,其他更多的詳細(xì)功能開發(fā)可以參考Hview-ui
項(xiàng)目源碼
如果想要了解更多的組件輪子開發(fā),或者組件庫(kù)開發(fā)流程,更多詳細(xì)的組件開發(fā)過(guò)程更新在GitHub
項(xiàng)目源碼,最后覺(jué)得我們項(xiàng)目or文章不錯(cuò)可以點(diǎn)個(gè)star,點(diǎn)點(diǎn)小手支持一下,也歡迎各路大佬為我們的開源項(xiàng)目添磚加瓦。