您好,登錄后才能下訂單哦!
前言:轉(zhuǎn)眼距離上篇JS組件系列——又一款MVVM組件:Vue(一:30分鐘搞定前端增刪改查)已有好幾個(gè)月了,今天打算將它撿起來,發(fā)現(xiàn)好久不用,Vue相關(guān)技術(shù)點(diǎn)都生疏不少。經(jīng)過這幾個(gè)月的時(shí)間,Vue的發(fā)展也是異常迅猛,不過這好像和博主都沒什么太大的關(guān)系,博主還是老老實(shí)實(shí)研究自己的技術(shù)吧。技術(shù)之路還很長,且行且研究吧。
一、為什么組件很重要
前兩天,看到一篇關(guān)于匯總vue開源項(xiàng)目的文章,資源非常豐富,不得不感嘆開源社區(qū)的強(qiáng)大。隨便點(diǎn)進(jìn)去看了幾個(gè)UI組件,基本都不是原生的html用法,如果你不懂Vue的組件相關(guān)概念,看到一些“稀奇古怪”的標(biāo)簽寫法,可能會(huì)使用,但肯定無法理解為什么可以這么寫。比如我們隨便找了一個(gè)名叫IView的來看看:
<i-input type="text" :value.sync="formInline.user" placeholder="Username"> <Icon type="ios-person-outline" slot="prepend"></Icon> </i-input>
這樣一段代碼就能得到如下效果:
博主好奇心重,打算一探究竟,今天就和大家一起來看一看這些“古怪”寫法的出處。希望通過本文,讓你有一種“哦,原來是這樣,不過如此嘛!”的感覺!
二、Vue里面的組件基礎(chǔ)知識(shí)
1、組件的概念
官方定義:組件(Component)是 Vue.js 最強(qiáng)大的功能之一。組件可以擴(kuò)展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素, Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以是原生 HTML 元素的形式,以 is 特性擴(kuò)展。
博主理解:Vue里面的組件可以理解為通過對普通html標(biāo)簽的封裝,得到一套獨(dú)立而且可以通用的html標(biāo)簽,我們在頁面里面使用這些標(biāo)簽傳入相應(yīng)的參數(shù)即可調(diào)用封裝好的組件。通過下面這張圖相信可以一目了然。
由普通的html標(biāo)簽form、input、button、label組成了一個(gè)新的元素集合,我們命名為i-form,這個(gè)i-form就是vue里面組件的概念。我們在頁面里面使用<i-form></i-form>時(shí),通過vue的組件渲染機(jī)制,在瀏覽器里面最終就可以顯示成為普通的html標(biāo)簽form、input、button、label。
2、組件原理
通過上圖我們知道,vue里面的組件實(shí)際上就是一些普通html元素的集合。那么,它是如何將這些自定義標(biāo)簽轉(zhuǎn)換為普通html標(biāo)簽的呢?在介紹組件原理之前,還是先來看一個(gè)最簡單的組件實(shí)例。
<div id="app"> <!-- 3. 在Vue實(shí)例里面使用組件--> <b-component></b-component> </div> <script src="Content/vue/dist/vue.js"></script> <script type="text/javascript"> // 1.創(chuàng)建組件構(gòu)造器 var myComponent = Vue.extend({ template: '<div id="bComponent">我是自定義組件的內(nèi)容</div>' }); //2.注冊組件到vue里面 Vue.component('b-component', myComponent) new Vue({ el: '#app', }); </script>
得到效果:
整個(gè)過程不難理解,主要分為三個(gè)大的步驟:
在網(wǎng)上找到一張圖可以清晰地解釋組件的整個(gè)渲染過程。
其實(shí)有時(shí)為了簡便,我們常將1、2步合并,代碼如下:
<div id="app"> <!-- 2. 在Vue實(shí)例里面使用組件--> <b-component></b-component> </div> <script src="Content/vue/dist/vue.js"></script> <script type="text/javascript"> //1.創(chuàng)建組件構(gòu)造器,注冊組件到vue里面 Vue.component('b-component', { template: '<div id="bComponent">我是自定義組件的內(nèi)容</div>' }) new Vue({ el: '#app', }); </script>
得到的結(jié)果和上述相同。
3、組件使用
上述解釋了下組件的定義和原理,關(guān)于組件的簡單實(shí)用,我們主要介紹以下幾個(gè)方面。
(1)組件的作用域
這個(gè)應(yīng)該不難理解,組件分為全局組件和局部組件,也就是說,你可以在頁面上面定義一個(gè)全局組件,頁面上面的任何Vue實(shí)例都可使用;而對于局部組件,是和具體的Vue實(shí)例相關(guān)的,只能在當(dāng)前Vue實(shí)例里面使用組件。還有一點(diǎn)需要說明:組件必須在Vue的實(shí)例里面使用,在Vue實(shí)例之外使用組件無效。通過下面一個(gè)例子即可清晰說明它們的區(qū)別。
<body> <div id="app"> <b-component></b-component> <b-component2></b-component2> </div> <div id="app2"> <b-component></b-component> <b-component2></b-component2> </div> <b-component></b-component> <b-component2></b-component2> <script src="Content/vue/dist/vue.js"></script> <script type="text/javascript"> //定義組件 Vue.component('b-component', { template: '<div id="bComponent">我是全局組件,任何Vue實(shí)例都可使用</div>' }) new Vue({ el: '#app', components: { 'b-component2': { template: '<div id="bComponent">我是局部組件,只能在app這個(gè)div里面使用</div>' } } }); new Vue({ el: '#app2', }); </script> </body>
得到結(jié)果:
(2)組件的傳值
組件實(shí)例的作用域是孤立的。這意味著不能并且不應(yīng)該在子組件的模板內(nèi)直接引用父組件的數(shù)據(jù)??梢允褂?props 把數(shù)據(jù)傳給子組件。這段話怎么理解呢?我們先來看幾個(gè)例子。
靜態(tài)Prop
我們先來看看下面的一段簡單的代碼
<body> <div id="app"> <b-component componentmessage="你好"></b-component> </div> <script src="Content/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('b-component', { template: '<div>{{componentmessage}}</div>', props: ['componentmessage'], }) new Vue({ el: '#app' }); </script> </body>
通過在組件里面使用props屬性,將外部的值傳入組件模板。最終渲染到頁面上面就得到“<div>你好</div>”這么一段html
動(dòng)態(tài)Prop
在多數(shù)情況下,我們在使用Vue實(shí)例的時(shí)候,一般通過data屬性傳入模型,比如
new Vue({ el: '#app', data: { name: 'Jim', Age: '28' } });
這個(gè)時(shí)候,我們的name和age如何傳到組件實(shí)例里面呢?
<body> <div id="app"> <b-component v-bind:my-name="name" v-bind:my-age="Age"></b-component> </div> <script src="Content/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('b-component', { template: '<div>姓名:{{myName}},年齡:{{myAge}}</div>', props: ['myName', 'myAge'], }) new Vue({ el: '#app', data: { name: 'Jim', Age: '28' } }); </script> </body>
得到結(jié)果
需要說明幾點(diǎn):
在使用標(biāo)簽<b-component>的時(shí)候,通過v-bind命令,將Vue實(shí)例里面的name、Age屬性以別名my-name、my-age的形式傳入組件實(shí)例。
為什么my-name、my-age傳到組件里面就變成了['myName', 'myAge']呢?這是因?yàn)樵谧咏M件中定義prop時(shí),使用了camelCase命名法。由于HTML特性不區(qū)分大小寫,camelCase的prop用于特性時(shí),需要轉(zhuǎn)為 kebab-case(短橫線隔開)。
很多情況下,v-bind可以簡寫為冒號(hào)(:),所以上述代碼也可以這么寫:<b-component :my-name="name" :my-age="Age"></b-component>。效果也是一樣。
這里很惡心的還有一點(diǎn),在Props里面定義的必須要使用所謂“駝峰式”的方式來定義變量,否則會(huì)因?yàn)橐粋€(gè)變量名大小寫搞死你。比如props:["myName"]這樣可以正確,但是如果props:["myname"]這樣的話就錯(cuò)誤,使用myname取值會(huì)是undefined。博主第一次玩這個(gè)玩意找了好半天,新手一定注意,大坑,大坑,大坑!慎入!
在封裝組件里面,props屬性使用非常多,更多props用法可參見文檔https://vuefe.cn/v2/guide/components.html
(3)組件的插槽
在使用組件的時(shí)候,我們經(jīng)常需要在組件實(shí)例向組件模板傳入html元素,這個(gè)時(shí)候我們就需要在組件的模板標(biāo)簽里面留一些占位符(俗稱“坑”),然后在具體的組件實(shí)例里面?zhèn)魅霕?biāo)簽來填“坑”,在Vue里面這些“坑”也叫插槽,使用<slot>來解決。對于開發(fā)人員來說,這個(gè)其實(shí)不陌生,從原來的母版頁到現(xiàn)在的layout頁面,基本都是使用的這種原理。
<body> <div id="app"> <b-component> <h2 slot="header">這里可能是一個(gè)頁面標(biāo)題</h2> <h3 slot="content">姓名:{{name}},年齡:{{Age}}</h3> <h2 slot="footer">尾部</h2> </b-component> </div> <template id="slottest"> <div class="container"> <header> <slot name="header"></slot> </header> <main> <slot name="content"></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> </template> <script src="Content/vue/dist/vue.js"></script> <script type="text/javascript"> Vue.component('b-component', { template: '#slottest', }) new Vue({ el: '#app', data: { name: 'Jim', Age: '28' } }); </script> </body>
得到結(jié)果
上述代碼應(yīng)該不難理解,就是一個(gè)“挖坑”和“填坑”的過程。順便要提一筆的是,Vue的組件支持使用<templete>的模式來定義標(biāo)簽?zāi)0澹褂酶屿`活和方便。
三、封裝自己的Component
以上講了這么多,都是關(guān)于Vue里面Component組件的一部分主要知識(shí)點(diǎn),其他還有很多都沒有展開說,因?yàn)檫@方面的文檔也是相當(dāng)豐富,園子里面keepfool的博文關(guān)于Vue組件的部分就介紹得非常詳細(xì),再者,Vue中文文檔也是有很詳細(xì)的用法說明。接下來,博主打算通過幾個(gè)實(shí)例來說明使用組件給我們前端開發(fā)帶來的好處。
1、使用Component封裝bootstrapTable
對于項(xiàng)目里面的表格展示,可以基于Vue可以自己開發(fā)一套,但是說實(shí)話,這個(gè)工程量還是蠻大的,并且如果要做好,要兼容很多表格的功能,從零開始去重復(fù)造輪子實(shí)在是有點(diǎn)太耗時(shí)。博主項(xiàng)目里面大部分的表格用的bootstrapTable組件,于是博主一直在想能不能封裝一套基于Vue的bootstrapTable的用法。網(wǎng)上也找不到類似的封裝示例,大部分使用vue的框架都會(huì)自己去實(shí)現(xiàn)一套自己的表格樣式。于是打算自己動(dòng)手試試,正好也可以熟悉下component的用法。
首先新建一個(gè)js文件命名為vue.bootstrapTable.js。博主直接將代碼貼出來,如果有不完善的地方,希望大家斧正。
(function ($) { //表格初始化的默認(rèn)參數(shù) var defaults = { method: 'get', toolbar: '#toolbar', striped: true, cache: false, pagination: true, }; //注冊bootstrapTable組件 Vue.component('bootstrap-table', { template: '<table></table>', props: { 'tableParam': { type: Object } }, //組件渲染之前 created: function () { //debugger; }, //組件渲染之后 mounted: function () { debugger; var params = $.extend({}, defaults, this.tableParam || {}); this.bootstraptable = $(this.$el).bootstrapTable(params); } }); })(jQuery);
然后再界面上面
<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <link href="Content/bootstrap/css/bootstrap.css" rel="stylesheet" /> <link href="Content/bootstrap-table/bootstrap-table.css" rel="stylesheet" /> </head> <body> <div id="app"> <bootstrap-table :table-param="tableParam"></bootstrap-table> </div> <script src="Content/jquery-1.9.1.min.js"></script> <script src="Content/bootstrap/js/bootstrap.js"></script> <script src="Content/bootstrap-table/bootstrap-table.js"></script> <script src="Content/vue/dist/vue.js"></script> <script src="Content/vue-component/vue.bootstrapTable.js"></script> <script type="text/javascript"> var testData = [ { Name: 'Jim', Age: 30, Remark: '雞母格林' }, { Name: 'Kate', Age: 28, Remark: '凱特' }, { Name: 'Lucy', Age: 20, Remark: '露西' }, { Name: 'Uncle Wang', Age: 45, Remark: '嚴(yán)厲的王老師' } ]; new Vue({ el: '#app', data: { tableParam: { data: testData, columns: [ { field: 'Name', title:'姓名' }, { field: 'Age', title: '年齡' }, { field: 'Remark', title: '備注' }] }, } }); </script> </body>
最后測試結(jié)果:
縱觀這數(shù)十行代碼,基本原來其實(shí)很簡單,通過組件的props功能將<bootstrap-table>實(shí)例中的初始化參數(shù)傳到組件模板里面,然后再組件加載完成之后初始化bootstrapTable,最后將bootstrapTable的實(shí)例給到組件,這樣在就可以通過Vue的實(shí)例通過子組件調(diào)用到當(dāng)前初始化的bootstrapTable對象。
2、封裝select
關(guān)于select的封裝,還是打算基于第三方組件來做。同樣的,我們新建一個(gè)js文件,命名為vue.bootstrapSelect.js,其代碼如下:
(function ($) { $("body").append('<template id="bootstrapSelect">' + '<select class="selectpicker" v-if="myMultiple" v-bind:data-live-search="mySearch" multiple>' + '<option v-for="item in myDatasource" v-bind:value="item.value">{{item.text}}</option>' +'</select>' + '<select class="selectpicker" v-else v-bind:data-live-search="mySearch">' + '<option v-for="item in myDatasource" v-bind:value="item.value">{{item.text}}</option>' +'</select>' + '</template>'); Vue.component('bootstrap-select', { template: '#bootstrapSelect', props: ['myDatasource', 'myMultiple', 'mySearch'], //組件渲染之前 created: function () { }, //組件渲染之后 mounted: function () { } }); })(jQuery);
頁面使用
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <link href="Content/bootstrap/css/bootstrap.css" rel="stylesheet" /> <link href="Content/bootstrap-table/bootstrap-table.css" rel="stylesheet" /> <link href="Content/bootstrap-select/css/bootstrap-select.css" rel="stylesheet" /> </head> <body> <div id="app"> <bootstrap-select :my-datasource="selectOptions.data" :my-multiple="selectOptions.multiple" :my-search="selectOptions.search"> </bootstrap-select> </div> <script src="Content/jquery-1.9.1.min.js"></script> <script src="Content/bootstrap/js/bootstrap.js"></script> <script src="Content/bootstrap-table/bootstrap-table.js"></script> <script src="Content/bootstrap-select/js/bootstrap-select.js"></script> <script src="Content/bootstrap-select/js/i18n/defaults-zh_CN.js"></script> <script src="Content/vue/dist/vue.js"></script> <script src="Content/vue-component/vue.bootstrapSelect.js"></script> <script type="text/javascript"> $(function () { var vm = new Vue({ el: '#app', data: { selectOptions:{ multiple: false,//多選 search: true,//搜索 data: [ { text: "北京市", value: 1 }, { text: "上海市", value: 2 }, { text: "重慶市", value: 3 }, ] } }, }); }); </script> </body> </html>
得到效果:
然后可配置多選,將初始化參數(shù)multiple設(shè)置為true即可。
為什么模板里面會(huì)有兩個(gè)select標(biāo)簽?原因就在于那個(gè)multiple,因?yàn)橹灰獦?biāo)簽里面出現(xiàn)了multiple,select就自動(dòng)多選,把multiple的值設(shè)置為任何屬性都不好使,這不做了一個(gè)if判斷,如果哪位有更好的方法,歡迎指出,不勝感激!
3、查看其他Vue框架源碼
現(xiàn)在再來看文章的開頭那段html
<i-input type="text" :value.sync="formInline.user" placeholder="Username"> <Icon type="ios-person-outline" slot="prepend"></Icon> </i-input>
結(jié)合Vue組件的文檔,其實(shí)上述就是一個(gè)對input標(biāo)簽做的封裝。
當(dāng)然,以上只是component的基礎(chǔ),組件的封裝還得結(jié)合很多其他的東西,要讀懂那些框架的源碼還需要學(xué)習(xí)一些其他知識(shí),但至少通過本文希望能夠讓你了解這些東西的由來。
四、總結(jié)
本篇到此結(jié)束,通過本文,相信你對Vue的component有了一個(gè)大概的了解。接下來如果有時(shí)間將結(jié)合webpack介紹Vue的一些高級(jí)用法。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。