1 <div id="app"> 2 <xz-todo></xz-todo> 3 </div> 4 <!--1. 为每个组件定义HTML 模板,有几个组件,就要创建几个template--> 5 <template id="tplTodo"> 6 <div> 7 <h3>父组件xz-todo: 代办事项列表</h3> 8 <xz-todo-input></xz-todo-input> 9 <!--父要给子tasks(右),绑定在子的tasks属性(左)中--> 10 <xz-todo-list :tasks="tasks"></xz-todo-list> 11 </div> 12 </template> 13 <template id="tplTodoInput"> 14 <div> 15 <h6>子组件xz-todo-input</h6> 16 <input v-model="input" @keyup.13="addFun"><button @click="addFun">添加</button> 17 </div> 18 </template> 19 <template id="tplTodoList"> 20 <div> 21 <h6>子组件xz-todo-list</h6> 22 <ul> 23 <xz-todo-item v-for="(t,i) in tasks" :t="t" :i="i" @remove="removeHandler"> 24 <!--当子组件触发remove时,就自动执行handler--> 25 </xz-todo-item> 26 </ul> 27 </div> 28 </template> 29 <template id="tplTodoItem"> 30 <li> 31 <p>孙子组件xz-todo-item</p> 32 <span>{{t}}</span><button @click="removeFun">x</button> 33 </li> 34 </template> 35 <script> 36 var bus=new Vue();//先建公交车 37 //2. 除全局父组件外,为每个子组件创建对象 38 var xzTodoInput={ 39 template:"#tplTodoInput", 40 data:function(){ 41 return { input:"" } 42 }, 43 methods:{ 44 addFun(){ 45 if(this.input.trim()!==""){ 46 bus.$emit("add",this.input) 47 this.input=""; 48 } 49 } 50 } 51 }; 52 var xzTodoItem={//强调: 子组件对象必须先于父组件定义 53 template:"#tplTodoItem", 54 //因为子想要任务名(显示)和下标(删除) 55 props:["t","i"], 56 methods:{ 57 removeFun(){ 58 if(confirm("是否删除?")) 59 this.$emit("remove",this.i); 60 } 61 } 62 }; 63 var xzTodoList={ 64 template:"#tplTodoList", 65 props:["tasks"],//因为子想要tasks列表 66 components:{ 67 //可用components继续包含更子级组件 68 xzTodoItem 69 }, 70 methods:{ 71 //当remove发生时,自动调用handler,获得子组件传来的i 72 removeHandler(i){ 73 this.tasks.splice(i,1); 74 } 75 }, 76 mounted(){ 77 //this->Vue 78 bus.$on("add",input=>{//必须用=> 79 this.tasks.push(input) 80 }) 81 } 82 }; 83 //3. 定义全局父组件,components中仅包含直接子组件 84 Vue.component("xz-todo",{ 85 template:"#tplTodo", 86 data:function(){ 87 return {//1. 因为整个组件需要一个任务列表,所以: 88 tasks:[] 89 } 90 }, 91 components:{//子组件 92 xzTodoInput,//xz-todo-input 93 xzTodoList //xz-todo-list 94 }, 95 mounted(){//2. 在全局父组件中,加载并保存列表数据 96 this.tasks=["吃饭","睡觉","打豆豆"]; 97 } 98 }) 99 //4. new Vue() 100 new Vue({ 101 el:"#app", 102 data:{} 103 }) 104 </script>