指令修饰符
"." 指明一些指令 后缀,不同 后缀 封装了不同的处理操作 → 简化代码
- ① 按键修饰符
@keyup.enter → 键盘回车监听 - ② v-model修饰符
v-model.trim → 去除首尾空格
v-model.number → 转数字 - ③ 事件修饰符
@事件名.stop → 阻止冒泡
@事件名.prevent → 阻止默认行为
<!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">
<h3>@keyup.enter → 监听键盘回车事件</h3>
<input @keyup.enter="fn" type="text" v-model="username" />
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
username: "",
},
methods: {
// fn(e) {
// if (e.key === "Enter") {
// console.log(e);
// console.log("键盘回车时触发", this.username);
// }
// },
fn(e){
console.log(e);
console.log("键盘回车时触发", this.username);
}
},
});
</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" />
<title>Document</title>
<style>
.father {
width: 200px;
height: 200px;
background-color: pink;
margin-top: 20px;
}
.son {
width: 100px;
height: 100px;
background-color: skyblue;
}
</style>
</head>
<body>
<div id="app">
<h3>v-model修饰符 .trim .number</h3>
姓名:<input v-model.trim="username" type="text" /><br />
年纪:<input v-model.number="age" type="text" /><br />
<h3>@事件名.stop → 阻止冒泡</h3>
<div @click="fatherFn" class="father">
<div @click.stop="sonFn" class="son">儿子</div>
</div>
<h3>@事件名.prevent → 阻止默认行为</h3>
<a @click.prevent href="http://www.baidu.com">阻止默认行为</a>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
username: "",
age: "",
},
methods: {
fatherFn() {
alert("老父亲被点击了");
},
sonFn(e) {
// e.stopPropagation()阻止冒泡
alert("儿子被点击了");
},
},
});
</script>
</body>
</html>
v-bind 对于样式控制的增强 - 操作class
语法 :class = "对象/数组"
- ① 对象 → 键就是类名,值是布尔值。如果值为 true,有这个类,否则没有这个类
<div class="box" :class="{ 类名1: 布尔值, 类名2: 布尔值 }"></div>
适用场景:一个类名,来回切换 - ② 数组 → 数组中所有的类,都会添加到盒子上,本质就是一个 class 列表
<div class="box" :class="[ 类名1, 类名2, 类名3 ]"></div>
适用场景:批量添加或删除类
<!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: 200px;
height: 200px;
border: 3px solid #000;
font-size: 30px;
margin-top: 10px;
}
.pink {
background-color: pink;
}
.big {
width: 300px;
height: 300px;
}
</style>
</head>
<body>
<div id="app">
<div class="box" v-bind:class="{pink:true,big:true}">哈哈哈</div>
<div class="box" v-bind:class="cc">哈哈哈</div>
<div class="box" v-bind:class="['big']">哈哈哈</div>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
cc:{pink:true,big:false}
},
});
</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" />
<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><a class="active" href="#">京东秒杀</a></li>
<li><a href="#">每日特价</a></li>
<li><a href="#">品类秒杀</a></li> -->
<li v-for="(item, index) in list" :key="item.id" @click="fn(index)">
<a href="#" :class="{active:index === activeIndex}">{{item.name}}</a>
</li>
</ul>
<ul>
<!-- <li><a class="active" href="#">京东秒杀</a></li>
<li><a href="#">每日特价</a></li>
<li><a href="#">品类秒杀</a></li> -->
<li v-for="(item, index) in list" :key="item.id" @click="activeIndex=index">
<a href="#" :class="{active:index === activeIndex}">{{item.name}}</a>
</li>
</ul>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
activeIndex: 0,
list: [
{ id: 1, name: "京东秒杀" },
{ id: 2, name: "每日特价" },
{ id: 3, name: "品类秒杀" },
],
},
methods: {
fn(index) {
this.activeIndex = index;
},
},
});
</script>
</body>
</html>
v-bind 对于样式控制的增强 - 操作style
语法 :style = "样式对象"
<div class="box" :style="{ CSS属性名1: CSS属性值, CSS属性名2: CSS属性值 }"></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>
.box {
width: 200px;
height: 200px;
background-color: rgb(187, 150, 156);
}
</style>
</head>
<body>
<div id="app">
<div class="box" :style="{width:'100px',height:'100px','background-color':'pink'}"></div>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
}
})
</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">
<title>Document</title>
<style>
.progress {
height: 25px;
width: 400px;
border-radius: 15px;
background-color: #272425;
border: 3px solid #272425;
box-sizing: border-box;
margin-bottom: 30px;
}
.inner {
width: 50%;
height: 20px;
border-radius: 10px;
text-align: right;
position: relative;
background-color: #409eff;
background-size: 20px 20px;
box-sizing: border-box;
transition: all 1s;
}
.inner span {
position: absolute;
right: -20px;
bottom: -25px;
}
</style>
</head>
<body>
<div id="app">
<div class="progress">
<div class="inner" :style="{width:p+'%'}">
<span>{{p}}%</span>
</div>
</div>
<button @click="p=25">设置25%</button>
<button @click="p=50">设置50%</button>
<button @click="p=75">设置75%</button>
<button @click="p=100">设置100%</button>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
p:0,
}
})
</script>
</body>
</html>
v-model 应用于其他表单元素
常见的表单元素都可以用 v-model 绑定关联 → 快速 获取 或 设置 表单元素的值
它会根据 控件类型 自动选取 正确的方法 来更新元素
- 输入框 input:text → value
- 文本域 textarea → value
- 复选框 input:checkbox → checked
- 单选框 input:radio → checked
- 下拉菜单 select → value
- ...
<!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>
textarea {
display: block;
width: 240px;
height: 100px;
margin: 10px 0;
}
</style>
</head>
<body>
<div id="app">
<h3>小黑学习网</h3>
姓名:
<input type="text" v-model="username">
<br><br>
是否单身:
<input type="checkbox" v-model="isSingle">
<br><br>
<!--
前置理解:
1. name: 给单选框加上 name 属性 可以分组 → 同一组互相会互斥
2. value: 给单选框加上 value 属性,用于提交给后台的数据
结合 Vue 使用 → v-model
-->
性别:
<input type="radio" name="gender" value="1" v-model="gender">男
<input type="radio" name="gender" value="2" v-model="gender">女
<br><br>
<!--
前置理解:
1. option 需要设置 value 值,提交给后台
2. select 的 value 值,关联了选中的 option 的 value 值
结合 Vue 使用 → v-model
-->
所在城市:
<select v-model="cityId">
<option value="101">北京</option>
<option value="102">上海</option>
<option value="103">成都</option>
<option value="104">南京</option>
</select>
<br><br>
自我描述:
<textarea v-model="desc"></textarea>
<button>立即注册</button>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
username:'',
isSingle:true,
gender:'2',
cityId:'104',
desc:'textarea'
},
computed:{
}
})
</script>
</body>
</html>
计算属性
概念:基于现有的数据,计算出来的新属性。 依赖的数据变化,自动重新计算。
语法:
- 声明在
computed配置项中,一个计算属性对应一个函数 - 使用起来和普通属性一样使用
{{ 计算属性名 }}
计算属性 → 可以将一段 求值的代码 进行封装
computed: {
计算属性名 () {
基于现有数据,编写求值逻辑
rerurn 结果
}
},
<!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>
table {
border: 1px solid #000;
text-align: center;
width: 240px;
}
th,td {
border: 1px solid #000;
}
h3 {
position: relative;
}
</style>
</head>
<body>
<div id="app">
<h3>小黑的礼物清单</h3>
<table>
<tr>
<th>名字</th>
<th>数量</th>
</tr>
<tr v-for="(item, index) in list" :key="item.id">
<td>{{ item.name }}</td>
<td>{{ item.num }}个</td>
</tr>
</table>
<!-- 目标:统计求和,求得礼物总数 -->
<p>礼物总数:{{totalCount}} 个</p>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
// 现有的数据
list: [
{ id: 1, name: '篮球', num: 5 },
{ id: 2, name: '玩具', num: 2 },
{ id: 3, name: '铅笔', num: 5 },
]
},
computed:{
totalCount(){
//基于现有的数据,编写求值逻辑
//计算属性的函数内部,可以通过 this 访问到 app 实例
// list=this.list;
// let t=0;
// for(let i=0;i<list.length;i++){
// t+=list[i].num;
// }
// console.log(this.list.length);
let total=this.list.reduce((sum,item) => sum + item.num,0)
return total
}
}
})
</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" />
<title>Document</title>
</head>
<body>
<div id="app">
姓:<input type="text" v-model="firstName" /><br />
名:<input type="text" v-model="lastName" /><br />
<p>姓名:{{fullName}}</p>
<button @click="changeName">修改姓名</button>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
firstName: "刘",
lastName: "备",
},
computed: {
// fullName() {
// return this.firstName + this.lastName;
// },
fullName:{
get(){
return this.firstName + this.lastName;
},
//当fullNmae 计算属性,被修改赋值时,执行set
// 修改的值,传递给set方法的形参
set(value){
console.log(value);
this.firstName=value.slice(0,1)
this.lastName=value.slice(1)
}
}
},
methods: {
changeName(){
this.fullName='吕布'
}
},
});
</script>
</body>
</html>
watch 侦听器(监视器)
作用:监视数据变化,执行一些 业务逻辑 或 异步操作。
语法:
- 简单写法 → 简单类型数据,直接监视
- 完整写法 → 添加额外配置项
(1) deep: true 对复杂类型深度监视
(2) immediate: true 初始化立刻执行一次handler方法
<!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;
box-sizing: border-box;
font-size: 18px;
}
#app {
padding: 10px 20px;
}
.query {
margin: 10px 0;
}
.box {
display: flex;
}
textarea {
width: 300px;
height: 160px;
font-size: 18px;
border: 1px solid #dedede;
outline: none;
resize: none;
padding: 10px;
}
textarea:hover {
border: 1px solid #1589f5;
}
.transbox {
width: 300px;
height: 160px;
background-color: #f0f0f0;
padding: 10px;
border: none;
}
.tip-box {
width: 300px;
height: 25px;
line-height: 25px;
display: flex;
}
.tip-box span {
flex: 1;
text-align: center;
}
.query span {
font-size: 18px;
}
.input-wrap {
position: relative;
}
.input-wrap span {
position: absolute;
right: 15px;
bottom: 15px;
font-size: 12px;
}
.input-wrap i {
font-size: 20px;
font-style: normal;
}
</style>
</head>
<body>
<div id="app">
<!-- 条件选择框 -->
<div class="query">
<span>翻译成的语言:</span>
<select v-model="obj.lang">
<option value="italy">意大利</option>
<option value="english">英语</option>
<option value="german">德语</option>
</select>
</div>
<!-- 翻译框 -->
<div class="box">
<div class="input-wrap">
<textarea v-model="obj.words"></textarea>
<span><i>⌨️</i>文档翻译</span>
</div>
<div class="output-wrap">
<div class="transbox">{{result}}</div>
</div>
</div>
</div>
<script src="./vue.js"></script>
<script src="./axios.js"></script>
<script>
// 接口地址:https://applet-base-api-t.itheima.net/api/translate
// 请求方式:get
// 请求参数:
// (1)words:需要被翻译的文本(必传)
// (2)lang: 需要被翻译成的语言(可选)默认值-意大利
// -----------------------------------------------
const app = new Vue({
el: "#app",
data: {
words: "",
obj: {
words: "小黑",
lang: "italy",
},
result: "",
// timer:null
},
// 具体讲解:(1) watch语法 (2) 具体业务实现
watch: {
// 该方法会在数据变化时调用执行
// words(newValue, oldValue) {
// // 防抖: 延迟执行 → 干啥事先等一等,延迟一会,一段时间内没有再次触发,才执行
// clearTimeout(this.timer)
// this.timer=setTimeout(async ()=>{
// const res = await axios({
// url: "https://applet-base-api-t.itheima.net/api/translate",
// params: {
// words: newValue,
// },
// });
// this.result=res.data.data;
// console.log(res.data.data);
// },300)
// },
obj: {
deep: true,
immediate:true,
handler(newValue) {
// console.log(newValue);
clearTimeout(this.timer);
this.timer = setTimeout(async () => {
const res = await axios({
url: "https://applet-base-api-t.itheima.net/api/translate",
params: newValue
});
this.result = res.data.data;
console.log(res.data.data);
}, 300);
},
},
},
});
</script>
</body>
</html>