文章目录
todos案例
1 提供的数据和 HTML结构
2 把数据渲染到页面上
3 把类名是 new-todo 按回车键的时候 把输入框中的数据展示到页面上
4. 实现全选功能
5 实现删除功能
6 实现编辑功能
7 Clear completed
8 number item left
todos案例-组件化抽离
1 提供的数据和 HTML结构
2 抽离头部组件
3 抽离数据展示组件
4 抽离fotter 部分
todos接口案例
1 请求后台接口list 获取 数据展示到页面上
2 增加内容
3 双击修改列表信息
5 删除全部完成
6 实现全选功能
todos案例
1 提供的数据和 HTML结构
引入todos的CSS样式 (HTML和 CSS 已经写好 我们需要改成Vue动态渲染的)
< section id = " todoapp" class = " todoapp" >
< header class = " header" >
< h1> todos h1>
< input placeholder = " What needs to be done?" class = " new-todo" >
header>
< section class = " main" >
< input id = " toggle-all" type = " checkbox" class = " toggle-all" >
< label for = " toggle-all" > Mark all as complete label>
< ul class = " todo-list" >
< li class = " " >
< div class = " view" > < input type = " checkbox" class = " toggle" >
< label> 吃饭 label>
< button class = " destroy" > button>
div>
< input class = " edit" >
li>
< li class = " " >
< div class = " view" >
< input type = " checkbox" class = " toggle" >
< label> 睡觉 label>
< button class = " destroy" > button>
div> < input class = " edit" > li>
< li class = " completed" >
< div class = " view" >
< input type = " checkbox" class = " toggle" >
< label> 打豆豆 label>
< button class = " destroy" >
button> div>
< input class = " edit" >
li>
ul>
section>
< footer class = " footer" >
< span class = " todo-count" >
< strong> 2 strong> item left span>
< ul class = " filters" >
< li> < a href = " #/" class = " selected" > All a> li>
< li> < a href = " #/active" > Active a> li>
< li> < a href = " #/completed" > Completed a> li>
ul>
< button class = " clear-completed" > Clear completed button>
footer>
section>
< link rel = " stylesheet" href = " css/base.css" >
< link rel = " stylesheet" href = " css/index.css" >
< script>
new Vue ( {
el: "#todoapp" ,
data: {
todos: [ {
id: 1 ,
title: '吃饭' ,
completed: false
} , {
id: 2 ,
title: '睡觉' ,
completed: false
} , {
id: 3 ,
title: '打豆豆' ,
completed: true
} ]
}
} )
script>
2 把数据渲染到页面上
根据completeed 的状态动态给li 绑定类名
未完成状态:不需要样式 完成状态: 类名为 completed 编辑状态:类名为 editing
如果completed 为 true 则给当前li 添加 completed
< li v-for = " (item, index) in todos"
v-bind: class= " {completed: item.completed}"
>
< div class = " view" >
< input type = " checkbox" class = " toggle" >
< label> {{item.title}} label> < button class = " destroy" > button>
div>
< input class = " edit" >
li>
3 把类名是 new-todo 按回车键的时候 把输入框中的数据展示到页面上
获取文本框中用户输入的数据
判断数据是否非空 如果是空的,则什么都不做 如果不是空的,则添加到数组中
添加到数组中
清空文本框
< header class = " header" >
< h1> todos h1>
< input class = " new-todo" placeholder = " What needs to be done?" @keyup.enter = " addTodo" >
header>
< script>
new Vue ( {
el: "#todoapp" ,
data: {
todos: [ {
id: 1 ,
title: '吃饭' ,
completed: false
} , {
id: 2 ,
title: '睡觉' ,
completed: false
} , {
id: 3 ,
title: '打豆豆' ,
completed: true
} ]
} ,
methods: {
addTodo ( event) {
var todoText = event. target. value. trim ( )
if ( ! todoText. length) {
return
}
const lastTodo = this . todos[ this . todos. length - 1 ]
const id = lastTodo ? lastTodo. id + 1 : 1
this . todos. push ( {
id,
title: todoText,
completed: false
} )
event. target. value = ''
} ,
}
}
} )
script>
4. 实现全选功能
4.1 当点击三角即类名为 toggle-all 的复选框的时候
如果当前三角高亮 即 复选框为选中状态 让当前所有的li 为 完成状态
否则为未完成状态
4.2 当点击单个li 里面的复选框的时候 如果当前复选框选中 则当前的状态为完成状态
通过双向绑定获取当前复选框选中状态 通过选中状态动态改变 completed 的值
4.3 如果当前所有的li 都处于完成状态 即 复选框都选中 则上面的 toggle-all 复选框选中 有一个没有选中则当前toggle-all 复选框 处于未选中状态
< section class = " main" >
< input v-model = " toggleStat"
id = " toggle-all"
type = " checkbox" class = " toggle-all" >
< ul class = " todo-list" >
< li v-for = " (item, index) in todos"
v-bind: class= " {completed: item.completed}" >
< div class = " view" >
< input type = " checkbox" class = " toggle" v-model = " item.completed" >
< label> {{item.title}} label>
< button class = " destroy" > button>
div>
< input class = " edit" >
li>
ul>
section>
< script>
new Vue ( {
el: "#todoapp" ,
methods: {
addTodo ( event) {
} ,
removeTodo ( delIndex, event) {
this . todos. splice ( delIndex, 1 )
} ,
} ,
computed: {
toggleStat: {
get ( ) {
return this . todos. every ( item => item. completed)
} ,
set ( val) {
this . todos. forEach ( todo => todo. completed = val)
}
}
}
} )
script>
5 实现删除功能
给类名是 destroy 的按钮添加点击事件
点击当前按钮 删除当前按钮所在的 li
< section class = " main" >
< input v-model = " toggleStat" id = " toggle-all" type = " checkbox"
class = " toggle-all" >
< label for = " toggle-all" > Mark all as complete label>
< ul class = " todo-list" >
< li v-for = " (item, index) in todos"
v-bind: class= " {completed: item.completed}" >
< div class = " view" >
< input type = " checkbox" class = " toggle" v-model = " item.completed" >
< label> {{item.title}} label>
< button class = " destroy"
@click = " removeTodo(index)" >
button>
div>
< input class = " edit" >
li>
ul>
section>
< script>
new Vue ( {
el: "#todoapp" ,
methods: {
addTodo ( event) {
} ,
removeTodo ( delIndex) {
this . todos. splice ( delIndex, 1 )
} ,
} ,
} )
script>
6 实现编辑功能
6.1 双击标题的时候 当前li 的类名添加 editing
6.1.1 给当前标题添加双击事件
6.1.2 给当前li 添加editing 添加editing后 当前隐藏的输入框会显示出来
6.2 输入框的默认值为当前标题
6.3 当用户没有编辑 的时候 按esc退出的时候 数据不发生变化
6.4 当用户输入内容按回车键的时候 把标题更新
6.5当用户失去焦点的 时候 把输入框中的标题更新
< section class = " main" >
< input v-model = " toggleStat" id = " toggle-all" type = " checkbox"
class = " toggle-all" >
< label for = " toggle-all" > Mark all as complete label>
< ul class = " todo-list" >
< li v-for = " (item, index) in todos"
v-bind: class= " {completed: item.completed, editing: item === currentEditing}" >
< div class = " view" >
< input type = " checkbox" class = " toggle" v-model = " item.completed" >
< label
@dblclick = " currentEditing = item"
> {{item.title}} label>
< button class = " destroy"
@click = " removeTodo(index)" >
button>
div>
< input class = " edit"
:value = " item.title"
@keyup.esc = " currentEditing = null"
@keyup.enter = " saveEdit(item, index, $event)"
@blur = " saveEdit(item, index, $event)"
>
li>
ul>
section>
< script>
new Vue ( {
el: "#todoapp" ,
data: {
currentEditing: null ,
} ,
methods: {
saveEdit ( item, index, event) {
var editText = event. target. value. trim ( )
if ( ! editText. length) {
return this . todos. splice ( index, 1 )
}
item. title = editText
this . currentEditing = null
} ,
}
} )
script>
7 Clear completed
点击Clear completed 的时候删除所有的 已完成项
< footer class = " footer" >
< button
class = " clear-completed"
@click = " removeAllDone" > Clear completed button>
footer>
< script>
new Vue ( {
el: "#todoapp" ,
data: {
currentEditing: null ,
} ,
methods: {
removeAllDone ( ) {
this . todos = this . todos. filter ( item => ! item. completed)
} ,
}
} )
script>
8 number item left
< span class = " todo-count" > < strong> {{leftCount}} strong> item left span>
< script>
new Vue ( {
computed: {
leftCount: function ( ) {
return this . todos. filter ( item => ! item. completed) . length
}
}
} )
script>
todos案例-组件化抽离
1 提供的数据和 HTML结构
引入todos的CSS样式 (HTML和 CSS 已经写好 我们需要改成Vue动态渲染的)
< section id = " todoapp" class = " todoapp" >
< header class = " header" >
< h1> todos h1>
< input placeholder = " What needs to be done?" class = " new-todo" >
header>
< section class = " main" >
< input id = " toggle-all" type = " checkbox" class = " toggle-all" >
< label for = " toggle-all" > Mark all as complete label>
< ul class = " todo-list" >
< li class = " " >
< div class = " view" > < input type = " checkbox" class = " toggle" >
< label> 吃饭 label>
< button class = " destroy" > button>
div>
< input class = " edit" >
li>
< li class = " " >
< div class = " view" >
< input type = " checkbox" class = " toggle" >
< label> 睡觉 label>
< button class = " destroy" > button>
div> < input class = " edit" > li>
< li class = " completed" >
< div class = " view" >
< input type = " checkbox" class = " toggle" >
< label> 打豆豆 label>
< button class = " destroy" >
button> div>
< input class = " edit" >
li>
ul>
section>
< footer class = " footer" >
< span class = " todo-count" >
< strong> 2 strong> item left span>
< ul class = " filters" >
< li> < a href = " #/" class = " selected" > All a> li>
< li> < a href = " #/active" > Active a> li>
< li> < a href = " #/completed" > Completed a> li>
ul>
< button class = " clear-completed" > Clear completed button>
footer>
section>
< link rel = " stylesheet" href = " css/base.css" >
< link rel = " stylesheet" href = " css/index.css" >
< script>
new Vue ( {
el: "#todoapp" ,
data: {
todos: [ {
id: 1 ,
title: '吃饭' ,
completed: false
} , {
id: 2 ,
title: '睡觉' ,
completed: false
} , {
id: 3 ,
title: '打豆豆' ,
completed: true
} ]
}
} )
script>
2 抽离头部组件
把头部封装到一个组件中
给输入框绑定事件
当用户输入完数据后 通过子向父传值 把获取的用户输入的信息提交到父组件中去
父组件接收到子组件传递的数据 存放到todos 中
父组件中展示头部组件
< section id = " todoapp" class = " todoapp" >
< myheader @inpvalue = " addTodo" > myheader>
section>
< script>
var myheader = {
template: `
` ,
methods: {
addToParent ( event) {
var todoText = event. target. value. trim ( )
if ( ! todoText. length) {
return
}
this . $emit ( "inpvalue" , todoText)
}
}
}
new Vue ( {
el: "#todoapp" ,
data: {
currentEditing: null ,
todos: [ {
id: 1 ,
title: '吃饭' ,
completed: false
} , {
id: 2 ,
title: '睡觉' ,
completed: false
} , {
id: 3 ,
title: '打豆豆' ,
completed: true
} ]
} ,
methods: {
addTodo ( todoText) {
# 2.4 父组件接收到子组件传递的数据 存放到todos 中
const lastTodo = this . todos[ this . todos. length - 1 ]
const id = lastTodo ? lastTodo. id + 1 : 1
this . todos. push ( {
id,
title: todoText,
completed: false
} )
event. target. value = ''
} ,
}
# 2.1 注册子组件
components: {
myheader
}
} )
script>
3 抽离数据展示组件
3.1 把显示数据的代码封装到一个组件中
3.2 把父组件中的todos 传递过来 子组件接收到父组件传递过来的数据 进行渲染
3.3 点击删除 删除当前的数据
3.4 双击的时候 当前数据可编辑
3.5 按enter键的时候 保存当前数据
3.6 实现全选功能
< section id = " todoapp" class = " todoapp" >
< mylist :todos = " todos" @dbl-click = " aaaa"
@removetodo = " removeTodo"
@save-edit = " saveEdit"
:currentediting = " currentEditing"
>
mylist>
section>
< script src = " js/vue.js" > script>
< script>
var mylist = {
# 3.2 .2 子组件通过 props 接收父组件传递过来的数据
props: [ "todos" , "currentediting" ] ,
template: `
` ,
methods: {
# 3.3 .2 删除操作 子组件不要操作父组件里面的数据 把对应的数据传递到父组件中
removeTodoParent ( index) {
this . $emit ( "removetodo" , index)
} ,
# 3.5 .1 把当前数据发送到父元素 通过父元素保存子元素数据
saveEdit ( item, index, event) {
var editText = event. target. value. trim ( )
this . $emit ( "save-edit" , editText, item, index)
} ,
# 3.4 .2 子组件 把当前点击的li 传递到父元素
doubleMethods ( item) {
this . $emit ( "dbl-click" , item)
}
} ,
computed: {
# 3.6 .1 实现全选功能
toggleStat1: {
get ( ) {
return this . todos. every ( item => item. completed)
} ,
set ( val) {
this . todos. forEach ( todo => todo. completed = val)
}
} ,
} ,
}
new Vue ( {
el: "#todoapp" ,
data: {
currentEditing: null ,
todos: [ {
id: 1 ,
title: '吃饭' ,
completed: false
} , {
id: 2 ,
title: '睡觉' ,
completed: false
} , {
id: 3 ,
title: '打豆豆' ,
completed: true
} ]
} ,
methods: {
removeTodo ( delIndex) {
this . todos. splice ( delIndex, 1 )
} ,
saveEdit ( editText, item, index) {
console. log ( item, index, '-------------' )
if ( ! editText. length) {
return this . todos. splice ( index, 1 )
}
item. title = editText
this . currentEditing = null
} ,
removeAllDone ( ) {
this . todos = this . todos. filter ( item => ! item. completed)
} ,
# 3.4 .3 把当前li的数据 赋值给 currentEditing 即让当前li 绑定 类名
aaaa ( item) {
this . currentEditing = item
}
} ,
computed: {
} ,
components: {
myheader,
mylist,
}
} )
script>
body>
html>
4 抽离fotter 部分
4.1 把footer 部分的代码封装到一个组件中
4.2 实现 未选中部分的展示
4.3 删除已经选中的
< section id = " todoapp" class = " todoapp" >
< myfotter :leftcount = " leftCount" @delete-all-done = " removeAllDone" > myfotter>
section>
< script>
# 4.1 把footer 部分的代码封装到一个组件中
var myfotter = {
props: [ 'leftcount' ] ,
template: `
` ,
methods: {
deleteAll ( ) {
this . $emit ( "delete-all-done" )
}
}
}
new Vue ( {
computed: {
leftCount: function ( ) {
return this . todos. filter ( item => ! item. completed) . length
} ,
} ,
components: {
myheader,
mylist,
myfotter
}
} )
script>
todos接口案例
1 请求后台接口list 获取 数据展示到页面上
发送ajax请求
在mounted 钩子中将数据渲染到页面上
axios.defaults.baseURL = 'http://localhost:3001/';
new Vue({
data: {
currentEditing: null,
todos: []
},
mounted() {
# 1.2 在mounted 钩子中将数据渲染到页面上
this.getList()
},
methods: {
# 1.1 发送ajax请求
getList() {
axios.get('list').then(res => {
console.log(res.data)
this.todos = res.data
})
}
}
})
2 增加内容
在回车事件中发送ajax请求
我们已经封装好的 addTodo 方法中发送ajax请求
将用户输入的内容添加到后台
因为我们所有的数据增删改查都是在父组件中修改 所有ajax也在父组件的 方法中发送
addTodo ( todoText) {
axios. post ( 'add' , {
title: todoText,
} ) . then ( res => {
# 在请求成功之后重新渲染页面
this . getList ( )
} )
event. target. value = ''
} , event. target. value = '' } ,
3 双击修改列表信息
按回车键或者失去焦点的时候获取到用户信息
把收集到的用户信息发送到后台
## 子组件中 需要把当前id 传递过去
saveEdit(item, event) {
var editText = event.target.value.trim()
console.log(item, '--------')
this.$emit("save-edit", editText, item)
},
### 父组件方法
### 因为我们所有的数据增删改查都是在父组件中修改 所有ajax也在父组件的 方法中发送
// 保存编辑项
saveEdit(editText, item) {
axios.put(`list/${item.id}`, {
title: editText,
}).then(res => {
this.getList()
// 3. 去除 editing 样式
this.currentEditing = null
})
}
4 删除列表信息
点击按钮 删除当前列表信息
发送ajax请求 根据id 删除当前信息
# 4.1 需要把删除按钮的id 传递过去
# 父组件
### 因为我们所有的数据增删改查都是在父组件中修改 所有ajax也在父组件的 方法中发送
// 删除任务项
removeTodo(delIndex) {
axios.delete(`list/${delIndex}`).then(res => {
this.getList()
})
},
5 删除全部完成
在fotter 的Clear completed 的事件处理函数中发送ajax 请求删除所有complete 为true 的
# 父组件
### 因为我们所有的数据增删改查都是在父组件中修改 所有ajax也在父组件的 方法中发送
removeAllDone() {
axios.delete('deleteall').then(res=>
this.getList()
})
6 实现全选功能
在toggleStat1 中发送ajax请求 根据当前复选框选中状态 修改后台数据中对应的 complete 值
#2 把数据更新放在父组件中
computed: {
toggleStat1: {
get() {
return this.todos.every(item => item.completed)
},
set(val) {
axios.get(`all/${Number(val)}`).then(res => {
#1 子组件通知父组件更新数据
this.$emit('get-list')
})
}
}
}