Web前端笔记-12、Vue-插值表达式、响应式、Vue指令
概念:Vue 是一个用于构建用户界面的渐进式框架。
构建用户界面:把数据渲染成页面。
渐进式:声明式渲染、组件系统、客户端路由VueRouter、大规模状态管理Vuex、构建工具webpack/vite。循序渐进,学一点用一点。
框架:一套完整的项目解决方案。
Vue快速上手
使用步骤:
- 准备一个容器。
- 导包。
- 创建实例 new Vue()
- 实例指定配置项渲染数据。el指定挂载点,data提供数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 1. 准备一个容器 -->
<div id="app">
<p>姓名:{{uname}}</p>
<p>年龄:{{age}}</p>
<p>朋友的姓名:{{friend.fname}}</p>
<p>朋友的性别:{{friend.sex}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app', // 指定数据展示的元素
data: {
// 要展示的数据
uname: 'good',
age: 18,
friend: {
sex: '男',
fname: 'friend'
}
}
})
</script>
</body>
</html>
插值表达式
插值表达式{{ }}是一种 Vue 的模板语法
作用:利用表达式进行插值,渲染到页面中
表达式:是可以被求值的代码,JS引擎会将其计算出一个结果
obj.name price >=100 ? 'ex':'cheap' arr[0] fn() obj.fn()
以上都是表达式。
注意:
- 使用的数据必须存在。
- 支持的是表达式,而非语句。比如 if for不能用。
- 不能在标签属性中使用插值当作属性值。
响应式
除了基本的模板渲染,Vue背后还做了大量工作。比如:数据的响应式处理。
响应式:数据变化了,页面(视图)会自动更新。
结论:data中所有的数据都会加到app对象上,成为其属性。 let app = new Vue()
思想:数据驱动视图。别想着改DOM了,直接改数据即可。实在改不了的再想DOM的事。
开发者调试工具
专门调试Vue项目。
极简插件:下载 开发者模式一 拖拽安装 插件详情允许访问文件
Vue指令
v-html v-show v-if v-else v-on v-bind v-for v-model
Vue 会根据不同的【指令】,针对标签实现不同的【功能】。方便渲染数据的。
指令:带有 v-前缀的特殊标签属性。
v-html
相当于原生的innerHTML,把v-html=""的值展示到标签内容中。
会把标签的原有内容覆盖。
会动态解析标签。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<p>{{str}}</p>
<p v-html="str"></p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
str: '一个v-html的示例,可以<strong>解析html标签</strong>'
}
})
</script>
</body>
</html>
v-show v-if
v-show:控制元素显示隐藏。v-show = "true or false"
原理:切换 display:none 控制显示隐藏。
场景:频繁切换显示隐藏的场景。
v-if:控制元素显示隐藏(条件渲染)。v-if = "true or false"
原理:基于条件判断,是否 创建或移除 元素节点。
场景:要么显示,要么隐藏,不频繁切换的场景。
v-if 可配合 v-else-if 和 v-else多条件判断控制显示隐藏。
v-on
进行注册事件的。注册事件 = 添加监听 + 提供处理逻辑
之前注册事件:找到元素对象,addEventListener,写回调函数。
现在用v-on。
语法:
v-on:事件名="内联语句"适合比较简单的一行逻辑
v-on:事件名 ="methods中的函数名"适合多行
简写:
v-on:替换成@
v-on:click="count++" 可以简写成 @click="count++"
内联:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<button @click="count--">-</button>
<span v-html="count"></span>
<button @click="count++">+</button>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
count: 10
}
})
</script>
</div>
</body>
</html>
使用函数:
methods:与data平级。
在Vue中,this永远表示Vue实例对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<button @click="fn">切换显示隐藏</button>
<h1 v-show="flag">内容</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
flag: true,
count: 0
},
methods: {
fn() {
this.flag = !this.flag
this.count++
console.log(`第${this.count}次点击`)
},
},
})
</script>
</body>
</html>
传参:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 210px;
margin: 20px;
padding: 20px;
border: 3px solid #000;
border-radius: 10px;
}
h3 {
margin: 10px 0 20px 0;
}
p {
margin: 20px;
}
</style>
</head>
<body>
<div id="app">
<div class="box">
<h3>自动售货机</h3>
<button @click="fn(colaPrice)">可乐{{colaPrice}}元</button>
<button @click="fn(coffePrice)">咖啡{{coffePrice}}元</button>
<button @click="fn(milkPrice)">牛奶{{milkPrice}}元</button>
</div>
<p>银行卡余额:{{money}}元</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
money: 100,
colaPrice: 5,
coffePrice: 10,
milkPrice: 8
},
methods: {
fn(n) {
this.money -= n
},
},
})
</script>
</body>
</html>
事件对象:
事件对象就是之前addEventListener中回调函数的第一个参数e。
回顾:这个对象里有事件触发时的相关信息,包含属性和方法例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
e.target e.keye.target得到的是触发事件的元素
- 如果在模板中(html页面中)使用事件对象,可以使用
$event(固定写法) - 如果在JS中使用事件对象,还是事件处理函数的形参e
- 如果JS中,既用e,又有其他参数,秉持一对一的原则。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>输入框1输入内容,并将其显示在p标签中(在模板中使用)</h2>
<input type="text" @input="result1 = $event.target.value">
<p v-html="result1"></p>
<h2>输入框2输入内容,并将其显示在p标签中(在JS的函数中使用)</h2>
<input type="text" @input="fn">
<p v-html="result2"></p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
result1: '',
result2: '',
},
methods: {
fn(e) {
this.result2 = e.target.value
}
},
})
</script>
</body>
</html>
上面的代码中,在模板中,$event就是input触发时返回的事件对象。在JS的事件函数用e。
一对一原则:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>输入框1输入内容,并将其显示在p标签中(在模板中使用)</h2>
<input type="text" @input="result1 = $event.target.value">
<p v-html="result1"></p>
<h2>输入框2输入内容,并将其显示在p标签中(在JS的函数中使用)</h2>
<input type="text" @input="fn(100, 200, $event)">
<p v-html="result2"></p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
result1: '',
result2: '',
},
methods: {
fn(a, b , e) {
console.log(a + b)
this.result2 = e.target.value
}
},
})
</script>
</body>
</html>
@input="fn(100, 200, $event)"与fn(a, b , e) {}对应
v-bind
作用:动态设置html的标签属性。
语法:v-bind:属性名="表达式"
一旦属性名加上了v-bind,引号里就只能看作表达式,不再是字符串。
简写:把v-bind删掉,:属性名="表达式"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<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>
<img :src="imgList[index]" alt="波仔" :title="title">
<button v-show="index<imgList.length-1" @click="index++">下一页</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
index: 0,
title: '波仔',
imgList: [
'./imgs/10-01.png',
'./imgs/10-02.png',
'./imgs/11-00.gif',
'./imgs/11-01.gif'
]
},
})
</script>
</body>
</html>
v-for
作用:基于数据循环,多次渲染整个元素。可以遍历数组、对象、数字等。
遍历数组语法:v-for="(item, index) in 数组",v-for="item in 数组"
v-for的key
在有v-for的标签里加key属性,key的值是字符串或者数字,通常用到变量或表达式,注意别忘了使用v-bind。以后所有的遍历都加上key,保证key不重复即可。
作用:key作用:给元素添加的唯一标识。便于Vue进行列表项的正确排序复用。
v-for 的默认行为会尝试 原地修改元素(就地复用)。数据驱动,根据数据v-for生成li,如果不给key,vue不知道应该删哪个li,就默认将最后一个li删掉,并根据数据重新渲染填充剩下的li。
推荐使用id,不要用index,因为index会变。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in bookList" :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/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
bookList: [
{id:1, name:'《红楼梦》', author: '曹雪芹'},
{id:2, name:'《西游记》', author: '吴承恩'},
{id:3, name:'《水浒传》', author: '施耐庵'},
{id:4, name:'《三国演义》', author: '罗贯中'},
]
},
methods: {
del (id) {
this.bookList = this.bookList.filter(item=>{
return item.id !== id
})
}
},
})
</script>
</body>
</html>
v-model应用到input
思想:双向数据绑定。
作用: 给表单元素使用,双向数据绑定。可以快速获取或设置表单元素内容
数据变化,视图自动更新。视图变化,数据自动更新。
语法:v-model ='变量'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
账户:<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/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
username: '',
password: '',
},
methods: {
login(){
console.log('账密:', this.username, this.password)
},
reset(){
this.username = this.password = ''
},
},
})
</script>
</body>
</html>
id使用时间戳写法
id: +new Date()id: Date.now()
指令修饰符
通过.指明一些指令后缀,不同后缀封装了不同的处理操作以简化代码。
- v-model修饰符
v-model.trim 去除首尾空格
v-model.number 转数字(填数字才有效,比如年龄、单价需要字符串转数字)
v-model.lazy 输入框change时,才更新数据(比如手机号的输入)
- 事件修饰符
@事件名.stop 阻止冒泡
@事件名-prevent 阻止标签的默认行为 <a> <form>
@keyup.enter 键盘回车监听 .esc .49数字1 .13enter
v-bind对样式操作的增强
分为控制类名和控制style行内样式
语法 ::class = "对象/数组"
对象:键就是类名,值是布尔值。如果值为 true,有这个类,否则没有这个类(比较方便)
<div class="box" :class="{类名1:布尔值,类名2:布尔值 }"></div>
适用场景:一个类名,来回切换。Tab切换。
数组:数组中所有的类,都会添加到盒子上,本质就是一个 class 列表。
<div class="box" :class="[类名1,类名2,类名3]"></div>
适用场景:批量添加或删除类
<!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>
* {
margin: 0;
padding: 0;
}
ul {
display: flex;
border-bottom: 2px solid #e01222;
padding: 0 10px;
}
li {
width: 100px;
height: 50px;
line-height: 50px;
list-style: none;
text-align: center;
}
li a {
display: block;
text-decoration: none;
font-weight: bold;
color: #333333;
}
li a.active {
background-color: #e01222;
color: #fff;
}
</style>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item, index) in list" :key="item.id" @mouseenter="activeIndex=index">
<a :class="{active: index === activeIndex}" href="#">{{item.name}}</a>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
activeIndex: 0, // 记录高亮
list: [
{ id: 1, name: '京东秒杀' },
{ id: 2, name: '每日特价' },
{ id: 3, name: '品类秒杀' }
]
}
})
</script>
</body>
</html>
操作行内样式::style ="样式对象"
<div class="box" :style="{CSS属性名1:CSS属性值,CSS属性名2:CSS属性值}"></div>
适用场景:某个具体属性的动态设置
<div class="box" :style="{width:'100px', 'background-color':'pink' }"></div>
<div class="progress">
<div class="inner" :style="{width: percent+'%'}">
<span>{{percent}}%</span>
</div>
</div>
v-model应用到其他表单元素
v-model与表单元素的绑定关系:
input:text => value
textarea => value
input:checkbox => checked
input:radio => checked
select => value
注意:复选框只有一个和多个一组(name相同)是不一样的,只有一个的复选框v-model与value值绑定时通过布尔值控制。一组的复选框通过一个数组控制,数组中存在对应value的复选框被选中。
<input type="checkbox" name="hobby" value="吃" v-model="aihao"/>吃饭
aihao: ['吃']
全选,反选:
通过v-model与复选框绑定(绑定的是checked)。
list.every(item => item.isChecked)
computed: {
checkedAll:{
get(){
// 点击小控制全选框
return this.fruitList.every(item => item.isChecked)
},
set(val) {
// 点击全选框控制小
this.fruitList.forEach(item => {
item.isChecked = val
})
}
}
}
// 在全选复选框处 v-model="checkedAll"

浙公网安备 33010602011771号