一 概念-为什么学习vue以及vue是什么?
- Angular 2. vue 3. React
Vue2 -> 稳定
- 最新长期稳定版 2.7.1 2016年9月 六年多 近140次版本更新
- 生态系统,文档系统完备
- 过往案例项目支撑
Vue3 -> 趋势
- 性能提升 => 1.2~2倍
- 内核体积更小=> 10kb
- TS支持度更高
- 组合式API,封装复用逻辑
Vue快速上手
Vue是什么
- 概念:Vue是一个用于
- 构建用户界面 1. 基于数据渲染出用户看到的页面
- 的渐进式 2. 循序渐进
- 框架 3. 一套完整的项目解决方案
- 1-图片
- 2-图片
- 3-图片
- 优点: 大大提升开发效率(70%)
- 缺点: 需要理解记忆规则 - 官网
总结: Vue是一个用于 构建用户界面 的 渐进式 框架
- 构建用户界面: 基于 数据 动态 渲染 页面
- 渐进式: 循序渐进的学习
- 框架: 一套完整的项目的解决方案,提升开发效率(理解记忆规则)
- 规则 - 官网
1 创建Vue实例,初始化渲染
V2: v2.cn.vuejs.org/
- 学习-教程-安装-开发版本 在线链接:
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
页面中显示:"你好"
<body>
<!--
目标: 使用 Vue 完成渲染
创建Vue实例,初始化渲染
1 准备容器(vue所管理的范围)
2 引包(开发版本包 / 生产版本包)官网
3 创建实例
4 添加配置项 => 完成渲染
-->
<div>
这里是非 vue 托管的区域: {{ msg }}
</div>
------------------------------
<div id="app">
{{ msg }}
<!-- 开发版本: 包含完整的警告和调试模式,学习阶段统一使用开发版本 -->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
// 一旦引入了 vue 包,全局就会有一个 vue 构造函数
// 3 创建实例
// 4 添加配置项 => 完成渲染
const app = new Vue({
el:'#app',
data:{
msg:'你好!'
}
})
</script>
总结: 创建 Vue实例,初始化渲染的核心步骤
- 准备容器
- 引包(官网) - 开发版本/生产版本
- 创建Vue实例 new Vue()
- 制定配置项 el data => 渲染数据
- 4.1 el 指定挂载点,选择器指定控制的是哪个盒子
- 4.2 data提供数据
2 插值表达式
- 插值表达式{{}}
- 插值表达式是一种vue的模板语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!--
目标: 使用插值表达式渲染数据到网页
插值表达式:Vue的一种模板语法
作用:利用表达式进行插值渲染
语法:{{ 表达式 }}
注意点:
1. 使用的数据要存在
2. 支持的是表达式,不是语句 if for
3. 不能在标签属性中使用 {{ }}
-->
<div id="app">
<p>{{ nickname }}</p>
<p>{{ nickname.substring(2) }}</p>
<p>{{ age >=18 ? '成年' : '未成年'}}</p>
<p>{{ fried.name }}{{ friend.desc }}</p>
<!-- <p>{{ gender }}</p> -->
<!-- 插值表示的类型没有,会报错 -->
<!-- <p>{{if}}</p> -->
<!-- <a href="{{ url}}">百度</a> -->
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
nickname: '紫阳道长',
age: 18,
friend: {
name: '张三',
desc: '热爱学习 Vue'
}
}
})
</script>
</body>
</html>
- 作用: 利用表达式进行插值,渲染到页面中
- 表达式: 是可以被求职的代码,js引擎会将其计算出一个结果
- 语法: {{ 表达式 }}
- 注意点: 3.1 使用的数据必须存在(data)
<!-- <p>{{ gender }}</p> -->
3.2 支持的是表达式,而非语句,比如: if for ...
<!-- <p>{{if}}</p> -->
3.3 不能在表情属性中使用 {{}} 插值
<!-- <a href="{{ url}}">百度</a> -->
总结:
- 插值表达式的作用是什么? 利用表达式进行插值,将数据渲染页面中
- 语法格式? {{ 表达式 }}
- 插值表达式的注意点
- 3.1 使用的数据要存在 (data)
- 3.2 支持的是表达式,而非语句 if..for
- 3.3 不能在标签属性里面使用
3 响应式特性:
- Vue核心特性: 响应式
- 我们已经掌握了基础的模版渲染,其实除了基本的模版渲染,Vue背后还有做了大量工作。
- 如何访问 or 修改? data中的数据,最终会被添加到实例上
- 1 访问数据: "实例.属性名"
- 2 修改数据: "实例.属性名" = "值"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
{{ msg }}
{{ count }}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标: 理解响应式数据的特性
* 好处: 程序员以后不用再操心视图如何渲染了,把精力全部放在操作
* 数据上面,只要数据变化,视频会自动更新
*/
const app = new Vue({
el: '#app',
data: {
// 响应式数据 → 数据变化了,视图自动更新
msg: '你好,黑马',
count: 100
}
})
</script>
</body>
</html>
Vue核心特性: 响应式 数据改变,视图会自动更新
- 聚焦于数据 -> 数据驱动视图
- 使用 Vue开发,关注业务的核心逻辑,根据业务修改数据即可
总结:
- 什么是响应式呢?
- 数据改变,视图自动更新
- 使用Vue开发 - 专注于业务核心逻辑 即可
- 如何访问或修改数据呢?
- data中的数据,最终会被添加到实例上
- 【0】 访问数据:"实例.属性名"
- 【1】修改数据: "实例.属性名" ="值"
4 开发者工具-安装vue-devtools插件
安装Vue开发者工具: 装插件调试Vue应用
- 通过谷歌应用商城安装(国外网站)
- 极简插件: 下载 - 开发者模式 - 拖拽安装 - 插件详情允许访问文件
Vue指令
Vue指令 v-html
- Vue会根据不同的[指令],针对标签实现不同的[功能]
- 指令: 带有 v-前缀 的特殊 标签属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div>
{{ msg }}
</div>
<!-- v-html 设置元素的 innerHTML
v-html="表达式"
注意: 如果使用了 v-html 则标签内不能再写内容了,会被v-html的结果覆盖掉 -->
<div v-html="msg"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标:
* 将带有标签的 msg 数据解析标签并渲染到 div 中
*/
const app = new Vue({
el: '#app',
data: {
msg: '<h1>学前端~来黑马!</h1>'
}
})
</script>
</body>
</html>
总结:
- 什么是Vue指令呢?
- 指令计算带有 v-前缀的特殊属性,不同属性对应 不同的功能
- 学习不同指令 - 解决不同业务场景需求
- 如果需要动态解析标签,可以用哪个指令?语法?
- v-html = "表达式" - 动态设置元素 innerHTML
Vue指令 v-show vs v-if
v-show
- 作用 控制元素显示隐藏
- 语法: v-show="表达式" 表达式值 true显示,flash隐藏
- 原理: 切换 display:none 控制显示隐藏
- 场景: 频繁切换显示隐藏的场景
v-if
- 作用: 控制元素显示隐藏(条件渲染)
- 语法: v-if="表达式" 表达式值 true显示,flase隐藏
- 原理: 基于条件判断,是否 创建 或 移除 元素节点
- 场景: 要么显示,要么隐藏,不频繁切换的场景
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 200px;
height: 100px;
line-height: 100px;
margin: 10px;
border: 3px solid #000;
text-align: center;
border-radius: 5px;
box-shadow: 2px 2px 2px #ccc;
}
</style>
</head>
<body>
<div id="app">
<div v-show="isShow" class="box">我是v-show控制的盒子</div>
<div v-if="isShow" class="box">我是v-if控制的盒子</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标: 控制盒子显示隐藏
* v-show 底层原理: 通过设置 display:none 来改变合作的现实状态
* v-if 底层原理: 通过创建 / 删除 DOM 元素来实现合作的现实隐藏
*
*
* v-show 比较适合频繁切换显示隐藏的场景
* v-if 比较时候初始状态就决定了显示隐藏的场景
* */
const app = new Vue({
el: '#app',
data: {
isShow:true
}
})
</script>
</body>
</html>
Vue指令 v-else 和 v-else-if
1 作用: 辅助v-if 进行判断渲染 2 语法: v-else v-else-if="表达式"
v-else、v-else-if用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!--
v-if 和 v-else 注意事项
v-else 必须紧贴着 v-if 来编写,中间不能有任何标签问题(注释除外)
-->
<p v-if="gender === 1">性别:♂ 男</p>
<p v-else>性别:♀ 女</p>
<hr>
<p v-if="score >=90">成绩评定A:奖励电脑一台</p>
<p v-else-if="score >= 70">成绩评定B:奖励周末郊游</p>
<p v-else-if="score >= 60">成绩评定C:奖励零食礼包</p>
<p v-else>成绩评定D:惩罚一周不能玩手机</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
// 目标:
// 1. 根据条件渲染姓名
// 2. 根据成绩来渲染奖励
const app = new Vue({
el: '#app',
data: {
gender: 1,
score: 95
}
})
</script>
</body>
</html>
Vue指令 v-on
1 作用: 注册事件 = 添加监听 + 提供处理逻辑 2 语法: 2.1 v-on:事件名="内联语句" 2.2 v-on:事件名="methods中的函数名" 3 简写: @事件名 4 注意: methods函数内的 this指向 Vue实例
<button v-on:click="count++">按钮</buttton>
1. v-on:事件名="内联语句"、用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!--
v-on 语法
v-on:事件名="内联代码" 适合机器简单的场景,一行代码就搞定
v-on:事件名="事件除了函数" 适合复杂的逻辑处理
简写:
v-on: => @
-->
<button v-on:click="count--">-</button>
<span>{{ count }}</span>
<button @click="count++">+</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
// 目标: 点击 - 让数字减一, 点击 + 让数字加一
const app = new Vue({
el: '#app',
data: {
count: 100
}
})
</script>
</body>
</html>
2. v-on:事件名="methods中的函数名"、用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<button @click="change">切换显示隐藏</button>
<h1 v-show="isshow">黑马程序员</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标:
* 点击切换 h1 标签显示隐藏
* 思路:
* 1 定义 isshow 变量,默认值为 true
* 2 使用 v-show 控制 h1 标签的现实隐藏
* 3 给 button 绑定点击事件, 对 isshow变量进行取反
*/
const app = new Vue({
el: '#app',
data: {
isshow:true
},
// methods 中存放函数
// 只要定义在 methods 中的函数,最终都会放到实例对象上,所以内部的 this 指向实例对象
methods:{
change(){
console.log('我被点了')
this.isshow = !this.show
}
}
})
</script>
</body>
</html>
3 v-on 调用传参
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
border: 3px solid #000000;
border-radius: 10px;
padding: 20px;
margin: 20px;
width: 200px;
}
h3 {
margin: 10px 0 20px 0;
}
p {
margin: 20px;
}
</style>
</head>
<body>
<div id="app">
<div class="box">
<h3>小黑自动售货机</h3>
<!--
v-on 事件处理函数传参:
@click="事件处理函数(实参)"
注意: 即便加了 () 也不是调用函数,依然是绑定事件处理函数,函数依然在事件触发时
才会执行,执行时会携带参数过去
-->
<button @click="buy(5)">可乐5元</button>
<button @click="buy(10)">咖啡10元</button>
</div>
<p>银行卡余额:{{ money }}元</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标:
* 点击不同按钮, 银行卡余额减少对应的金额
*/
const app = new Vue({
el: '#app',
data: {
money: 100
},
methods:{
but(price){
this.money -= price
}
}
})
</script>
</body>
</html>
Vue指令 v-bind
- 作用 动态的设置html的标签属性 src url title
- 语法 v-bind: 属性名="表达式"
- 注意: 简写形式 :属性名="表达式"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!--
v-bind: 动态设置标签属性的
v-bind: 属性名="表达式"
支持简写:
:属性名="表达式"
-->
<!-- <img v-bind:src="imgUrl" v-bind:title="msg" alt=""> -->
<img :src="imgUrl" :title="msg" alt="">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标:
* 使用 v-bind 指令动态绑定标签属性
*/
const app = new Vue({
el: '#app',
data: {
imgUrl: './imgs/10-02.png',
msg: 'hello 波仔'
}
})
</script>
</body>
</html>
案例-波仔的学习之旅
图片切换案例-波仔学习之旅 核心思路分析
- 数组 存储图片路径 - 【图片1,图片2,图片3】
- 准备下标 index,数组【下标】 - v-bind 设置 src展示图 - 修改下标切换图片
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<button v-show="index > 0" @click="index--" >上一页</button>
<div>
<img :src="list[index]" alt="">
</div>
<button v-show="index < list.length -1" @click="index++">下一页</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标: 点击按钮切换图片, 如果到第一张就不显示上一页按钮, 如果到最后一张就不显示下一页按钮
* 思路:
* 1. 定义一个变量当做数组索引
* 2. 使用 v-bind 绑定 img 的 src 为 list[index]
* 3. 点击按钮操作 index 值即可
* 4. 使用 v-show 控制上一页和下一页按钮显示隐藏
*/
const app = new Vue({
el: '#app',
data: {
index:0,
list: [
'./imgs/11-00.gif',
'./imgs/11-01.gif',
'./imgs/11-02.gif',
'./imgs/11-03.gif',
'./imgs/11-04.png',
'./imgs/11-05.png',
]
},
methods:{
}
})
</script>
</body>
</html>
Vue 指令 v-for
1 作用: 基于数据循环,多次渲染整个元素 - 数组、对象、数字
<p v-for="">我是一个内容</p>
2 遍历数组语法:
- v-for="(item.index) in 数组"
- item 每一项,index下标
- 省略index: v-for="item in 数组"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h3>小黑水果店</h3>
<ul>
<!--
v-for 写在 li 上就是重复渲染 li
语法:
v-for="(每一项,索引) in 数组"
-->
<li v-for="(item,index) in list">{{item}} --- {{index}}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标: 使用 v-for 循环渲染 li
*/
const app = new Vue({
el: '#app',
data: {
list: ['西瓜', '苹果', '鸭梨', '榴莲']
}
})
</script>
</body>
</html>
显示效果:
图书管理案例-小黑的书架
明确需求
- 基本渲染 - v-for
- 删除功能 - 用 filter 根据 id从数组中删除对应项
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h3>小黑的书架</h3>
<ul>
<li v-for="item in booksList" >
<span>{{item.name}}</span>
<span>{{item.author}}</span>
<button @click="del(item.id)">删除</button>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标:
* 1. 渲染书籍信息
* 2. 实现删除功能
*
* 思路:
* 1. 使用 v-for 循环渲染 li
* 2. 使用 v-on 给删除按钮绑定点击事件
* 3. 点击后传入 id
* 4. 根据 id 删除数据
*/
const app = new Vue({
el: '#app',
data: {
booksList: [
{ id: 1, name: '《红楼梦》', author: '曹雪芹' },
{ id: 2, name: '《西游记》', author: '吴承恩' },
{ id: 3, name: '《水浒传》', author: '施耐庵' },
{ id: 4, name: '《三国演义》', author: '罗贯中' }
]
},
methods:{
del(id){
// 根据 id 找到索引,根据索引删除元素
// forEach map reduce find findIndex
// const index = this.booksList.findIndex(item => item.id === id)
// this.booksList.splice(index,1)
// 2 filter 筛选不符合 id 的元素,把新数组覆盖回老数组
this.booksList = this.booksList.filter(item => item.id !== id)
}
}
})
</script>
</body>
</html>
v-for中的key
key的作用:
给元素添加唯一标识,便于Vue进行列表项的正确排序复用
注意点:
- key的值只能是 字符串 或 数字类型
- key 的值必须具有 唯一性
- 推荐使用 id 作为key(唯一),不推荐使用 index 作为 key (会变化,不对应)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h3>小黑的书架</h3>
<ul>
<!--
复用: vue不好轻易删除 DOM 并重新创建 DOM,因为这样很消耗性能,它会想尽
一切办法去的销毁 DOM
v-for 的默认复用策略: 就地更新,当前删除一个元素后,还剩3个 li,那么 vue
就会把最后一个 li 删除,里面的内容平移,以复用所以现存的li
v-for时建议加上 key属性,一般用唯一标识: id
key的设置要求:
1 一定要在当前v-for 中唯一
2 必须是 string 或 number
-->
<li v-for="(item, index) in booksList" :key="item.id">
<span>{{ item.name }}</span>
<span>{{ item.author }}</span>
<button @click="del(item.id)">删除</button>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标: 理解 v-for 中 :key 的作用
*/
const app = new Vue({
el: '#app',
data: {
booksList: [
{ id: 1, name: '《红楼梦》', author: '曹雪芹' },
{ id: 2, name: '《西游记》', author: '吴承恩' },
{ id: 3, name: '《水浒传》', author: '施耐庵' },
{ id: 4, name: '《三国演义》', author: '罗贯中' }
]
},
methods: {
del(id) {
this.booksList = this.booksList.filter(item => item.id !== id)
}
}
})
</script>
</body>
</html>
Vue指令 v-model
1 作用: 给表单元素 使用。双向数据绑定-可以快速 获取 或 设置 表单元素内容
- 1.1 数据变化 - 视频自动更新
- 1.2 视图变化 - 数据自动更新
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!--
v-model 可以让数据和视图,形成双向数据绑定
1. 数据变化,视图自动更新
2. 视图变化,数据自动更新
可以快速获取或设置表单元素的内容
-->
账户:<input type="text" v-model="username"> <br><br>
密码:<input type="password" v-model="password"><br><br>
<button @click="login">登录</button>
<button @click="reset">重置</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标: 理解 v-model 的使用
* 1. 使用 v-model 双向绑定用户名和密码
* 2. 点击登录时直接获取用户名密码数据
* 3. 点击重置时直接重置用户名和密码
*/
const app = new Vue({
el: '#app',
data: {
username:'zhangsan',
password:'123456'
},
methods: {
login(){
console.log(this.username,this.password);
},
reset(){
this.password=""
this.username=""
}
}
})
</script>
</body>
</html>
综合案例-小黑记事本
功能需求:
- ① 列表渲染
- ② 删除功能
- ③ 添加功能
- ④ 底部统计 和 清空
第一步、删除and渲染功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./css/index.css" />
<title>记事本</title>
</head>
<body>
<!-- 主体区域 -->
<section id="app">
<!-- 输入框 -->
<header class="header">
<h1>小黑记事本</h1>
<input placeholder="请输入任务" class="new-todo" />
<button class="add">添加任务</button>
</header>
<!-- 列表区域 -->
<section class="main">
<ul class="todo-list">
<li class="todo" v-for="(item,index) in list" :key="item.id ">
<div class="view">
<span class="index">{{index+1}}</span> <label>{{item.name}}</label>
<button class="destroy" @click="del(item.id)"></button>
</div>
</li>
</ul>
</section>
<!-- 统计和清空 -->
<footer class="footer">
<!-- 统计 -->
<span class="todo-count">合 计:<strong> 1 </strong></span>
<!-- 清空 -->
<button class="clear-completed">
清空任务
</button>
</footer>
</section>
<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标1 列表渲染
* 1.1 使用 v-for 循环渲染 list
* 1.2 设置 :key
* 1.3 使用索引作为序号
*
*
* 目标2 删除功能
* 2.1 给小叉叉绑定点击事件
* 2.2 传入id
* 2.3 使用 filter 筛选删除
*/
const app = new Vue({
el: '#app',
data: {
list: [
{ id: 1, name: '跑步一公里' },
{ id: 2, name: '打球一小时' },
{ id: 3, name: '游泳100米' },
]
},
// 删除 按钮
methods:{
del(id){
this.list = this.list.filter(item => item.id !== id)
}
}
})
</script>
</body>
</html>
第二步-添加功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./css/index.css" />
<title>记事本</title>
</head>
<body>
<!-- 主体区域 -->
<section id="app">
<!-- 输入框 -->
<header class="header">
<h1>小黑记事本</h1>
<input placeholder="请输入任务" class="new-todo" v-model="taskname"/>
<button class="add" @click="add">添加任务</button>
</header>
<!-- 列表区域 -->
<section class="main">
<ul class="todo-list">
<li class="todo" v-for="(item,index) in list" :key="item.id ">
<div class="view">
<span class="index">{{index+1}}</span> <label>{{item.name}}</label>
<button @click="del(item.id)" class="destroy"></button>
</div>
</li>
</ul>
</section>
<!-- 统计和清空 -->
<footer class="footer">
<!-- 统计 -->
<span class="todo-count">合 计:<strong> 1 </strong></span>
<!-- 清空 -->
<button class="clear-completed">
清空任务
</button>
</footer>
</section>
<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标1 列表渲染
* 1.1 使用 v-for 循环渲染 list
* 1.2 设置 :key
* 1.3 使用索引作为序号
*
*
* 目标2 删除功能
* 2.1 给小叉叉绑定点击事件
* 2.2 传入id
* 2.3 使用 filter 筛选删除
*
* 目标3
* 3.1 定义 taskname数据,使用 v-model双向数据绑定
* 3.2 给添加任务按钮绑定点击事件
* 3.3 匪口校验
* 3.4 将数据组装后添加到数组的第一个元素
* 3.5 清空文本框(给 taskname 赋值 空)
*/
const app = new Vue({
el: '#app',
data: {
list: [
{ id: 1, name: '跑步一公里' },
{ id: 2, name: '打球一小时' },
{ id: 3, name: '游泳100米' },
],
taskname:''
},
// 删除 按钮
methods:{
del(id){
this.list = this.list.filter(item => item.id !== id)
},
add(){
if(this.taskname.trim() === '')return alert('请输入任务名称')
// console.log(this.taskname);
this.list.unshift({
id: +new Date(),
name:this.taskname
})
this.taskname = ""
}
}
})
</script>
</body>
</html>
第三步 底部统计、清空功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./css/index.css" />
<title>记事本</title>
</head>
<body>
<!-- 主体区域 -->
<section id="app">
<!-- 输入框 -->
<header class="header">
<h1>小黑记事本</h1>
<input placeholder="请输入任务" class="new-todo" v-model="taskname"/>
<button class="add" @click="add">添加任务</button>
</header>
<!-- 列表区域 -->
<section class="main">
<ul class="todo-list" >
<li class="todo" v-for="(item,index) in list" :key="item.id ">
<div class="view">
<span class="index">{{index+1}}</span> <label>{{item.name}}</label>
<button @click="del(item.id)" class="destroy"></button>
</div>
</li>
</ul>
</section>
<!-- 统计和清空 内容全部清空后 清空内容和内容多少隐藏-->
<footer class="footer" v-show="list.length>0">
<!-- 统计 -->
<span class="todo-count">合 计:<strong> {{list.length}} </strong></span>
<!-- 清空 -->
<button class="clear-completed" @click="clear">
清空任务
</button>
</footer>
</section>
<!-- 底部 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
/**
* 目标1 列表渲染
* 1.1 使用 v-for 循环渲染 list
* 1.2 设置 :key
* 1.3 使用索引作为序号
*
*
* 目标2 删除功能
* 2.1 给小叉叉绑定点击事件
* 2.2 传入id
* 2.3 使用 filter 筛选删除
*
* 目标3
* 3.1 定义 taskname数据,使用 v-model双向数据绑定
* 3.2 给添加任务按钮绑定点击事件
* 3.3 匪口校验
* 3.4 将数据组装后添加到数组的第一个元素
* 3.5 清空文本框(给 taskname 赋值 空)
*
*
* 目标4 清空任务和底部统计
* 4.1 底部统计计算 list.length
* 4.2 清空任务计算给list 赋值为空数组
* 4.3 使用 v-show 控制底部的显示隐藏
*/
const app = new Vue({
el: '#app',
data: {
list: [
{ id: 1, name: '跑步一公里' },
{ id: 2, name: '打球一小时' },
{ id: 3, name: '游泳100米' },
],
taskname:''
},
// 删除 按钮
methods:{
del(id){
this.list = this.list.filter(item => item.id !== id)
},
add(){
if(this.taskname.trim() === '')return alert('请输入任务名称')
// console.log(this.taskname);
this.list.unshift({
id: +new Date(),
name:this.taskname
})
this.taskname = ""
},
clear(){
this.list = []
}
}
})
</script>
</body>
</html>