利用jQuery实现todolist
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.jquery.com/jquery-3.4.1.js"></script>
<title>Document</title>
</head>
<body>
<div>
<input id="input" type="text">
<button id="btn">提交</button>
<ul id="list"></ul>
</div>
<script>
// MVP模式
function Page() {
}
$.extend(Page.prototype,{
init: function () {
this.bindEvents()
},
bindEvents:function () {
var btn = $('#btn')
btn.on('click',$.proxy(this.handleBtnClick,this))
},
handleBtnClick: function () {
var inputElement = $("#input");
var inputValue = $("#input").val();
var ulElem = $("#list");
ulElem.append('<li>'+ inputValue+'</li>');
inputElement.val('');
}
})
var page=new Page();
page.init();
</script>
</body>
</html>
直接引入vue实现的简单todolist
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div id="app">
<!-- v-model数据的双向绑定 ,input框内容和inputValue
其中之一变了,另一个也会跟着变-->
<input type="text" v-model="inputValue" @keyup.enter="handleBtnClick">
<button @click="handleBtnClick">提交</button>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
<script>
var app =new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
methods: {
handleBtnClick: function (){
this.list.push(this.inputValue)
this.inputValue=''
}
}
})
</script>
</body>
</html>
使用组件化思想修改todolist
之前todo的列表是用<li></li>标签实现的。现在我们将这一部分改成用组件显示。
全局组件
首先使用Vue.component("")方法创建一个全局组件
// vue
Vue.component("TodoItem")
然后在组件中使用template创建组件模板
// vue
Vue.component("TodoItem",{
template:"<li>todo item</li>"
})
``
在html中使用创建好的标签,比如下面的`todo-item`.
```html
<ul>
<!-- <li v-for="item in list">{{item}}</li> -->
<todo-item v-for="item in list"></todo-item>
</ul>
这样就把一个todo组件化了。但是现在无论输入什么,结果都是todo item。想要子组件展示相应的内容,就需要对组件传值。
这里就需要v-bind。
v-bind向子组件传递一个绑定值。所以需要将上面的html代码修改为:
<ul>
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
</ul>
意思在循环list时,把list中的每一项赋值为item,再把输入的值通过v-bind的content传给item。
接下来就需要把值传递给组件了。这里要用到props,在TodoItem中添加props属性,props接收一个content参数:
// vue
Vue.component("TodoItem",{
props: ['content']
template:"<li>todo item</li>"
})
这样子组件就能接收到父组件输入的值。现在只需要再修改一下template里的todo item,就可以显示出来了:
// vue
Vue.component("TodoItem",{
props: ['content']
template:"<li>{{content}}</li>"
})
下面是完整的代码:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div id="app">
<input type="text" v-model="inputValue" @keyup.enter="handleBtnClick">
<button @click="handleBtnClick">提交</button>
<ul>
<!-- v-bind向子组件传入绑定值,通过content把外部获取的值传递给todo-item-->
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
</ul>
</div>
<script>
// 创建了全局组件
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>
</body>
</html>
局部组件
首先创建一个局部组件。
var TodoItem ={
props: ['content'],
template: "<li>{{content}}</li>"
}
局部组件使用时要先在vue实例中注册注册,才能被使用:
var app =new Vue({
// 局部组件需要注册才能使用
components: {
TodoItem
}
下面是完整的代码:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div id="app">
<input type="text" v-model="inputValue" @keyup.enter="handleBtnClick">
<button @click="handleBtnClick">提交</button>
<ul>
<todo-item v-bind:content="item" v-for="item in list"></todo-item>
</ul>
</div>
<script>
var TodoItem ={
props: ['content'],
template: "<li>{{content}}</li>"
}
var app =new Vue({
el: '#app',
data: {
list: [],
inputValue: ''
},
// 局部组件需要注册才能使用
components: {
TodoItem
},
methods: {
handleBtnClick: function (){
this.list.push(this.inputValue)
this.inputValue=''
}
}
})
</script>
</body>
</html>
vue组件之间的传值
上面已经实现了一个todo的添加。但现在删除功能还没有实现。现在需要实现点击一个todo就将它删除。 因为上面我们把todo-item设为了子组件。现在就涉及到子组件向父组件传值。
首先需要在子组件中做事件绑定,然后编写事件函数。当点击todo-item时,子组件将数据传递给父组件,让父组件进行删除操作。
当子组件被点击时,子组件需要将删除操作传递给父组件,这里用到了$emit,向上一层触发事件
// vue局部组件
var TodoItem ={
props: ['content'],
template: "<li @click='handleItemClick'>{{content}}</li>" ,
methods: {
handleItemClick: function () {
// 子组件被点击时,将事件发射出去
this.$emit("delete")
}
}
}
父组件需要对事件进行监听,一旦删除事件被触发,就调用hangdleItemClick函数
<ul>
<todo-item @delete="handleItemDelete" v-bind:content="item" v-for="item in list"></todo-item>
</ul>
接下来就需要在父组件中定义handleItemClick函数。此函数需要删除点击对应的item,但是目前项目中没有对应的数据。所以需要在todo-item中利用v-bind再传一个值:
<ul>
<todo-item @delete="handleItemDelete" v-bind:index="item" v-bind:content="item" v-for="(item,index) in list"></todo-item>
</ul>
然后还需要在子组件的props中加入index,这样子组件才能接受父组件的值:
var TodoItem ={
props: ['content','index']
}
然后还需要把子组件中的handleItemClick函数添加一个this.index。这样父组件监听时就会拿到delete与index
var TodoItem ={
props: ['content','index'],
methods: {
handleItemClick: function () {
this.$emit("delete",this.index)
}
}
}
最后就是添加父组件中的handleItemDele:
handleItemDelete: function (index) {
this.list.splice(index,1)
}
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<style>
#id{
width: 400px;
height: 600px;
}
ul{
background-color:bisque;
}
</style>
<title>Document</title>
</head>
<body>
<div id="app">
<!-- v-model数据的双向绑定 ,input框内容和inputValue
其中之一变了,另一个也会跟着变-->
<input type="text" v-model="inputValue" @keyup.enter="handleBtnClick">
<button @click="handleBtnClick">提交</button>
<ul>
<!-- v-bind向子组件传入绑定值,通过content把外部获取的值传递给todo-item-->
<!-- 父组件监听delete事件,一旦删除事件被触发,就调用hangdleItemClick函数 -->
<todo-item @delete="handleItemDelete" v-bind:index="index" v-bind:content="item" v-for="(item,index) in list"></todo-item>
</ul>
</div>
<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',
data: {
list: [],
inputValue: ''
},
// 局部组件需要注册才能使用
components: {
TodoItem
},
methods: {
handleBtnClick: function (){
this.list.push(this.inputValue)
this.inputValue=''
},
handleItemDelete: function (index) {
this.list.splice(index,1)
}
}
})
</script>
</body>
</html>