JS框架之vue.js(深入三:組件1)
這個(gè)要單獨(dú)寫,原文是這么描述vue的組件的:組件(Component)是 Vue.js 最強(qiáng)大的功能之一。組件可以擴(kuò)展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以是原生 HTML 元素的形式,以 is 特性擴(kuò)展。
這個(gè)特性我感覺比較難理解,一步步來,看看組件到底是個(gè)什么東西?
1.舉個(gè)栗子
//model層: // 通過extend方式定義一個(gè)Vue組件 var MyComponent = Vue.extend({ template: '<div>A custom component!</div>' }) // 向Vue注冊這個(gè)組件,名稱定為my-component Vue.component('my-component', MyComponent) // 創(chuàng)建根實(shí)例 new Vue({ el: '#example' }) //Vue層: <div id="example"> <my-component></my-component> </div>
渲染為:
<div id="example"> <div>A custom component!</div> </div>
就是這個(gè)栗子,差點(diǎn)把我忽悠了,以為前面對extend的概念理解錯(cuò)了。還記得前面是這么描述
var MyComponent = Vue.extend()的,Vue相當(dāng)于基類,MyComponent繼承了Vue,擁有了Vue的屬性和方法,但是繼承的概念還有另一層,就是基類是木有子類自定義的屬性和方法的。這里的子類MyComponent擴(kuò)展了一個(gè)屬性template,按照繼承的說法,Vue基類是不能使用的,但是這個(gè)栗子看似違背了這個(gè)規(guī)則,最后創(chuàng)建的是Vue實(shí)例,同時(shí)讓模板生效了。正常的寫法不是應(yīng)該這樣:
//model層: // 通過extend方式定義一個(gè)Vue組件 var MyComponent = Vue.extend({ template: '<div>A cu stom component!</div>' }) // 不用注冊 //Vue.component('my-component', MyComponent) // 創(chuàng)建MyComponent 實(shí)例 new MyComponent ({ el: '#example' }) //Vue層: <div id="example"> //不用組件 //<my-component></my-component> </div>
經(jīng)過試驗(yàn),這種寫法確實(shí)沒錯(cuò),也可以正常顯示。問題來了,為什么第一種寫法也是可以的,比較兩處代碼,發(fā)現(xiàn)第一種寫法有一個(gè)注冊過程,注冊了一個(gè)my-component,最后使用的也是這個(gè)my-component,仔細(xì)想想,并不是說Vue實(shí)例可以使用template,而是向Vue注冊了這個(gè)組件后,Vue實(shí)例就可以使用這個(gè)組件了,所以并不沖突。(嚇?biāo)缹殞毩? -)
想清楚這個(gè)后,再來考慮另外一個(gè)問題,這兩種寫法的區(qū)別在于哪里?
有沒有發(fā)現(xiàn),第二種寫法其實(shí)是很有限制的,他替換了整個(gè)div,不管div中有多少內(nèi)容。比如:
<div id="example"> ssssdfsdaf <button>abc</button> </div>
最后統(tǒng)統(tǒng)不見,被替換成<div>A cu stom component!</div>。靈活度太低,如果我只想替換ssssdfsdaf怎么辦?所以就要用第一種方式了,于是幡然醒悟,原來這就是組件,就像一個(gè)零件一樣,想往哪塞就往哪塞:
<div id="example"> <my-template>ssssdfsdaf<my-template> <button>abc</button> </div>
另外,注冊必須在新建實(shí)例前,反過來的話,新建的實(shí)例肯定不能使用組件的。
原文還說replace可以決定是否替換,這個(gè)不知道咋用,先留一坑在這,后面看看能否用上。 //坑1
2.組件注冊有兩種方式:
一是前面看到的全局注冊方式,Vue.component,這種全局可用。
二是局部注冊方式
// 局部注冊也可以這么做 var Parent = Vue.extend({ components: { 'my-component': { template: '<div>A custom component!</div>' } } })
這種寫法最簡,很明顯Parent擴(kuò)展了Vue,擁有了組件my-component。此時(shí)的組件只有Parent能用,Vue不能用。
3.is屬性
組件在使用的過程中也是有限制的。原因在于:
Vue 的模板是 DOM 模板,使用瀏覽器原生的解析器而不是自己實(shí)現(xiàn)一個(gè)。所以組件被替換后必須依照html的正常標(biāo)準(zhǔn)來,它必須是有效的 HTML 片段。一些 HTML 元素對什么元素可以放在它里面有限制。常見的限制:
a 不能包含其它的交互元素(如按鈕,鏈接)
ul 和 ol 只能直接包含 li
select 只能包含 option 和 optgroup
table 只能直接包含 thead, tbody, tfoot, tr, caption, col, colgroup
tr 只能直接包含 th 和 td
以table為例
<table> <my-component></my-component> <my-component></my-component> </table> // 定義 var MyComponent = Vue.extend({ template: '<tr>A custom component!</tr>' })
這樣的寫法看似正常,因?yàn)?lt;table><tr></tr></table>結(jié)構(gòu)是正常的,但是實(shí)際上不能依賴自定義組件在瀏覽器驗(yàn)證之前的展開結(jié)果,所以這里不被認(rèn)為是<tr>。為此,is屬性便有作用了,將以上寫法改寫:
<table> <tr is="my-component"></tr> //這里改成is屬性 <tr is="my-component"></tr> <tr is="my-component"></tr> </table> // 定義 var MyComponent = Vue.extend({ template: '<div>A custom component!</div>' //這里不能用tr })
修改后,相當(dāng)于
<table> <tr><my-component></my-component></tr> <tr><my-component></my-component></tr> <tr><my-component></my-component></tr> </table>
保留了原來的tr,所以dom解析不會(huì)出錯(cuò)
4.Props:組件通訊的手段
4.1“prop” 是組件數(shù)據(jù)的一個(gè)字段,期望從父組件傳下來。子組件需要顯式地用 props 選項(xiàng) 聲明 props:
Vue.component('child', { // 聲明 props,這里駝峰式命名 props: ['myMessage'], //模板中可以這樣用 template: '<span>{{ myMessage }}</span>' })
HTML 特性不區(qū)分大小寫。名字形式為 camelCase 駝峰式的 prop 用作特性時(shí),需要轉(zhuǎn)為 kebab-case(短橫線隔開),所以html中是這個(gè)樣子的:
<!-- kebab-case in HTML --> <child my-message="hello!"></child>
以上這種是props的靜態(tài)用法,也可以用 v-bind 綁定動(dòng)態(tài) Props 到父組件的數(shù)據(jù)。每當(dāng)父組件的數(shù)據(jù)變化時(shí),也會(huì)傳導(dǎo)給子組件:
<div> <input v-model="parentMsg"> <br> <child v-bind:my-message="parentMsg"></child> </div>
這時(shí)候看到v-model有點(diǎn)懵逼,這貨不是跟{{}}類似,引用data屬性中的parentMsg嗎?此時(shí)肯定是沒有定義parentMsg的,所以v-bind:my-message=”parentMsg”綁定組件的同時(shí),賦予了父組件parentMsg屬性。
4.2 prop的綁定類型:
prop 默認(rèn)是單向綁定:當(dāng)父組件的屬性變化時(shí),將傳導(dǎo)給子組件,但是反過來不會(huì)。這是為了防止子組件無意修改了父組件的狀態(tài)——這會(huì)讓應(yīng)用的數(shù)據(jù)流難以理解。不過,也可以使用 .sync 或 .once 綁定修飾符顯式地強(qiáng)制雙向或單次綁定:
<!-- 默認(rèn)為單向綁定 --> <child :msg="parentMsg"></child> <!-- 雙向綁定 --> <child :msg.sync="parentMsg"></child> <!-- 單次綁定 --> <child :msg.once="parentMsg"></child>
雙向綁定會(huì)把子組件的 msg 屬性同步回父組件的 parentMsg 屬性。單次綁定在建立之后不會(huì)同步之后的變化。這里原文還特定強(qiáng)調(diào)了下, prop 是一個(gè)對象或數(shù)組時(shí),是按引用傳遞,修改內(nèi)容會(huì)隨時(shí)修改父組件內(nèi)容,這個(gè)有語言基礎(chǔ)的都知道。
4.3 prop驗(yàn)證:
組件可以為 props 指定驗(yàn)證要求。當(dāng)組件給其他人使用時(shí)這很有用,因?yàn)檫@些驗(yàn)證要求構(gòu)成了組件的 API,確保其他人正確地使用組件。此時(shí) props 的值是一個(gè)對象({}而不是[]),包含驗(yàn)證要求:
Vue.component('example', { props: { // 基礎(chǔ)類型檢測 (`null` 意思是任何類型都可以) propA: Number, // 多種類型 (1.0.21+) propM: [String, Number], // 必需且是字符串 propB: { type: String, required: true }, // 數(shù)字,有默認(rèn)值 propC: { type: Number, default: 100 }, // 對象/數(shù)組的默認(rèn)值應(yīng)當(dāng)由一個(gè)函數(shù)返回 propD: { type: Object, default: function () { return { msg: 'hello' } } }, // 指定這個(gè) prop 為雙向綁定 // 如果綁定類型不對將拋出一條警告 propE: { twoWay: true }, // 自定義驗(yàn)證函數(shù) propF: { validator: function (value) { return value > 10 } }, // 轉(zhuǎn)換函數(shù)(1.0.12 新增) // 在設(shè)置值之前轉(zhuǎn)換值 propG: { coerce: function (val) { return val + '' // 將值轉(zhuǎn)換為字符串 } }, propH: { coerce: function (val) { return JSON.parse(val) // 將 JSON 字符串轉(zhuǎn)換為對象 } } } })
type 可以是下面原生構(gòu)造器:
String
Number
Boolean
Function
Object
Array
type 也可以是一個(gè)自定義構(gòu)造器,使用 instanceof 檢測。
當(dāng) prop 驗(yàn)證失敗了,Vue 將拒絕在子組件上設(shè)置此值,如果使用的是開發(fā)版本會(huì)拋出一條警告。
這里也是看的我一臉懵逼,連個(gè)栗子都不給,拿剛才的例子改一下打個(gè)比方
Vue.component('child', { // 聲明 props,這里駝峰式命名 props: ['myMessage'], //模板中可以這樣用 template: '<span>{{ myMessage+1}}</span>' //改成表達(dá)式 }) <!-- kebab-case in HTML --> <child my-message="hello!"></child> //這里先不改
如果我們希望別人把child組件的myMessage當(dāng)做Number類型來處理,而我們這里又沒有做prop驗(yàn)證,結(jié)果就是{{ myMessage+1}}會(huì)變成字符串拼接,當(dāng)html傳入的是hello!,渲染出來結(jié)果:hello!
所以說,告訴別人這里要傳入Number類型是必要的,于是改為:
Vue.component('child', { // 聲明 props,這里駝峰式命名 props: {myMessage:Number}, //模板中可以這樣用 template: '<span>{{ myMessage+1}}</span>' //改成表達(dá)式 })
這時(shí)候如果傳入hello!,此時(shí)渲染結(jié)果?沒錯(cuò),就是NaN。這樣別人就知道要傳入一個(gè)數(shù)字了。
如果這樣傳入
<child my-message="123"></child> //改成123
這樣總行了吧,運(yùn)行,他喵的居然還不行,還是NaN。原文有這樣的解釋:
//#字面量語法 vs. 動(dòng)態(tài)語法 //初學(xué)者常犯的一個(gè)錯(cuò)誤是使用字面量語法傳遞數(shù)值: <!-- 傳遞了一個(gè)字符串 "1" --> <comp some-prop="1"></comp> 因?yàn)樗且粋€(gè)字面 prop,它的值以字符串 "1" 而不是以實(shí)際的數(shù)字傳下去。如果想傳遞一個(gè)實(shí)際的 JavaScript 數(shù)字,需要使用動(dòng)態(tài)語法,從而讓它的值被當(dāng)作 JavaScript 表達(dá)式計(jì)算: <!-- 傳遞實(shí)際的數(shù)字 --> <comp :some-prop="1"></comp>
好吧,也就是說剛才傳遞的實(shí)際上是字符串”123”,結(jié)果必然是NaN,再改:
<child :my-message="123"></child> //改成123
此時(shí){{myMessage+1}}會(huì)得到正確的結(jié)果:124
以上所述是小編給大家介紹的JS框架之vue.js(深入三:組件1),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
vue3發(fā)送驗(yàn)證碼倒計(jì)時(shí)功能的實(shí)現(xiàn)(防止連點(diǎn)、封裝復(fù)用)
這篇文章主要介紹了vue3發(fā)送驗(yàn)證碼倒計(jì)時(shí)功能的實(shí)現(xiàn)(防止連點(diǎn)、封裝復(fù)用),實(shí)現(xiàn)思路是點(diǎn)擊發(fā)送驗(yàn)證碼,驗(yàn)證碼倒計(jì)時(shí),校驗(yàn)手機(jī)號是否正常等一系列操作,本文通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01vue實(shí)現(xiàn)豎屏滾動(dòng)公告效果
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)豎屏滾動(dòng)公告效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04vue3+ts+axios+pinia實(shí)現(xiàn)無感刷新方式
這篇文章主要介紹了vue3+ts+axios+pinia實(shí)現(xiàn)無感刷新方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04Vue 項(xiàng)目遷移 React 路由部分經(jīng)驗(yàn)分享
這篇文章主要為大家介紹了Vue 項(xiàng)目遷移 React 路由部分經(jīng)驗(yàn)分享,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09vite+vue3搭建的工程實(shí)現(xiàn)批量導(dǎo)入store的module
這篇文章主要介紹了vite+vue3搭建的工程實(shí)現(xiàn)批量導(dǎo)入store的module方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03vue利用vue meta info設(shè)置每個(gè)頁面的title與meta信息
這篇文章主要給大家介紹了關(guān)于vue如何利用vue meta info設(shè)置每個(gè)頁面的title與meta信息的相關(guān)資料,文中將實(shí)現(xiàn)的方法介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-10-10validate?注冊頁的表單數(shù)據(jù)校驗(yàn)實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了validate?注冊頁的表單數(shù)據(jù)校驗(yàn)實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09VUE+Express+MongoDB前后端分離實(shí)現(xiàn)一個(gè)便簽墻
這篇文章主要介紹了VUE+Express+MongoDB前后端分離實(shí)現(xiàn)一個(gè)便簽墻,需要的朋友可以參考下2021-04-04element ui提交表單返回成功后自動(dòng)清空表單的值的實(shí)現(xiàn)代碼
這篇文章主要介紹了elementui提交表單返回成功后自動(dòng)清空表單的值,本文通過兩種方法結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08