JS元件系列——又一款MVVM元件:Vue(二:構建自己的Vue元件)
前言:轉眼距離上篇 JS元件系列——又一款MVVM元件:Vue(一:30分鐘搞定前端增刪改查) 已有好幾個月了,今天打算將它撿起來,發現好久不用,Vue相關技術點都生疏不少。經過這幾個月的時間,Vue的發展也是異常迅猛,不過這好像和博主都沒什麼太大的關係,博主還是老老實實研究自己的技術吧。技術之路還很長,且行且研究吧。
一、為什麼元件很重要
前兩天,看到一篇關於 彙總vue開源專案 的文章,資源非常豐富,不得不感嘆開源社群的強大。隨便點進去看了幾個UI元件,基本都不是原生的html用法,如果你不懂Vue的元件相關概念,看到一些“稀奇古怪”的標籤寫法,可能會使用,但肯定無法理解為什麼可以這麼寫。比如我們隨便找了一個名叫
<i-input type="text" :value.sync="formInline.user" placeholder="Username"> <Icon type="ios-person-outline" slot="prepend"></Icon> </i-input>
這樣一段程式碼就能得到如下效果:
博主好奇心重,打算一探究竟,今天就和大家一起來看一看這些“古怪”寫法的出處。希望通過本文,讓你有一種“哦,原來是這樣,不過如此嘛!”的感覺!
二、Vue裡面的元件基礎知識
1、元件的概念
官方定義:元件(Component)是 Vue.js 最強大的功能之一。元件可以擴充套件 HTML 元素,封裝可重用的程式碼。在較高層面上,元件是自定義元素, Vue.js 的編譯器為它新增特殊功能。在有些情況下,元件也可以是原生 HTML 元素的形式,以 is 特性擴充套件。
博主理解:Vue裡面的元件可以理解為通過對普通html標籤的封裝,得到一套獨立而且可以通用的html標籤,我們在頁面裡面使用這些標籤傳入相應的引數即可呼叫封裝好的元件。通過下面這張圖相信可以一目瞭然。
由普通的html標籤form、input、button、label組成了一個新的元素集合,我們命名為i-form,這個i-form就是vue裡面元件的概念。我們在頁面裡面使用<i-form></i-form>時,通過vue的元件渲染機制,在瀏覽器裡面最終就可以顯示成為普通的html標籤form、input、button、label。
2、元件原理
通過上圖我們知道,vue裡面的元件實際上就是一些普通html元素的集合。那麼,它是如何將這些自定義標籤轉換為普通html標籤的呢?在介紹元件原理之前,還是先來看一個最簡單的元件例項。
<div style="text-align:center;margin-top:200px;" id="app"> <!-- 3. 在Vue例項裡面使用元件--> <b-component></b-component> </div> <script src="Content/vue/dist/vue.js"></script> <script type="text/javascript"> // 1.建立元件構造器 var myComponent = Vue.extend({ template: '<div id="bComponent">我是自定義元件的內容</div>' }); //2.註冊元件到vue裡面 Vue.component('b-component', myComponent) new Vue({ el: '#app', }); </script>
得到效果:
整個過程不難理解,主要分為三個大的步驟:
- 定義一個元件構造器,宣告元件要渲染的html內容
- 將元件構造器註冊到Vue的元件系統裡面,使其成為Vue的一個元件,給元件取一個名稱,比如b-component
- 在Vue的例項裡面使用元件。因為上面兩步定義了Vue的元件,既然是Vue的元件,那麼要使用元件,首先得有一個Vue的例項,元件必須要在Vue的例項裡面使用。
在網上找到一張圖可以清晰地解釋元件的整個渲染過程。
其實有時為了簡便,我們常將1、2步合併,程式碼如下:
<div style="text-align:center;margin-top:200px;" id="app"> <!-- 2. 在Vue例項裡面使用元件--> <b-component></b-component> </div> <script src="Content/vue/dist/vue.js"></script> <script type="text/javascript"> //1.建立元件構造器,註冊元件到vue裡面 Vue.component('b-component', { template: '<div id="bComponent">我是自定義元件的內容</div>' }) new Vue({ el: '#app', }); </script>
得到的結果和上述相同。
3、元件使用
上述解釋了下元件的定義和原理,關於元件的簡單實用,我們主要介紹以下幾個方面。
(1)元件的作用域
這個應該不難理解,元件分為全域性元件和區域性元件,也就是說,你可以在頁面上面定義一個全域性元件,頁面上面的任何Vue例項都可使用;而對於區域性元件,是和具體的Vue例項相關的,只能在當前Vue例項裡面使用元件。還有一點需要說明:元件必須在Vue的例項裡面使用,在Vue例項之外使用元件無效。通過下面一個例子即可清晰說明它們的區別。
<body> <div style="text-align:center;margin-top:50px;" id="app"> <b-component></b-component> <b-component2></b-component2> </div> <div style="text-align:center;margin-top:50px;" 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例項都可使用</div>' }) new Vue({ el: '#app', components: { 'b-component2': { template: '<div id="bComponent">我是區域性元件,只能在app這個div裡面使用</div>' } } }); new Vue({ el: '#app2', }); </script> </body>
得到結果:
(2)元件的傳值
元件例項的作用域是孤立的。這意味著不能並且不應該在子元件的模板內直接引用父元件的資料。可以使用 props 把資料傳給子元件。這段話怎麼理解呢?我們先來看幾個例子。
- 靜態Prop
我們先來看看下面的一段簡單的程式碼
<body> <div style="text-align:center;margin-top:50px;" 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
- 動態Prop
在多數情況下,我們在使用Vue例項的時候,一般通過data屬性傳入模型,比如
new Vue({ el: '#app', data: { name: 'Jim', Age: '28' } });
這個時候,我們的name和age如何傳到元件例項裡面呢?
<body> <div style="text-align:center;margin-top:50px;" 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>
得到結果
需要說明幾點:
- 在使用標籤<b-component>的時候,通過v-bind命令,將Vue例項裡面的name、Age屬性以別名my-name、my-age的形式傳入元件例項。
- 為什麼my-name、my-age傳到元件裡面就變成了['myName', 'myAge']呢?這是因為在子元件中定義prop時,使用了camelCase命名法。由於HTML特性不區分大小寫,camelCase的prop用於特性時,需要轉為 kebab-case(短橫線隔開)。
- 很多情況下,v-bind可以簡寫為冒號(:),所以上述程式碼也可以這麼寫: <b-component :my-name="name" :my-age="Age"></b-component> 。效果也是一樣。
- 這裡很噁心的還有一點,在Props裡面定義的必須要使用所謂“駝峰式”的方式來定義變數,否則會因為一個變數名大小寫搞死你。比如props:["myName"]這樣可以正確,但是如果props:["myname"]這樣的話就錯誤,使用myname取值會是undefined。博主第一次玩這個玩意找了好半天,新手一定注意,大坑,大坑,大坑!慎入!
(3)元件的插槽
在使用元件的時候,我們經常需要在元件例項向元件模板傳入html元素,這個時候我們就需要在元件的模板標籤裡面留一些佔位符(俗稱“坑”),然後在具體的元件例項裡面傳入標籤來填“坑”,在Vue裡面這些“坑”也叫插槽,使用<slot>來解決。對於開發人員來說,這個其實不陌生,從原來的母版頁到現在的layout頁面,基本都是使用的這種原理。
<body> <div style="text-align:center;margin-top:50px;" id="app"> <b-component> <h1 slot="header">這裡可能是一個頁面標題</h1> <h2 slot="content">姓名:{{name}},年齡:{{Age}}</h2> <h1 slot="footer">尾部</h1> </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>
得到結果
上述程式碼應該不難理解,就是一個“挖坑”和“填坑”的過程。順便要提一筆的是,Vue的元件支援使用<templete>的模式來定義標籤模板,使用更加靈活和方便。
三、封裝自己的Component
以上講了這麼多,都是關於Vue裡面Component元件的一部分主要知識點,其他還有很多都沒有展開說,因為這方面的文件也是相當豐富,園子裡面keepfool的博文關於Vue元件的部分就介紹得非常詳細,再者,Vue中文文件也是有很詳細的用法說明。接下來,博主打算通過幾個例項來說明使用元件給我們前端開發帶來的好處。
1、使用Component封裝bootstrapTable
對於專案裡面的表格展示,可以基於Vue可以自己開發一套,但是說實話,這個工程量還是蠻大的,並且如果要做好,要相容很多表格的功能,從零開始去重複造輪子實在是有點太耗時。博主專案裡面大部分的表格用的bootstrapTable元件,於是博主一直在想能不能封裝一套基於Vue的bootstrapTable的用法。網上也找不到類似的封裝示例,大部分使用vue的框架都會自己去實現一套自己的表格樣式。於是打算自己動手試試,正好也可以熟悉下component的用法。
首先新建一個js檔案命名為vue.bootstrapTable.js。博主直接將程式碼貼出來,如果有不完善的地方,希望大家斧正。
(function ($) { //表格初始化的預設引數 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: '嚴厲的王老師' } ]; new Vue({ el: '#app', data: { tableParam: { data: testData, columns: [ { field: 'Name', title:'姓名' }, { field: 'Age', title: '年齡' }, { field: 'Remark', title: '備註' }] }, } }); </script> </body>
最後測試結果:
縱觀這數十行程式碼,基本原來其實很簡單,通過元件的props功能將<bootstrap-table>例項中的初始化引數傳到元件模板裡面,然後再元件載入完成之後初始化bootstrapTable,最後將bootstrapTable的例項給到元件,這樣在就可以通過Vue的例項通過子元件呼叫到當前初始化的bootstrapTable物件。
2、封裝select
關於select的封裝,還是打算基於第三方元件來做。同樣的,我們新建一個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>
得到效果:
然後可配置多選,將初始化引數multiple設定為true即可。
為什麼模板裡面會有兩個select標籤?原因就在於那個multiple,因為只要標籤裡面出現了multiple,select就自動多選,把multiple的值設定為任何屬性都不好使,這不做了一個if判斷,如果哪位有更好的方法,歡迎指出,不勝感激!
3、檢視其他Vue框架原始碼
現在再來看文章的開頭那段html
<i-input type="text" :value.sync="formInline.user" placeholder="Username"> <Icon type="ios-person-outline" slot="prepend"></Icon> </i-input>
結合Vue元件的文件,其實上述就是一個對input標籤做的封裝。
當然,以上只是component的基礎,元件的封裝還得結合很多其他的東西,要讀懂那些框架的原始碼還需要學習一些其他知識,但至少通過本文希望能夠讓你瞭解這些東西的由來。
四、總結
本篇到此結束,通過本文,相信你對Vue的component有了一個大概的瞭解。接下來如果有時間將結合webpack介紹Vue的一些高階用法。
最近打算做點自己的東西出來,將部落格裡面的一些好的技術(包括vue)融合進去。有專案合作的小夥伴趕快聯絡博主吧!
歡迎各位轉載,但是未經作者本人同意,轉載文章之後必須在文章頁面明顯位置給出作者和原文連線,否則保留追究法律責任的權利
相關推薦
JS元件系列——又一款MVVM元件:Vue(一:30分鐘搞定前端增刪改查)
正文 前言:關於Vue框架,好幾個月之前就聽說過,瞭解一項新技術之後,總是處於觀望狀態,一直在猶豫要不要系統學習下。正好最近有點空,就去官網瞭解了下,看上去還不錯的一個元件,就抽空研究了下。最近園子裡vue也確實挺火,各種入門博文眼花繚亂,博主也不敢說寫
JS元件系列——又一款MVVM元件:Vue(二:構建自己的Vue元件)
前言:轉眼距離上篇 JS元件系列——又一款MVVM元件:Vue(一:30分鐘搞定前端增刪改查) 已有好幾個月了,今天打算將它撿起來,發現好久不用,Vue相關技術點都生疏不少。經過這幾個月的時間,Vue的發展也是異常迅猛,不過這好像和博主都沒什麼太大的關係,博主還是老老實實研究自己的技術吧。技術之路還很長,且行
C#元件系列——又一款日誌元件:Elmah的學習和分享
前言:好久沒動筆了,都有點生疏,12月都要接近尾聲,可是這月連一篇的產出都沒有,不能壞了“規矩”,今天還是來寫一篇。最近個把月確實很忙,不過每天早上還是會抽空來園子裡逛逛。一如既往,園子裡每年這個時候都有大把的年終總結、回憶過去展望未來之類的文章。博主是沒時間寫總結了,要學的東西太多。關於Vue的系列一定要抽
C#元件系列——又一款Excel處理神器Spire.XLS,你值得擁有(二)
前言:上篇 C#元件系列——又一款Excel處理神器Spire.XLS,你值得擁有 介紹了下元件的兩個功能,說不上特色,但確實能解決我們專案中的一些實際問題,這兩天繼續研究了下這個元件,覺得有些功能用起來還是挺方便的,這篇繼續來看看Spire.XLS的一些其他功能,說不定有你需要的呢~~ 一、基礎入門
C#元件系列——又一款Excel處理神器Spire.XLS,你值得擁有
前言:最近專案裡面有一些對Excel操作的需求,博主想都沒想,NPOI唄,簡單、開源、免費,大家都喜歡!確實,對於一些簡單的Excel匯入、匯出、合併單元格等,它都沒啥太大的問題,但是這次的需求有兩點是NPOI搞不定的: 匯入Excel後,需要切割Excel的Sheet頁,然後每個Sheet頁單獨生成一
JS元件系列——表格元件神器:bootstrap table(二:父子表和行列調序)
前言:上篇 JS元件系列——表格元件神器:bootstrap table 簡單介紹了下Bootstrap Table的基礎用法,沒想到討論還挺熱烈的。有園友在評論中提到了父子表的用法,今天就結合Bootstrap table的父子表和行列調序的用法再來介紹下它稍微高階點的用法
C#進階系列——一步一步封裝自己的HtmlHelper元件:BootstrapHelper(三:附原始碼)
前言:之前的兩篇封裝了一些基礎的表單元件,這篇繼續來封裝幾個基於bootstrap的其他元件。和上篇不同的是,這篇的有幾個元件需要某些js檔案的支援。 BootstrapHelper系列文章目錄 一、NumberBoxExtensions NumberBoxExtensions是一個基於boot
C#進階系列——一步一步封裝自己的HtmlHelper元件:BootstrapHelper(二)
前言:上篇介紹了下封裝BootstrapHelper的一些基礎知識,這篇繼續來完善下。參考HtmlHelper的方式,這篇博主先來封裝下一些常用的表單元件。關於BootstrapHelper封裝的意義何在,上篇評論裡面已經討論得太多,這裡也不想過多糾結。總之一句話:凡事有得必有失,就看你怎麼去取捨。有興趣的可
JS元件系列——Bootstrap Table 表格行拖拽(二:多行拖拽)
前言:前天剛寫了篇JS元件系列——Bootstrap Table 表格行拖拽,今天接到新的需要,需要在之前表格行拖拽的基礎上能夠同時拖拽選中的多行。博主用了半天時間研究了下,效果是出來了,但是感覺不盡如人意。先把它分享出來,以後想到更好的辦法再優化吧。 一、效果展示 1、拖動前 2、拖動中
android黑科技系列——破解一款永久免費網絡訪問工具
大神 oot 有效期 發布 前言 expired 日誌信息 轉折 expire 一、前言 因為最近個人需要,想在手機上使用“高級搜索”,但是找了一圈發現都是需要收費的網絡工具,奈何我沒錢,所以只能通過專業技能弄一個破解版的。 二、應用分析 下面
android黑科技系列——爆破一款應用的簽名驗證問題
equal 沒有 term 通過 攻防 都在 都是 什麽 tac 一、前言 在之前的文章中說過Android中的安全和破解是相輔相成的,為了防止被破解,很多應用做了一些防護策略,但是防護策略也是分等級,一般簡單的策略就是混淆代碼和簽名校驗,而對於簽名校驗很多應用都是會做的
Via瀏覽器 v3.4.5 又一款經典簡潔的安卓瀏覽器
Via瀏覽器是由國內開發者開發的一款安卓平臺上的極簡瀏覽器,它追求極簡,是極客之選。Via瀏覽器以極客思維為主線,化繁為簡,簡化過程,提升搜尋與瀏覽的效率,注重瀏覽體驗,乾淨利落,簡約不簡單。 小體積的瀏覽器讓每個安卓機型都可以輕鬆駕馭。麻雀雖小五臟俱全,Via瀏覽器常用功能一應俱全,對於高階的
又一款好用的百度網盤免費下載不限速
之前我再某寶購買了一個百度網盤下載檔案不限速神器!一直用到現在,感覺非常好用! 免費推薦給大家使用!本人親測,無毒。下載不限速,下載大檔案必備。 https://download.csdn.net/download/aaa8086/10783779 無需安裝,電腦版,不支援移動版。個人覺
又一款牛逼哄哄的日曆外掛jeDate橫空出世
原文:http://www.jayui.com/jedate/index.html 下載:http://download.csdn.net/detail/cometwo/9393326 選擇理由 jeDate除了包含日期範圍限制、開始日期設定、自定義日期格式、時間戳轉換、當天的前
SpeedPan 速盤 又一款百度網盤滿速下載工具利器
速盤是一款由吾愛破解論壇會員“菩提葉”製作的度盤高速下載工具。支援百度網盤網路資源搜尋並下載,登陸我的網盤賬戶可以下載網盤檔案,還能離線下載。不過安全起見建議登入小號。 1、大家可以登入速盤網站http
又一款linux提權輔助工具 – Linux Exploit Suggester
sys 查找 udev dip name 零基礎 article cal 大神 https://github.com/PenturaLabs/Linux_Exploit_Suggester Linux_Exploit_Suggester是一款根據操作系統版本號自動查找
又一款開源圖示庫 CSS.GG,值得一用
![](https://imgkr.cn-bj.ufileos.com/f819ad89-839d-409d-9a18-3ccd463814e8.png) 嗨,我是 `Martin`,也叫老王,今天推薦一款好用的開源圖示庫。 我們平常找圖示往往會去 [`iconfont`](https://www.ico
郵件黑名單系列文章一 : 如何刪除被Office 365(微軟郵件伺服器)列入黑名單的郵件IP?
郵件伺服器黑名單分兩種: 1. 第三方公開的DNSBL(域名系統黑名單,也稱為DNSBL或DNS黑名單)如http://www.dnsbl.info/ ,一但你被該組織列入黑名單,會導致引用該黑名單的ESP郵件服務商阻止你的發信。2. ESP自己的反垃圾郵箱系統,識別你為垃圾郵件傳送者,會把你
設計一款c#自動程式碼生成器 (1)
1,構思配置驅動檔案生成 網上自動化指令碼生成的思路是 1)設定好對應的模板 2)讀取資料庫對應的檔案 3)根據模板對應的欄位替換生成 模板》讀取資料》生成對應檔案 為什麼會有做自動化指令碼的想法,是因為工作中發現protobuf 這個工具可以自動編譯根據伺服器生成對應的cs檔案 所以我這裡想仿
一款好看的Sublime Text淺色主題:Ayu大作
上一篇分享的VS Code的文中,介面也是淺色主題,也是Ayu作品。下面看一下Sublime Text中的Ayu淺色主題 不錯吧。 如何下載? 首選項——外掛控制——安裝外掛或者ctrl+shift+P 搜尋“ayu” Prefer