vue2封裝input組件方式(輸入的雙向綁定)
vue2封裝input組件
重點
首先我們要明白 vue中v-modle 的對于input 做了什么
<input type="text" v-model="username"> <input type="text" :value="username" @input="username = $event.target.value">
以上的兩行代碼,所呈現(xiàn)的效果是一樣的。也就是說: v-model=“username” 在input中做了兩件事情。
- :value 綁定了值
- @input=“username = $event.target.value” 監(jiān)聽了值的改變
代碼示例:
父組件
<template> <div id="app"> <lj-input placeholder="請輸入" v-model="username"></lj-input> <div>{{username}}</div> </div> </template> <script> import ljInput from './components/inputCom/LjInput.vue' export default { name: 'App', components: { ljInput }, data(){ return{ username:'', } }, methods: { } } </script>
子組件
<template> <div class="lj-input"> <input :class="{'is-disabled':disabled}" :placeholder="placeholder" :type="type" :disabled ='disabled' :value="value" @input="handleInput" > </div> </template> <script> export default { name:'ljInput', props: { placeholder:{ type:String, default:'' }, type:{ type:String, default:'' }, disabled:{ type:Boolean, default:false }, value:{ type:String, default:'' } }, methods:{ handleInput(e){ // 這句代碼是關鍵 this.$emit('input',e.target.value) } } } </script> <style> .is-disabled{ cursor: not-allowed; } </style>
vue二次封裝input的幾種方式
下面就是自己封裝input 框實現(xiàn)的效果
在看如何封裝之前,先來了解一下v-model是怎么回事。
其實說白了,v-model就是change和value的結合體。
廢話不多說,下面就來看一下在vue中如何封裝自定義的input組件。
封裝原生input
<template> <input type="text" :value="value" @input="handleChange" /> </template> <script> export default { name: "AppInput", model: { prop: "value", event: "change", }, props: { value: "", }, data() { return { }; }, created() {}, mounted() {}, methods: { handleChange(e) { this.$emit("change", e.target.value); }, }, }; </script>
封裝el-input
<template> <!-- 對el-input進行了包裝--> <div> <el-input v-model="localValue" @change="$emit('change', $event)"></el-input> <!-- el-input提供了input事件,讓我們感知el-input內部原生input值的變化,通過$event可以獲取到具體的值 通過emit再次傳遞給父組件一個input事件,父組件中,v-on:input="searchText = $event"這句就能正常使用了 --> <span style="color: #f56c6c; font-size: 12px;"></span> </div> </template> <script> export default { name: "input-name", props: { // 保證父組件中,v-bind:value可以正常設置值 value: [String], }, data() { return { // 獲取props中value的值,并與el-input綁定,過程中不修改props中value的值,保證了單向數(shù)據(jù)流原則 localValue: this.value } } } </script> <style lang="less" scoped> </style>
上面的那種方式會在回顯數(shù)據(jù)時有問題。解決辦法就是:如果出現(xiàn)異步回顯數(shù)據(jù)那么就需要用計算來作為中間值轉換。
<template> <!-- 對el-input進行了包裝--> <div> <el-input v-model="localValue" @change="$emit('change', $event)"></el-input> <!-- el-input提供了input事件,讓我們感知el-input內部原生input值的變化,通過$event可以獲取到具體的值 通過emit再次傳遞給父組件一個input事件,父組件中,v-on:input="searchText = $event"這句就能正常使用了 --> <span style="color: #f56c6c; font-size: 12px;"></span> </div> </template> <script> export default { name: "input-name", props: { // 保證父組件中,v-bind:value可以正常設置值 value: [String], }, data() { return { } }, computed: { localValue: { get: function () { console.log(this.value) return this.value; }, set: function (v) { v; }, }, }, } </script> <style lang="less" scoped> </style>
VUE高級用法封裝input
這種方式更加簡潔,并且不會出現(xiàn)第二種封裝方式出現(xiàn)的bug。
<template> //這里不能使用v-model,會報子組件不能直接操作父組件傳入?yún)?shù)的錯誤 //使用value的話其實就是做一個回顯因為外層的v-model在這里使用已經改變了外層的值了 <el-input v-bind="$attrs" v-on="$listeners" :value="value" ></el-input> </template> <script> export default { name: "f-input", data() { return { }; }, props: { value:"" }, created() {}, mounted() {}, methods: {} }; </script>
//正常的使用方式 <f-input v-model="number"></f-input> //不用v-model語法糖的方式 <f-input :value="number" @change="number = $event,target.value"></f-input>
這里核心用到了兩個方法 attrs 和 listeners 其中 atters 可以把父組件標簽上的所有自定義屬性(不包括props,tyle,class)同步到當前元素中,listeners 可以把 f-input 標簽上的所有方法同步到子組件中當前元素中。
那么上面已經知道 v-model 就是 change 和 value 的語法糖,那在 f-input 上綁定 listeners 就可以讀取到 f-input 的 v-model 的 change 事件,atters 可以讀取到 f-input 的 v-model 的 value 值。
$ 符號打不出來了,將就著看吧。如果還是不明白 atters和 listeners是怎么回事的可以看一下vue官網(wǎng)中的介紹。
看官網(wǎng)又出了一種封裝的寫法,感覺挺有意思,在這里記錄一下。
默認情況下,組件上的 v-model 使用 modelValue 作為 prop 和 update:modelValue 作為事件。我們可以通過向 v-model 傳遞參數(shù)來修改這些名稱
子組件將需要一個 firstName prop 和 lastName prop并發(fā)出 update:firstName 和 update:lastName要同步的事件
var Component = { props: { firstName: String, lastName: String }, emits: ['update:firstName', 'update:lastName'], //vue3可以支持多個根元素,所有這個地方不會有報錯,vue2是會報錯的。 template: ` <input type="text" :value="firstName" @input="$emit('update:firstName', $event.target.value)"> <input type="text" :value="lastName" @input="$emit('update:lastName', $event.target.value)"> ` }
<template> <my-component v-model:first-name="firstName" v-model:last-name="lastName"> </my-component> firstName:{{firstName}} lastName:{{lastName}} </template> <script> const App = { setup(props, context) { const data= reactive({ firstName: 0, lastName: 0, }); return { ...toRefs(data), } }, components: { 'my-component': Component, }, methods: { }, }; const app = createApp(App).mount('#app'); </script>
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
如何通過Vue自帶服務器實現(xiàn)Ajax請求跨域(vue-cli)
從A頁面訪問到B頁面,并且要獲取到B頁面上的數(shù)據(jù),而兩個頁面所在的端口、協(xié)議和域名中哪怕有一個不對等,那么這種行為就叫跨域,這篇文章給大家介紹如何通過Vue自帶服務器實現(xiàn)Ajax請求跨域(vue-cli),感興趣的朋友一起看看吧2023-10-10Vue3中無法為el-tree-select設置反選問題解析
這篇文章主要介紹了Vue3中無法為el-tree-select設置反選問題分析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04Vue 解決通過this.$refs來獲取DOM或者組件報錯問題
這篇文章主要介紹了Vue 解決通過this.$refs來獲取DOM或者組件報錯問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07Vue3+Vite+TS實現(xiàn)二次封裝element-plus業(yè)務組件sfasga
這篇文章主要介紹了在Vue3+Vite+TS的基礎上實現(xiàn)二次封裝element-plus業(yè)務組件sfasga,下面文章也將圍繞實現(xiàn)二次封裝element-plus業(yè)務組件sfasga的相關介紹展開相關內容,具有一定的參考價值,需要的小伙伴可惡意參考一下2021-12-12解決axios發(fā)送post請求返回400狀態(tài)碼的問題
今天小編就為大家分享一篇解決axios發(fā)送post請求返回400狀態(tài)碼的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08Vue項目中如何封裝axios(統(tǒng)一管理http請求)
這篇文章主要給大家介紹了關于Vue項目中如何封裝axios(統(tǒng)一管理http請求)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-05-05