目录
接着VueJS教程2。
13、Vue实例
13.1 动态组件(Tab切换、简化版留言板)
举例1(component标签:是Vue框架自定义的标签,它的用途就是可以动态绑定我们的组件,根据数据的不同更换不同的组件):
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="utf-8"> 6 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 7 <meta http-equiv="Content-Language" content="zh-cn" /> 8 <title>My test page</title> 9 <script src="https://unpkg.com/vue"></script> 10 <style> 11 .tab-button { 12 padding: 6px 10px; 13 border-top-left-radius: 3px; 14 border-top-right-radius: 3px; 15 border: 1px solid #ccc; 16 cursor: pointer; 17 background: #f0f0f0; 18 margin-bottom: -1px; 19 margin-right: -1px; 20 } 21 22 .tab-button:hover { 23 background: #e0e0e0; 24 } 25 26 .tab-button.active { 27 background: #e0e0e0; 28 } 29 30 .tab { 31 border: 1px solid #ccc; 32 padding: 10px; 33 } 34 </style> 35 </head> 36 37 <body> 38 <div id="app"> 39 <button v-for="(tab, index) in tabs" v-bind:key="index" v-bind:class="{'tab-button': current_tab === tab}" 40 @click="current_tab = tab">{{ tab }}</button> 41 42 <component :is="currentTabComponent" class="tab"></component> <!-- currentTabComponent:已注册组件的名字,或一个组件的选项对象 --> 43 </div> 44 45 <script> 46 Vue.component('tab-home', { 47 template: '<div>Home component</div>' 48 }) 49 Vue.component('tab-posts', { 50 template: '<div>Posts component</div>' 51 }) 52 Vue.component('tab-archive', { 53 template: '<div>Archive component</div>' 54 }) 55 56 var app = new Vue({ 57 el: '#app', 58 data: { 59 current_tab: 'Home', 60 tabs: ['Home', 'Posts', 'Archive'] 61 }, 62 computed: { 63 currentTabComponent() { 64 return 'tab-' + this.current_tab.toLowerCase(); 65 } 66 }, 67 }) 68 </script> 69 </body> 70 71 </html>
输出结果:
13.2 使用Vue开发TodoList
举例1:
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="utf-8"> 6 <title>My test page</title> 7 <script src="https://cdn.jsdelivr.net/npm/vue"></script> 8 </head> 9 10 <body> 11 <div id="app"> 12 <input type="text" placeholder="请输入事项" v-model="msg"> 13 <button @click="handleSubmitBtn">提交</button> 14 15 <todo-list v-for="(item, index) in list" :todo_item="item" :todo_index="index" 16 @click-sub-event="handleDelBtn($event)"></todo-list> 17 </div> 18 19 <script> 20 Vue.component("todo-list", { 21 props: ['todo_item', 'todo_index'], 22 template: ` 23 <ul> 24 <li> 25 {{ todo_index }}. {{ todo_item }} 26 <button @click=handleClickSubComp(todo_index)>X</button> 27 </li> 28 </ul> 29 `, 30 data: function () { 31 return { 32 33 } 34 }, 35 methods: { 36 handleClickSubComp: function (index) { 37 this.$emit("click-sub-event", index); 38 } 39 } 40 }); 41 42 var app = new Vue({ 43 el: '#app', 44 data: { 45 msg: "", 46 list: [], 47 }, 48 methods: { 49 handleSubmitBtn: function () { 50 this.list.push(this.msg); 51 this.msg = ''; 52 }, 53 handleDelBtn: function (index) { 54 this.list.splice(index, 1); 55 console.log(index); 56 } 57 } 58 }) 59 </script> 60 </body> 61 62 </html>
输出结果:
举例2(结合 非父子组件之前传值(Bus/总线/发布订阅模式/观察者模式)):
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="utf-8"> 6 <title>My test page</title> 7 <script src="https://cdn.jsdelivr.net/npm/vue"></script> 8 </head> 9 10 <body> 11 <div id="app"> 12 <todo-list-header></todo-list-header> 13 <todo-list-body></todo-list-body> 14 </div> 15 16 <script> 17 Vue.prototype.bus = new Vue(); 18 19 Vue.component("todo-list-header", { 20 props: [], 21 template: ` 22 <div> 23 <input type="text" placeholder="请输入事项" v-model="msg"> 24 <button @click="handleSubmitBtn">提交</button> 25 </div> 26 `, 27 data: function () { 28 return { 29 index: 0, 30 msg: "", 31 } 32 }, 33 methods: { 34 handleSubmitBtn: function () { 35 this.bus.$emit('click-submit-event', this.msg, this.index); 36 this.msg = ''; 37 this.index++; 38 }, 39 }, 40 mounted: function () { 41 42 } 43 }); 44 45 Vue.component("todo-list-body", { 46 props: [], 47 template: ` 48 <ul> 49 <li v-for="(item, idx) in list"> 50 {{ item }} 51 <button @click=handleDelBtn(idx)>X</button> 52 </li> 53 </ul> 54 `, 55 data: function () { 56 return { 57 index: '', 58 list: [], 59 } 60 }, 61 methods: { 62 handleDelBtn: function (idx) { 63 this.bus.$emit("click-delete-event", idx); 64 } 65 }, 66 mounted: function () { 67 var this_ = this; 68 69 this.bus.$on('click-submit-event', function (msg, idx) { 70 this_.list.push(msg); 71 this_.index = idx; 72 }); 73 74 this.bus.$on('click-delete-event', function (idx) { 75 this_.list.splice(idx, 1); 76 console.log(idx); 77 }); 78 } 79 }); 80 81 var app = new Vue({ 82 el: '#app', 83 data: { 84 85 }, 86 methods: { 87 88 } 89 }) 90 </script> 91 </body> 92 93 </html>
输出结果:
举例3(在上述例子基础上进行简化(优化)):
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="utf-8"> 6 <title>My test page</title> 7 <script src="https://cdn.jsdelivr.net/npm/vue"></script> 8 </head> 9 10 <body> 11 <div id="app"> 12 <todo-list-header></todo-list-header> 13 <todo-list-body></todo-list-body> 14 </div> 15 16 <script> 17 Vue.prototype.bus = new Vue(); 18 19 Vue.component("todo-list-header", { 20 props: [], 21 template: ` 22 <div> 23 <input type="text" placeholder="请输入事项" v-model="msg"> 24 <button @click="handleSubmitBtn">提交</button> 25 </div> 26 `, 27 data: function () { 28 return { 29 index: 0, 30 msg: "", 31 } 32 }, 33 methods: { 34 handleSubmitBtn: function () { 35 this.bus.$emit('click-submit-event', this.msg, this.index); 36 this.msg = ''; 37 this.index++; 38 }, 39 }, 40 mounted: function () { 41 42 } 43 }); 44 45 Vue.component("todo-list-body", { 46 props: [], 47 template: ` 48 <ul> 49 <li v-for="(item, idx) in list"> 50 {{ item }} 51 <button @click=handleDelBtn(idx)>X</button> 52 </li> 53 </ul> 54 `, 55 data: function () { 56 return { 57 index: '', 58 list: [], 59 } 60 }, 61 methods: { 62 handleDelBtn: function (idx) { 63 this.list.splice(idx, 1); 64 console.log(idx); 65 } 66 }, 67 mounted: function () { 68 var this_ = this; 69 70 this.bus.$on('click-submit-event', function (msg, idx) { 71 this_.list.push(msg); 72 this_.index = idx; 73 }); 74 } 75 }); 76 77 var app = new Vue({ 78 el: '#app', 79 data: { 80 81 }, 82 methods: { 83 84 } 85 }) 86 </script> 87 </body> 88 89 </html>
输出结果:同上。
14、Vue CLI
14.1 使用vue-cli开发TodoList