你們好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新......javascript
- github:https://github.com/Daotin/Web
- 微信公衆號:Web前端之巔
- 博客園:http://www.cnblogs.com/lvonve/
- CSDN:https://blog.csdn.net/lvonve/
在這裏我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,期間也會分享一些好玩的項目。如今就讓咱們一塊兒進入 Web 前端學習的冒險之旅吧!css
什麼是組件: 組件的出現,就是爲了拆分 Vue 實例的代碼量的,可以讓咱們以不一樣的組件,來劃分不一樣的功能模塊,未來咱們須要什麼樣的功能,就能夠去調用對應的組件便可;html
組件化和模塊化的不一樣:前端
定義全局組件有三種方式:vue
一、使用 Vue.extend
配合 Vue.component
方法:java
// 1.使用 Vue.extend 來建立全局的Vue組件 var login = Vue.extend({ // 經過 template 屬性,指定了組件要展現的HTML結構 template: '<h1>登陸</h1>' }); // 2.使用 Vue.component('組件的名稱', 建立出來的組件模板對象) Vue.component('login', login); // 3.使用組件 <div id="app"> <!-- 若是要使用組件,直接,把組件的名稱,以 HTML 標籤的形式,引入到頁面中便可 --> <login></login> </div>
注意:git
使用 Vue.component 定義全局組件的時候,組件名稱使用了 駝峯命名(如myLogin),則在引用組件的時候,須要把 大寫的駝峯改成小寫的字母,同時在兩個單詞以前,使用 - 連接(
<my-login></my-login>
);若是不使用駝峯,則直接拿名稱來使用便可;github
固然,上面兩步能夠合成一個步驟完成:微信
Vue.component('login', Vue.extend({ template: '<h1>登陸</h1>' }));
二、直接使用 Vue.component 方法:app
Vue.component('login', { template: '<div><h3>註冊</h3><span>123</span></div>' });
注意:不管是哪一種方式建立出來的組件,組件的 template 屬性指向的模板內容,必須有且只能有惟一的一個根元素,不然會報錯。
三、將模板字符串,定義到 template 標籤中:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="./lib/vue-2.4.0.js"></script> </head> <body> <div id="box"> <!-- 3. 使用組件 --> <mycom></mycom> </div> <!-- 2.在 被控制的 #box 外面,使用 template 元素,定義組件的HTML模板結構 --> <template id="tmp1"> <!-- 仍是須要聽從template 模板內容,必須有且只能有惟一的一個根元素 --> <div> <h3>登陸</h3> <p>p標籤</p> </div> </template> <script> // 1.定義組件 Vue.component('mycom', { template: '#tmp1' }); var vm = new Vue({ el: "#box", data: {}, methods: {} }); </script> </body> </html>
注意:
一、
template: '#tmp1'
是定義模板標籤的 id ,# 別忘寫了。二、被控制的 #box 外面,使用 template 標籤;
三、 template 標籤裏面,仍是聽從只能有惟一的一個根元素的原則。
定義私有組件,就是再VM實例中定義組件。
以下,box中可使用,box2不可使用。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="./lib/vue-2.4.0.js"></script> </head> <body> <div id="box"> <mycom></mycom> </div> <div id="box2"> <mycom></mycom> </div> <template id="temp"> <h3>自定義私有屬性</h3> </template> <script> var vm = new Vue({ el: "#box", data: {}, methods: {}, // 定義私有組件 components: { mycom: { template: '#temp' } } }); var vm2 = new Vue({ el: "#box2", data: {}, methods: {} }); </script> </body> </html>
組件中也能夠有本身的data和methods屬性,能夠傳入template中使用。
特色:
<div id="box2"> <login></login> </div> <template id="temp2"> <div> <input type="button" value="按鈕" @click="myclick"> <h3>自定義私有屬性</h3> <p> {{msg}} </p> </div> </template> <script> Vue.component('login', { template: '#temp2', data: function () { return { msg: '這是組件中的data' } }, methods: { myclick() { console.log("點擊按鈕"); } } }); </script>
咱們在登陸註冊一個網站的時候,常常看到兩個按鈕,一個登陸,一個註冊,若是你沒有帳號的話,須要先註冊才能登陸。咱們在點擊登陸和註冊的時候,網頁會相應的切換,登陸頁面就是登錄組件,註冊頁面就是註冊組件,那麼點擊登陸和註冊,如何實現組件的切換呢?
使用flag
標識符結合v-if
和v-else
切換組件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="./lib/vue-2.4.0.js"></script> </head> <body> <div id="box"> <!-- 給a註冊點擊事件,切換flag狀態 --> <a href="javascript:;" @click.prevent="flag=true">登陸</a> <a href="javascript:;" @click.prevent="flag=false">註冊</a> <!-- 使用v-if v-else切換組件 --> <login v-if="flag"> </login> <register v-else="flag"> </register> </div> <script> Vue.component('login', { template: '<h3>登陸組件</h3>' }); Vue.component('register', { template: '<h3>註冊組件</h3>' }); var vm = new Vue({ el: "#box", data: { flag: true }, methods: {} }); </script> </body> </html>
缺陷:因爲flag的值只有true和false,因此只能用於兩個組件間 的切換,當大於兩個組件的切換就不行了。
使用 component元素的:is
屬性來切換不一樣的子組件
使用 <component :is="componentId"></component>
來指定要切換的組件。
componentId:爲須要顯示的組件名稱,爲一個字符串,可使用變量指定。
componentId: 'login'
// 默認顯示登陸組件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="./lib/vue-2.4.0.js"></script> </head> <body> <div id="box"> <!-- 給a註冊點擊事件,切換flag狀態 --> <a href="javascript:;" @click.prevent="componentId='login'">登陸</a> <a href="javascript:;" @click.prevent="componentId='register'">註冊</a> <component :is="componentId"></component> </div> <script> Vue.component('login', { template: '<h3>登陸組件</h3>' }); Vue.component('register', { template: '<h3>註冊組件</h3>' }); var vm = new Vue({ el: "#box", data: { componentId: 'login' // 默認顯示登陸 }, methods: {} }); </script> </body> </html>
爲組件切換添加過渡:
很簡單,只須要用 transition 將 component 包裹起來便可。
<transition> <component :is="componentId"></component> </transition>
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="./lib/vue-2.4.0.js"></script> <link rel="stylesheet" href="./lib/animate.css"> <style> .loginDiv { width: 200px; height: 200px; background-color: red; } .registerDiv { width: 200px; height: 200px; background-color: blue; } </style> </head> <body> <div id="box"> <!-- 給a註冊點擊事件,切換flag狀態 --> <a href="javascript:;" @click.prevent="componentId='login'">登陸</a> <a href="javascript:;" @click.prevent="componentId='register'">註冊</a> <transition mode="out-in" enter-active-class="animated bounceInRight" leave-active-class="animated bounceOutRight"> <component :is="componentId"></component> </transition> </div> <template id="login"> <div class="loginDiv"> </div> </template> <template id="register"> <div class="registerDiv"> </div> </template> <script> Vue.component('login', { template: '#login' }); Vue.component('register', { template: '#register' }); var vm = new Vue({ el: "#box", data: { componentId: 'login' }, methods: {} }); </script> </body> </html>
mode="out-in"
:能夠設置切換組件的模式爲先退出再進入。
咱們先經過一個例子看看子組件可不能夠直接訪問父組件的數據:
<body> <div id="box"> <mycom></mycom> </div> <template id="temp"> <h3>子組件 --- {{msg}}</h3> </template> <script> var vm = new Vue({ el: "#box", data: { msg: '父組件的msg' }, methods: {}, components: { mycom: { template: '#temp' } } }); </script> </body>
因爲 components 定義的是私有組件,咱們直接在子組件中調用父組件的msg會報錯。
那麼,怎麼讓子組件使用父組件的數據呢?
父組件能夠在引用子組件的時候, 經過 屬性綁定(v-bind:) 的形式, 把須要傳遞給子組件的數據,以屬性綁定的形式,傳遞到子組件內部,供子組件使用 。
<body> <div id="box"> <mycom v-bind:parentmsg="msg"></mycom> </div> <template id="temp"> <h3>子組件 --- 父組件:{{parentmsg}}</h3> </template> <script> var vm = new Vue({ el: "#box", data: { msg: '父組件的msg' }, methods: {}, components: { mycom: { template: "#temp", // 對傳遞給子組件的數據進行聲明,子組件才能使用 props: ['parentmsg'] } } }); </script> </body>
注意:父組件綁定的屬性名稱不能有大寫字母,不然不會顯示,而且在命令行會有提示:
組件data數據和props數據的區別:
案例:發表評論功能
父組件爲評論列表,子組件爲ID,評論者,內容和按鈕的集合,在輸入ID,評論者等內容,而後點擊添加的時候,須要首先獲取子組件的list列表,而後再添加新的列表項到列表中。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="./lib/vue-2.4.0.js"></script> </head> <body> <div id="box"> <mycom :plist="list"></mycom> <ul> <li v-for="item in list" :key="item.id"> ID:{{item.id}} --- 內容:{{item.content}} --- 評論人:{{item.user}} </li> </ul> </div> <template id="tmp1"> <div> <label> ID: <input type="text" v-model="id"> </label> <br> <label> 評論者: <input type="text" v-model="user"> </label> <br> <label> 內容: <textarea v-model="content"></textarea> </label> <br> <!-- 把父組件的數據做爲子組件的函數參數傳入 --> <input type="button" value="添加評論" @click="addContent(plist)"> </div> </template> <script> var vm = new Vue({ el: "#box", data: { list: [{ id: Date.now(), user: 'user1', content: 'what' }, { id: Date.now(), user: 'user2', content: 'are' }] }, methods: {}, components: { mycom: { template: '#tmp1', data: function () { return { id: '', user: '', content: '', } }, methods: { addContent(plist) { plist.unshift({ id: this.id, user: this.user, content: this.content }); } }, props: ['plist'] } } }); </script> </body> </html>
把添加ID,評論人,內容做爲子組件,把列表做爲父組件,而後把添加的數據放到父組件列表上,因爲要獲取到父組件列表的數據,因此必然涉及到父組件向子組件傳值的過程。這裏還經過子組件方法參數來保存父組件的數據到子組件的數據中。
既然父組件能夠向子組件傳遞數據,那麼也能夠向子組件傳遞方法。
<body> <div id="box"> <mycom v-bind:parentmsg="msg" @parentfunc="show"></mycom> </div> <template id="temp"> <div> <input type="button" value="調用父組件方法" @click="sonClick"> <h3>子組件 --- 父組件:{{parentmsg}}</h3> </div> </template> <script> var vm = new Vue({ el: "#box", data: { msg: '父組件的msg' }, methods: { show(data1, data2) { console.log("這是父組件的show方法" + data1 + data2); } }, components: { mycom: { template: "#temp", // 對傳遞給子組件的數據進行聲明,子組件才能使用 props: ['parentmsg'], methods: { sonClick() { // 調用父組件的show方法 this.$emit("parentfunc", 111, 222); } } } } }); </script> </body>
一、
@parentfunc="show"
綁定父組件的show方法。二、
<input type="button" value="調用父組件方法" @click="sonClick">
點擊按鈕調用父組件的show方法三、在 子組件的 sonClick 方法中使用
this.$emit("parentfunc");
來調用父組件的show方法四、父組件的show方法也能夠傳參,在調用的時候,實參從 this.$emit 的第二個參數開始傳入。
五、若是 this.$emit 的第二個參數傳的是子組件的data數據,那麼父組件的方法就能夠得到子組件的數據,這也是把子組件的數據傳遞給父組件的方式。
咱們知道Vue不推薦直接獲取DOM元素,那麼在Vue裏面怎麼獲取DOM及組件元素呢?
咱們呢能夠在元素上使用 ref
屬性來獲取元素。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="./lib/vue-2.4.0.js"></script> </head> <body> <div id="box"> <input type="button" value="獲取元素" @click="getrefs" ref="mybtn"> <h3 ref="myh3">這是H3</h3> <mycom ref="mycom"></mycom> </div> <template id="tmp1"> </template> <script> // 定義組件 Vue.component('mycom', { template: '#tmp1', data: function () { return { msg: '子組件的msg', pmsg: '' } }, methods: { show(data) { console.log('調用子組件的show'); this.pmsg = data; console.log(this.pmsg); }, } }); var vm = new Vue({ el: "#box", data: { parentmsg: '父組件的msg' }, methods: { getrefs() { console.log(this.$refs.myh3); console.log(this.$refs.mycom.msg); this.$refs.mycom.show(this.parentmsg); } } }); </script> </body> </html>
總結:
一、ref 屬性不只能夠獲取DOM元素,也能夠獲取組件(不管全局仍是私有組件)元素。
二、獲取到組件元素後,就能夠獲取組件元素的data數據和methods方法。
三、獲取到組件中的方法後,能夠傳入VM的data數據,就能夠把VM的data數據傳入組件中。