Vue学习:使用组件改造ToDoList与组件间的传值
一、原本的ToDoList
每一个li可以当作页面的一个部分,便可以拆开来编写,原本这里是利用v-for循环li标签来显示的,可以将li标签组件化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="inputValue"/>
<button v-on:click="handleBtnClick">提交</button>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
</body>
<script>
var app = new Vue({
el:'#app',
data:{
list:[],
inputValue:''
},
methods:{
handleBtnClick:function(){
this.list.push(this.inputValue),
this.inputValue=''
}
}
})
</script>
</html>
二、组件化改造ToDoList
2.1 定义全局组件
vue.component定义的是全局组件,组件名称是TodoItem,内容是li标签
//Vue定义全局组件
Vue.component("TodoItem",{
template:"<li>todo item</li>"
})
2.2 代替li标签
每点一次提交,都会多一次< li >todo item< /li >显示在页面,因为我们定义的组件名称是TodoItem,所以将大写的T和I用t和i代替,但是后面的驼峰都需要接一个-符号
<ul>
<!--<li v-for="item in list">{{item}}</li>-->
<todo-item v-for="item in list"></todo-item>
</ul>
2.3 v-bind传值
我们上面2.2中li标签内容只是显示todo item,在相对于我们外层容器div="app"来说,我们定义的组件是子组件,所以需要传递内容给子组件
这里便需要用到v-bind,这里将list每一项内容赋值给item,再把item利用v-bind的形式传递给todo-item组件,利用content来传值,所以需要在组件中去接收,接收父组件传值的需要定义props
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="inputValue"/>
<button v-on:click="handleBtnClick">提交</button>
<ul>
<!--<li v-for="item in list">{{item}}</li>-->
<!--将list每一项内容赋值给item,再把item利用v-bind的形式传递给todo-item组件,利用content来传-->
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
</ul>
</div>
</body>
<script>
//Vue定义全局组件
Vue.component("TodoItem",{
//props代表从父组件接收内容
props:['content'],
template:"<li>{{content}}</li>"
})
var app = new Vue({
el:'#app',
data:{
list:[],
inputValue:''
},
methods:{
handleBtnClick:function(){
this.list.push(this.inputValue),
this.inputValue=''
}
}
})
</script>
</html>
2.4 局部组件
利用var定义一个对象,这里便是一个局部组件,然后再父组件里面注册
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="inputValue"/>
<button v-on:click="handleBtnClick">提交</button>
<ul>
<!--<li v-for="item in list">{{item}}</li>-->
<!--将list每一项内容赋值给item,再把item利用v-bind的形式传递给todo-item组件,利用content来传-->
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
</ul>
</div>
</body>
<script>
//定义一个对象,这个就是一个局部组件
var TodoItem = {
props:['content'],
template:"<li>{{content}}</li>"
}
var app = new Vue({
el:'#app',
//注册局部组件
components:{
TodoItem:TodoItem
},
data:{
list:[],
inputValue:''
},
methods:{
handleBtnClick:function(){
this.list.push(this.inputValue),
this.inputValue=''
}
}
})
</script>
</html>
三、组件间的传值
3.1 给子组件的li标签绑定事件,$emit向外触发事件
v-on:click的简写为@click,然后handleItemClick需要写在子组件的methods中,由于数据放在父组件中,利用$emit向外触发事件,父组件创建子组件的时候监听delete事件
var TodoItem = {
props:['content','index'],
template:"<li @click='handleItemClick'>{{content}}</li>",
methods:{
handleItemClick:function(){
this.$emit("delete",this.index);
}
}
}
<ul>
<todo-item v-bind:content="item"
v-for="item in list"
@delete="handleItemDelete">
</todo-item>
</ul>
var app = new Vue({
el:'#app',
//注册局部组件
components:{
TodoItem:TodoItem
},
data:{
list:[],
inputValue:''
},
methods:{
handleBtnClick:function(){
this.list.push(this.inputValue),
this.inputValue=''
},
handleItemDelete:function(index){
//父组件监听的delete事件
}
}
})
3.2 父组件handleItemDelete改变list
向子组件传递下标,利用v-bind传递值给子组件
<ul>
<todo-item v-bind:content="item"
v-bind:index="index"
v-for="(item,index) in list"
@delete="handleItemDelete">
</todo-item>
</ul>
子组件接收下标,$emit也传递index参数给父组件
var TodoItem = {
props:['content','index'],
template:"<li @click='handleItemClick'>{{content}}</li>",
methods:{
handleItemClick:function(){
this.$emit("delete",this.index);
}
}
}
在handleItemDelete进行处理,splice进行删除list里面的数据
var app = new Vue({
el:'#app',
//注册局部组件
components:{
TodoItem:TodoItem
},
data:{
list:[],
inputValue:''
},
methods:{
handleBtnClick:function(){
this.list.push(this.inputValue),
this.inputValue=''
},
handleItemDelete:function(index){
this.list.splice(index,1)
}
}
})
3.3 完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="inputValue"/>
<button v-on:click="handleBtnClick">提交</button>
<ul>
<todo-item v-bind:content="item"
v-bind:index="index"
v-for="(item,index) in list"
@delete="handleItemDelete">
</todo-item>
</ul>
</div>
</body>
<script>
//定义一个对象,这个就是一个局部组件
var TodoItem = {
props:['content','index'],
template:"<li @click='handleItemClick'>{{content}}</li>",
methods:{
handleItemClick:function(){
this.$emit("delete",this.index);
}
}
}
var app = new Vue({
el:'#app',
//注册局部组件
components:{
TodoItem:TodoItem
},
data:{
list:[],
inputValue:''
},
methods:{
handleBtnClick:function(){
this.list.push(this.inputValue),
this.inputValue=''
},
handleItemDelete:function(index){
this.list.splice(index,1)
}
}
})
</script>
</html>