官方教程: https://cn.vuejs.org/v2/guidejavascript
let myComponent = Vue.extend({ template : '#my', // 此時的 #my 是id="my"的template標籤 }); // 能夠簡化爲 let myComponent = { template : '#my', data(){ // 此處的data必須是一個函數 } };
// 全局組件: 一次註冊在全部的vue實例中(都可以使用 Vue.component('my-component',{ template : '#my-component', data () { // 此處的data必須是一個函數 }, }); // 局部組件: 只能在某一個vue實例中使用 const vm = new Vue({ 'el' : '#app', components : { 'my-component' : { template : '#my', data() { // 此處的data必須是一個函數 } }, } });
注: 爲了保證各個組件的相互獨立性,全部的組件中的data必須是一個函數html
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue study</title> <script src="../node_modules/vue/dist/vue.js"></script> </head> <body> <!-- templates --> <template id="my"> <div> <p>這是本組件本身的數據: {{selfData}}</p> <p>這是父組件的數據: {{msg}}</p> </div> </template> <!-- /templates --> <!-- 使用組件 --> <div id="app"> <my-component :msg="message"></my-component> </div> <script> // 1.聲明一個組件 let myComponent = Vue.extend({ template: '#my', props: ["msg"], // props 不單單能夠是一個數組,也能夠是一個對象 data() { return { selfData: "hello Vue", }; }, }); /** props 支持的類型========================= 1. 簡單語法 Vue.component('props-demo-simple', { props: ['size', 'myMessage'] }) 2. 對象語法,提供校驗 Vue.component('props-demo-advanced', { props: { // 檢測類型 height: Number, // 檢測類型 + 其餘驗證 age: { type: Number, default: 0, required: true, validator: function (value) { return value >= 0 } } } }); ==================================*/ // 2.在Vue實例中來註冊組件 const vm = new Vue({ el: '#app', data: { message: 'hello world', }, components: { // 註冊一個局部組件 'my-component': myComponent, // 注: 此時必須使用 - 分割單詞,或者所有小寫,不能使用駝峯式寫法 } }); </script> <!-- 父組件 => 子組件: 在子組件中使用父組件的數據 1. 聲明一個組件 2. 註冊組件(全局或者局部組件均可以通訊) 3. 使用組件(my-component), 並在使用時綁定一個屬性 :msg 4. 在子組件中用 props 來獲取綁定的屬性 props : ["msg"], 5. 測試,看是否可以成功傳遞值 --> </body> </html>
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue study</title> <script src="./node_modules/vue/dist/vue.js"></script> </head> <body> <div id="app"> <!-- 使用組件 --> <my-component :msg="message" @custom_event="changeData"></my-component> </div> <!-- templates --> <template id="my"> <div> <p>{{msg}}</p> <p>{{selfData}}</p> <!-- <button @click="$emit('custom_enevt','args')">點我改變父組件的數據</button> --> <!-- 若是以爲這種行內的觸發知足不了複雜的邏輯需求,你也能夠把這個觸發寫到這個組件的方法中 --> <button @click="triggerParent(10)">點我改變父組件的數據</button> </div> </template> <script> // 聲明一個組件 let myComponent = Vue.extend({ template: '#my', props: ["msg"], data() { return { selfData: 'hello Vue', }; }, methods : { triggerParent(val){ // 觸發父組件並傳遞一個參數,此時的val是click調用時傳遞的參數 this.$emit('custom_event', val); }, }, }); const vm = new Vue({ el: '#app', data: { message: 'hello world', }, methods: { changeData (val) { // 把message變成一個隨機數鏈接上子組件傳遞的參數 this.message = val + Math.ceil(Math.random()*100); }, }, components: { // 註冊一個局部組件 'my-component': myComponent, } }); </script> <!-- 因爲vue爲了保證各個組件的獨立性,因此將各個組件的數據流向作成那單向數據流, 而這樣,就只能父組件改變子組件的內容,而不能子組件改變父組件的內容 因此爲了可以在子組件中改變父組件的數據,只有使用自定義事件系統 1. 聲明一個組件 let myComponent = Vue.extend({...}); 2. 註冊一個組件(全局,局部都行) 3. 使用組件 3.1) 綁定一個屬性 :msg="message" 子組件能夠用 props 來獲取綁定的屬性 3.2) 綁定一個自定義事件 @custom_event="changeData" 此時的custom_event是事件名稱,changeData是methods中的方法 3.3) 子類想改變父類的數據,能夠用$emit('事件名稱')來觸發父組件的事件,而後由父組件決定改變的規則,從而達到單向數據流的目的 3.4) 觸發父類自定義事件 3.4.1) 行內觸發 <button @click="$emit('custom_enevt','args')">點我改變父組件的數據</button> 此時的args是參數 3.4.2) 使用方法觸發 <button @click="triggerParent(10)">點我改變父組件的數據</button> methods : { triggerParent(val){ // 觸發父組件並傳遞一個參數,此時的val是click調用時傳遞的參數 this.$emit('custom_event', val); }, } --> </body> </html>
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue組件嵌套</title> <script src="./node_modules/vue/dist/vue.js"></script> <style> .cmpt1, .cmpt2 { color: #ffffff; padding: 15px; } .cmpt1 { background: #272822; } .cmpt2 { background: #265a88; } </style> </head> <body> <div id="app"> <my-component @custom_event="changeData" :msg="message"></my-component> </div> <!-- templates --> <template id="my"> <div> <one :msg="msg" :name="name"></one> <two :msg="msg" @test_event="changeMess"></two> </div> </template> <!--one--> <template id="one"> <div class="cmpt1"> <p>這是組件1</p> <p>這是二級傳遞: hello {{msg}}!!! </p> <p>這是三級傳遞: what's your name? my name is {{name}}</p> </div> </template> <!--two--> <template id="two"> <div class="cmpt2"> <p>這是組件2</p> <p> hello {{msg}} </p> <p> <button @click="changePrentData(10)">點我改變父組件數據</button> </p> </div> </template> <script> // 聲明一個子組件 let one = Vue.extend({ template: '#one', props: ["msg", "name"], }); // 聲明一個子組件 let two = Vue.extend({ template: '#two', props: ["msg"], methods: { changePrentData(val) { let m = Math.ceil(Math.random() * val); // this.$emit('custom_event', m); this.$emit('test_event', m); } }, }); // 聲明一個父組件 let myComponent = Vue.extend({ template: '#my', props: ["msg"], methods: { changeMess(val){ this.$emit('custom_event',val); } }, components: { 'one': one, 'two': two }, data() { return { name: 'Tom', }; } }); const vm = new Vue({ el: '#app', data: { message: 'world', }, methods: { changeData(val) { this.message = "這是改變後的message,喜歡嗎? " + val + " 是點擊是傳遞的參數"; } }, components: { // 註冊一個局部組件 'my-component': myComponent, } }); </script> <!-- 組件嵌套時,最底層的組件想要與最頂層的組件通訊,必須一層一層向上傳遞 --> </body> </html>
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>蒙版效果</title> <style> * { margin: 0; padding: 0; } html, body { width: 100%; height: 3000px; /* 爲了測試滾動 */ } #alert-panel { width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); position: absolute; top: 0; left: 0; /*display: none;*/ } #alert-panel #login { width: 500px; height: 300px; background: #000000; position: fixed; top: 50%; left: 50%; margin-left: -250px; margin-top: -180px; } #close-alert-panel { background: #000; color: #ffffff; border: none; width: 30px; height: 30px; float: right; } #close-alert-panel:hover { background: #f00; } </style> <!--javascript--> <script src="./node_modules/vue/dist/vue.js"></script> </head> <body> <div id="app"> <!-- 當點擊button的時候,顯示模態框,在模態框中點擊關閉按鈕時,關閉模態框 --> <button id="btn" @click="showDialog">點擊登錄</button> <modal :is-hide-dialog="!isHide" @close="closeModal"></modal> </div> <template id="dialog"> <div id="alert-panel" v-show="isHideDialog"> <div id="login"> <button id="close-alert-panel" @click="$emit('close')">×</button> </div> </div> </template> <script> // 聲明一個組件 let modal = Vue.extend({ template: '#dialog', props: ["isHideDialog"], }); const vm = new Vue({ el: '#app', data: { isHide: true, }, methods: { showDialog() { this.isHide = false; }, closeModal() { this.isHide = true; } }, components: { 'modal': modal } }); </script> </body> </html>
注: 若是ref放在組件上,那麼經過$refs拿到的不是組件的dom而是這個組件vue
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue study</title> <script src="./node_modules/vue/dist/vue.js"></script> </head> <body> <div id="app"> <!-- 注: 若是ref放在組件上,那麼經過$refs拿到的不是組件的dom而是這個組件 --> <load ref="load"></load> </div> <!--templates--> <template id="load"> <div v-if="isShow"> <p>玩命加載中...</p> </div> </template> <!-- JavaScript --> <script> let load = Vue.extend({ template: '#load', data () { return { isShow: true, } }, methods: { hide(){ this.isShow = false; console.log("我被調用了,這個組件已經被隱藏了"); } }, }); const vm = new Vue({ el: '#app', components: { "load": load, }, mounted () { // 當vm實例掛載的時候,就調用子組件的方法,隱藏加載組件 this.$refs.load.hide(); } }); </script> </body> </html>
默認在子組件中不能修改父組件傳遞的值,若是非要
加工父組件傳遞過來的數據,可使用 computed 屬性或者 data()
來加工父組件傳遞的值,此種方式雖然可以加工了父組件
傳遞的數據,可是不會改變父組件的數據,保證了各個組件的獨立性(單向數據流)java
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue study</title> <script src="./node_modules/vue/dist/vue.js"></script> </head> <body> <div id="app"> <my-comp :name="message"></my-comp> </div> <!--templates--> <template id="my"> <div> <p>父組件原數據: {{name}}</p> <p>改變後的數據: {{myName}}</p> <p>改變後的數據: {{myName2}}</p> </div> </template> <!-- JavaScript --> <script> // make a component let myComponent = Vue.extend({ template: '#my', props: ["name"], // 要求: 在子組件中,將父組件傳遞的值拼接一個隨機數 // 方式一:使用計算屬性來改變父組件傳遞的值 computed:{ myName(){ return this.name + Math.random(); } }, // 方式二:使用data()方法來改變父組件傳遞的值(局部變量) data(){ return { "myName2" :this.name + Math.random(), } }, }); const vm = new Vue({ el: '#app', data: { message: 'hello world', }, components: { // register a local component "my-comp": myComponent, }, }); </script> </body> </html>