vue相关介绍
Vue的两种使用方式:
1、vue核心包开发
场景:局部模块改造
2、vue核心包&vue插件工程化开发
场景:整站开发
概念:vue是用于构建用户界面的渐进式框架
创建vue实例
- 创建Vue实例,初始化渲染步骤:
- 准备容器
- 引包(官网)(开发版本的包/生产版本的包)
- 创建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>
<div id = "app">
{{msg}}
</div>
<!-- 引入开发版本的核心包 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
<script>
//一旦引入了vue.js核心包,在全局环境,就有了vue构造函数
const app = new Vue({
// 通过el配置选择器,指定el管理是哪一个盒子
el:'#app',
// 通过data提供数据
data:{
msg:'666',
}
})
</script>
</body>
</html>
插值表达式{{ }}
插值表达式是一种vue模板语法
作用:利用表达式进行插值,渲染到页面中,其中表达式是一种可以被求值的代码,JS引擎会将其计算出一个结果
语法:{{表达式}}
注意点:
1、使用数据时,数据必须是存在的
2、支持的是表达式(还可以是拼接字符串),而非语句,比如if for
3、不能在标签属性中使用{{ }}插值
<p title="{{username}}">我是标签</p>
vue响应式特性
响应式:数据变化,视图自动更新
vue指令
指令:带有v-前缀的特殊标签属性
指令—v-html
<!-- vue指令:v-前缀的标签属性 -->
<div v-html = "str"></div>
作用:设置元素的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">
<div v-html ='msg'></div>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
msg:'<a href = "http://www.itheima.com">黑马</a>'
}
})
</script>
</body>,
</html>
vue指令v-show vs v-if
v-show
1、作用:控制元素显示隐藏
2、语法:v-show=”表达式“,表达式值true显示,否则隐藏
3、底层原理:切换css的display:none来控制显示隐藏
4、使用场景:频繁切换显示隐藏场景
v-if
1、作用:控制元素显示隐藏(条件渲染)
2、语法:v-if=”表达式“,表达式值true显示,否则隐藏
3、底层原理:根据判断条件控制元素的创建和移除
4、使用场景:要么显示,要么隐藏,不频繁切换的场景
<!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">
<div v-show = "flag" class = "box">我是show</div>
<div v-if = "flag" class = "box">我是if</div>
<div class = "box">我是if</div>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
flag:false
}
})
</script>
</body>
</html>
vue指令v-else v-else-if
1、作用辅助v-if进行判断渲染
2、语法:v-else v-else-if= ”表达式“
3、注意:需要紧挨着v-if一起使用
<!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 v-if = "sex == 1">性别:男</p>
<p v-else>性别:女</p>
<hr>
<p v-if = "grade >= 90">成绩评定A:奖励电脑一台</p>
<p v-else v-else-if = "grade < 90 && grade >= 80">成绩评定B</p>
<p v-else v-else-if = "grade < 80 && grade >= 70">成绩评定C</p>
<p v-else v-else-if = "grade < 70">成绩评定D</p>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
grade:58,
sex:8
}
})
</script>
</body>,
</html>
指令v-on
1、作用:注册事件 = 添加监听 + 提供处理逻辑
2、语法:
- v-on:事件名=”内联语句“
- v-on:事件名=”methods中的函数名“
内联语句示例:
<!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">
<!-- click可以换做划入等动作,例如mouseenter,v-on:这一部分可以被替换为@ -->
<button v-on:click="count++">+</button>
<!-- <button @click="count++">+</button> -->
<span>{{count}}</span>
<button v-on:click="count--">-</button>
<!-- <button @click="count--">-</button> -->
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
count:0
}
})
</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>
</head>
<body>
<div id = "app">
<button @click = "isDisplay">切换显示隐藏</button>
<h1 v-show = "isShow">黑马程序员</h1>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
isShow:true
},
methods:{
isDisplay(){
this.isShow = !this.isShow;
}
}
})
</script>
</body>
</html>
v-on调用传参
<!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">
<div class = "box">
<h3>小黑自动售货机</h3>
<button @click = "buy(5)">可乐5元</button>
<button @click = "buy(10)">咖啡10元</button>
</div>
<div>银行卡余额:{{money}}</div>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
money:100
},
methods:{
buy(price){
this.money -= price;
}
}
})
</script>
</body>
</html>
指令v-bind
1、作用:动态的设置html的标签属性 → src url title......
2、语法: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">
<!-- 简写方式直接 v-bind:src → :src -->
<img v-bind:src="imgURL" alt="">
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
imgURL:'./images/taobao.jpg'
},
})
</script>
</body>
</html>
指令v-for
1、作用:基于数据循环,多次渲染整个元素,可以遍历数组、对象、数字等
<!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>小黑水果店</h3>
<ul>
<!-- list[index] 也可以用item表示,for后面的括号里面也可以只有item省略index-->
<li v-for="(item , index) in list">{{list[index]}}</li>
</ul>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
list:['西瓜', '苹果', '香蕉']
},
})
</script>
</body>
</html>
案例展示:图书管理案例
明确需求:
1、基本渲染
2、删除功能
<!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>小黑的书架</h3>
<ul>
<li v-for="(item , index) in bookList">
<span>{{ item.name }}</span>
<span>{{ item.author }}</span>
<!-- 注册点击事件,通过id进行删除数组中的数据 -->
<button @click="del(item.id)">删除</button>
</li>
</ul>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
bookList:[
{id:1, name:'《红楼梦》', author:'曹雪芹'},
{id:2, name:'《西游记》', author:'吴承恩'},
{id:3, name:'《水浒传》', author:'施耐庵'}
]
},
methods:{
del(id){
// filter:根据条件,保留满足条件的对影响,得到一个新数组
this.bookList = this.bookList.filter(item => item.id!== id)
}
}
})
</script>
</body>
</html>
指令v-for的key
语法:key属性 = ”唯一标识“
作用:给列表项添加唯一标识。便于vue进行列表项的正确排序复用
没有加key的情况:
点击删除:
可以发现粉色的背景颜色依然存在
而加上key后:
v-for的默认行文会尝试原地修改元素,也就是当我们删除三个元素中的第一个元素时候,如果没有加那么就相当于删除的是最后一个元素,然后将文字位置进行对应的修改
注意点:
key的值只能是字符串或数字
key的值必须具有唯一性
推荐使用id作为key
指令v-model
1、作用:给表单元素使用,双向数据绑定→可以快速获取或设置表单元素内容
数据变化→视图自动更新
视图变化→数据自动更新
2、语法: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="pwd" ><br><br>
<button v-on:click="login">登录</button>
<button v-on:click="reset">重置</button>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
username:'',
pwd:''
},
methods:{
login(){
console.log(this.username);
console.log(this.pwd);
},
reset(){
this.username='';
this.pwd='';
}
}
})
</script>
</body>
</html>
综合案例:小黑记事本
功能需求:
1、列表渲染
2、删除功能
3、添加功能
4、底部统计和清空
<!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>
input[type="text"] {
border: 1px solid black;
border-radius: 5px;
padding: 5px;
}
</style>
</head>
<body>
<div id="app">
<div>
<h3>记事本</h3>
<div>
<input type="text" v-model="content">
<!-- 添加功能
1、通过v-model绑定输入框,实时获取表单元素的内容
2、点击按钮,进行新增
-->
<button @click="add" >添加</button>
</div>
<div>
<ul>
<li v-for="(item,index) in list" :key="item.id">
<span>{{index + 1}}</span>
<span>{{item.content}}</span>
<button @click="del(item.id)">删除</button>
</li>
</ul>
<span>合计{{list.length}}</span><button @click="clear">清空</button>
</div>
</div>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
list:[
{
id:1,
content:'跑步1公里'
},
{
id:2,
content:'跳绳200次'
},
{
id:3,
content:'游泳100米'
}
]
},
methods:{
add(){
this.list.push({
id:this.list.length+1,
content:this.content
})
},
del(id){
this.list = this.list.filter(item => item.id!== id)
},
clear(){
this.list = []
}
}
})
</script>
</body>
</html>
指令修饰符
通过”."指明一些指令后缀,不同后缀封装了不同的处理操作→简化代码
1、按键修饰符
@keyup.enter→键盘回车监听(没有加后缀的时候按住任意键都可出发监听,但是加上了就只能通过回车触发)
因此既可通过点击添加按钮添加任务,也可以通过回车
2、v-model修饰符
v-model.trim→去除首尾空格
v-model.number→转数字
输入年龄的时候,原来是实际上是字符串,使用.number可以将其转换为数字,但是如果输入的不是数字得到的仍然是字符串
3、事件修饰符
@事件名.stop→阻止冒泡
<!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>
.father{
width: 200px;
height: 200px;
background-color:red;
}
.son{
width: 100px;
height: 100px;
background-color:blue;
}
</style>
</head>
<body>
<div id="app">
<div @click="father" class="father">
<div @click.stop="son" class="son"></div>
</div>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
username:'',
age:''
},
methods:{
father(){
alert('父亲被点击了')
},
son(){
alert('儿子被点击了')
}
}
})
</script>
</body>
</html>
在加上后缀之前,点击儿子的时候会触发点击父亲的事件,但是当加上后缀之后就不会触发父亲事件
@事件名.prevent→阻止默认行为
v-bind对于样式控制的增强
为了方便开发者进行样式控制,vue扩展了v-bind的语法,可以针对class类名和style行内样式进行控制
操作class
语法:
:class = "对象/数组"
1、对象→键就是类名,值是布尔值,如果值为true,有这个类,否则没有这个类
<div class="box" :class="{类名:布尔值,类名2:布尔值}"></div>
试用场景:一个类名,来回切换
2、数组→数组中所有的类,都会添加到盒子上,本质就是一个class列表
<div class="box" :class="[类名1,类名2,类名3]"></div>
试用场景:批量添加或删除类
三种表示方式具有相同的效果
导航高亮案例
点击哪一个哪一个就显示高亮
核心思路:
1、基于数据动态渲染tab
2、准备下标记录高亮的是哪一个tab
3、基于下标,动态控制class类名
<!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>
/* li标签中的a作为顶部并排的导航 */
ul {
list-style-type: none;
padding: 0;
margin: 0;
overflow: hidden;
background-color: #333;
}
li {
float: left;
}
li a {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
/* 鼠标移入li变色 */
.active{
background-color: pink;
}
</style>
</head>
<body>
<div id="app">
<ul>
<!-- 点击切换activeIndex的值 -->
<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:'品类秒杀'}
]
}
})
</script>
</body>
</html>
v-bind对于样式控制增强-操作styl
语法:
:style=“样式对象”
注意点:属性值需要用引号引起来,当属性名含有‘-’时也需要用引号
<!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;
background-color: pink;
}
</style>
</head>
<body>
<div id="app">
<div class="box" :style="{width:'400px', height:'400px', 'background-color':'green'}"></div>
</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:'品类秒杀'}
]
}
})
</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>
.progress{
/* 圆角矩形 */
border-radius: 10px;
/* 边框 */
border: 1px solid #ccc;
/* 背景色 */
background-color: black;
width:200px;
}
.inner{
/* 圆角矩形 */
border-radius: 10px;
/* 边框 */
border: 1px solid #ccc;
background-color: blue;
height:100%;
}
</style>
</head>
<body>
<div id="app">
<div class="progress">
<div class="inner" :style="{width:percent + '%'}">
<span>{{percent}}%</span>
</div>
</div>
<div>
<button @click="percent = 25">设置25%</button>
<button @click="percent = 50">设置50%</button>
<button @click="percent = 100">设置100%</button>
</div>
</div>
<script src="./vue.js "></script>
<script>
const app = new Vue({
el:'#app',
data:{
percent:30
}
})
</script>
</body>
</html>
v-model应用于其他表单元素
常见的表单元素都可以用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>
<style>
</style>
</head>
<body>
<div id="app">
<h1>小黑学习网</h1><br><br>
姓名:<input type="text" v-model="username">
<br><br>
是否单身:<input type="checkbox">
<br><br>
性别:
<!--
1、name:给单选框加上name属性,可以分组,同一组相互会互斥
2、value:给单选框加上value属性,用于提交给后台数据
-->
<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值,关联了选中的value值
-->
<select v-model="cityId">
<option value="101">北京</option>
<option value="102">上海</option>
<option value="103">成都</option>
</select>
<br><br>
自我描述:
<br><br>
<textarea v-model="desc" name="" id="" cols="30" rows="10"></textarea>
<br><br>
<button>注册</button>
</div>
<script src="./vue.js "></script>
<script>
const app = new Vue({
el:'#app',
data:{
username:'',
gender:1,
cityId:'101',
desc:""
}
})
</script>
</body>
</html>
计算属性
概念:
基于现有的数据,计算出来的新属性,依赖数据变化,自动重新计算
语法:
1、声明在computed配置项中,一个计算属性对应一个函数
2、使用起来和普通属性一样使用{{计算属性名}}
<!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>
/* 表格每一项都有边框*/
table {
border: 1px solid #ccc;
}
/* 表格每一项都有边框*/
table th {
width:50px;
border: 1px solid #ccc;
}
/* 文字居中显示 */
td, th {
text-align: center;
}
table td {
width:50px;
border: 1px solid #ccc;
}
</style>
</style>
</head>
<body>
<div id="app">
<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>
<br><br>
</table>
<!-- 不能加括号 -->
<div>礼物总数为:{{totalCount}}个</div>
</div>
<script src="./vue.js "></script>
<script>
const app = new Vue({
el:'#app',
data:{
list:[
{id:1, name:'篮球', num:1},
{id:2, name:'足球', num:2},
{id:3, name:'排球', num:3},
{id:4, name:'气球', num:4}
]
},
computed:{
totalCount(){
// 基于现有数据,编写求值逻辑
// 计算属性函数内部,可以直接通过this访问到app实例
let total = this.list.reduce((sum, item) => sum + item.num, 0);
return total;
}
}
})
</script>
</body>
</html>
计算属性vs方法methods
计算属性:
作用:封装了一段对于数据的处理,求得一个结果
缓存特性(提升性能):
计算属性会对计算出来 的结果缓存,再次使用直接读取缓存,依赖项变化了,会自动重新计算,并再次缓存
methods方法:
作用:给实例提供一个方法,调用来处理业务逻辑
计算属性完整写法
计算属性默认的简写,只能读取访问,不能修改
如果要修改,需要写出计算属性的完整写法
<!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>
</style>
</head>
<body>
<div id="app">
姓:<input type="text" v-model="firstName"> + 名:<input type="text" v-model="lastName"> = <span>{{fullName}}</span>
<br><br>
<button @click="changeName">改名卡</button>
</div>
<script src="./vue.js "></script>
<script>
const app = new Vue({
el:'#app',
data:{
firstName:'刘',
lastName:"备"
},
methods:{
changeName(){
this.fullName = fullName;
}
},
computed:{
fullName:{
// 当fullName计算属性,被获取求值时,执行get(有缓存优先读缓存),
// 会将返回值作为求值的结果
get(){
return this.firstName + this.lastName
},
set(){
this.firstName = firstName;
this.lastName = lastName;
}
}
}
})
</script>
</body>
</html>
watch侦听器 (监视器)
作用:监视数据变化,执行一些业务逻辑或异步操作
语法:
1、简答类型,简单类型数据直接监视
2、完整写法,添加额外配置项
<!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>
/* 为文本输入框添加边框 */
</style>
</head>
<body>
<div id="app">
<!-- 翻译框 -->
<div class="box">
<textarea v-model="words" cols="30" rows="10">老值</textarea>
<textarea v-model="person.name" cols="30" rows="10"></textarea>
</div>
</div>
<script src="./vue.js"></script>
<script>
const app = new Vue({
el:'#app',
data:{
words:'',
person:{
name:''
}
},
methods:{
},
watch:{
words(newValue, oldValue){
console.log('变化了',newValue,oldValue);
},
'person.name'(newValue){
console.log('变化了',newValue);
}
}
})
</script>
</body>
</html>