一、指令的概念和分类
1、什么vue指令
vue指令是一种以v-
开头的特殊性属性,每一种指令它都写在元素的开始部分,每一种指令都有着自己的具体的功能,功能涉及到内容渲染、条件判断、列表渲染、表单内容的收集、事件绑定等等。
2、vue指令的分类
-
内容渲染指令:v-text、v-html
-
条件判断指令:v-if、v-elseif、v-else、v-show
-
事件绑定指令:v-on
-
属性绑定指令:v-bind
-
列表渲染指令:v-for
-
双向绑定指令:v-model
-
其他指令:v-slot、v-once、v-cloak
二、内容渲染指令
在vue中如果要进行内容渲染,一共三种方式
-
通过插值表达式进行内容渲染
-
通过v-text进行内容渲染:其实它的作用就相当于innerText,它有一个缺点会覆盖标签文本内容
-
通过v-html进行内容渲染:其实它的作用就相当于innerHTML,他会解析HTML5的标签的
-
缺点1:会覆盖标签之间的内容
-
缺点2:会造成XSS网络攻击,给黑客攻击网站带来了隐患
-
<template>
<div>
<div>姓名:{{name}}</div>
<div v-text="englishName">英文名</div>
网址:<span v-html="url"></span>
头像:<div v-html="headerImg"></div>
</div>
</template>
<script>
export default {
data(){
return{
name:'胡夏',
englishName:'Summer',
url:'<a href="http://www.Summer.cn/first">个人主页</a>',
headerImg:'<img src="https://woniuimage.oss-cn-hangzhou.aliyuncs.com/woniuimage/teacher/20220222.png">'
}
}
}
</script>
三、vue-devtools工具的使用
vue-devtools是一款基于chrome浏览器的扩展插件,用于vue的调试的,使用它可以让我们在vue调试过程带来巨大的便利
安装vue-devtools的步骤
-
全局安装vue-devtools
npm i -g vue-devtools
-
安装完之后,查看全局安装是否已经完成
npm list -g
通过查看然后找到全局安装的路径C:\Users\giles\AppData\Roaming\npm\node_modules\vue-devtools\vender
-
打开开发者设置
浏览器设置>可扩展程序,将右上角的打开开发者模式开关按钮打开
-
加载已经解压的扩展程序
-
调试和使用
四、条件判断指令
根据条件的真假进行渲染
分为如下两种
-
v-if系列:实际上是在构建虚拟DOM的时候根据条件是否成立而后才创建真实DOM元素,如果条件不成立则要删除元素,如果频繁进行显示与删除会带来巨大的性能消耗
-
v-show:当条件成立则显示,如果条件为false,则是通过对css样式的控制来隐藏元素
v-if和v-show的区别
-
语法不同,v-if的切换频繁的时候不建议使用,因为它的创建和删除所带来性能开销较大,v-show是通过隐藏元素来实现显示或隐藏的,一般情况下,尽量建议大家使用v-show
-
v-if和v-else-if和v-else更多的是完成逻辑方面的判断
五、事件绑定指令
在vue中使用v-on
这个指令来进行事件的绑定
案例:计数器的操作
1、基本使用的语法
<template>
<div>
<h1>{{num}}</h1>
<button v-on:click="num++">+</button>
<button @click="num--">-</button>
<hr>
<h2>{{num}}</h2>
<!-- 在template模板中如果要调用的是无参数的函数可以写小括号,也可以不写括号都可以 -->
<button @click="increment">+</button>
<button @click="decryment()">-</button>
</div>
</template>
<script>
/*
* 计数器的实现思路
1、首先在data定义一个变量num
2、在template模板中使用插值表达式来进行渲染
3、在指定元素上使用v-on:事件类型=""方式来进行事件的绑定
可以使用@click这种简写的方式来对事件进行绑定
*/
export default {
//在data函数定义的数据都是响应式数据(只要数据发生变化,页面也会自动发生变化)
data(){
return{
//定义在data中的数据可以作为VueComponent实例的成员
num:0
}
},
//methods这个选项中,主要完成事件处理函数的编写,以及自定义函数编写
methods:{
//methods选项中的函数的语法:函数名(){}
increment(){
//如果要在methods选项中的函数中去访问data中的定义的数据,不能直接使用名称获取
this.num++
console.log(`num的数据是:${this.num}`);
},
decryment(){
console.log('##################');
}
}
}
</script>
<style>
</style>
2、事件传值
<template>
<div>
<h2>{{num}}</h2>
<button @click="increment(2)">+2</button>
<button @click="decrement" data-step='3'>-3</button>
<button @click="incrementN($event,4)" max-val='50'>+4</button>
</div>
</template>
<script>
export default {
data(){
return{
num:0
}
},
methods:{
increment(step){
this.num+=step
},
decrement(e){
this.num-=~~e.target.getAttribute('data-step')
},
incrementN(e,step){
if(this.num<~~e.target.getAttribute('max-val')){
this.num+=step
}else{
window.alert('数据超过50')
}
}
}
}
</script>
<style>
</style>
3、事件修饰符
2.1、阻止事件冒泡
事件冒泡:从子到父;事件捕获:从父到子
在vue中阻止事件冒泡,有三种方法
-
使用原生js的方式: e.stopPropagation()
<template>
<div class="parent" @click="handleParent">
<div class="child" @click="handleChild"></div>
</div>
</template>
<script>
export default {
methods: {
handleParent(e) {
console.log("handleParent.....");
},
handleChild(e) {
console.log("handleChild.....");
e.stopPropagation()
},
},
};
</script>
<style lang="scss">
.parent {
position: absolute;
width: 150px;
height: 150px;
border-radius: 50%;
background-color: orange;
.child {
position: absolute;
width: 80px;
height: 80px;
border-radius: 50%;
background-color: springgreen;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
}
</style>
-
.stop事件修饰符的方式来进行阻止
<div class="parent" @click="handleParent">
<div class="child" @click.stop="handleChild"></div>
</div>
-
.self事件修饰符的方式来进行阻止
<div class="parent" @click.self="handleParent">
<div class="child" @click="handleChild"></div>
</div>
2.2、阻止默认行为
阻止默认行为有两种方式
-
通过原生js的方式来进行阻止:e.preventDefault()
-
通过prevent事件修饰符的方式进行阻止
<a href="http://www.baidu.com" @click.prevent="go">百度</a>
六、属性绑定指令
1、v-bind的基础使用
属性绑定的指令v-bind
这个指令也有简写形式:
<template>
<div>
<div>
<img v-bind:src="imgUrl" alt="">
</div>
<div>
<button @click="changePic">换图</button>
</div>
<hr>
<!-- v-bind的简写形式是: -->
<a :href="networkUrl">{{school}}</a>
<br>
<button @click="changeSchool">更换</button>
</div>
</template>
<script>
export default {
data(){
return{
imgUrl:'https://img1.baidu.com/it/u=3009731526,373851691&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500',
networkUrl:'http://www.baidu.com',
school:'百度'
}
},
methods:{
changePic(){
this.imgUrl="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Flmg.jj20.com%2Fup%2Fallimg%2F1114%2F121420113514%2F201214113514-6-1200.jpg&refer=http%3A%2F%2Flmg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1671179801&t=595266893ba6bb495fa1d43e213ae8b7"
},
changeSchool(){
this.school='百度',
this.networkUrl="http://old.baidu.com"
}
}
}
</script>
<style>
img{
width: 250px;
}
</style>
2、vue组件引入assets文件夹中的图片
由于该文件夹下的图片是被编译的,所有如果要加载使用三种方式
-
base64方式:建议图片大小不要超过10k
-
import导入方式
-
require方式导入
<template>
<div>
<img :src="picUrl" alt="" />
<img :src="logoUrl" alt="">
<img :src="starUrl" alt="">
</div>
</template>
<script>
import logo from './assets/logo.png'
export default {
data() {
return {
picUrl:"data:image/jpeg;base64,UklGRtQuAABXRUJQV",//该地址不全
logoUrl:logo,
starUrl:require('./assets/women.jpg')
};
},
};
</script>
七、数据变更检测
vue是具有响应式的操作,当数据变化之后,页面会自动更新,但是vue2针对如下几种情况,数据变化,页面不能更新
1、针对对象
如果对对象新增属性、删除属性数据变化,不能带来页面的变化
1)针对与新增属性,可以使用5种方式进行数据变更,具体如下
-
this.$set()
-
Vue.set()
-
ES6的扩展运算符
-
Object.assign()
-
this.,$forceUpdate()
<template>
<div>
<div>{{teacher}}</div>
<button @click="addAttrByObj">新增属性</button>
</div>
</template>
<script>
import Vue from 'vue'
export default {
data(){
return{
teacher:{
name:'Giles'
}
}
},
methods:{
addAttrByObj(){
//1、this.$set(this.teacher,'age',38)
//2、Vue.set(this.teacher,'age',38)
//3、ES6的对象的扩展运算符
// this.teacher={
// ...this.teacher,
// age:38
// }
//4、Object.assign()
//this.teacher=Object.assign({},this.teacher,{age:38})
//5、使用vue实例中的$forceUpdate()
this.teacher.age=38
this.$forceUpdate()
}
}
}
</script>
2)如果删除一个对象中的属性,也是检测不到的,解决办法如下
/*
删除对象中的属性,实现自动变更检测的方式如下
方式1:使用$forceUpdate()来实现
delete this.teacher.job//非响应式
this.$forceUpdate()
*/
方式2://this.$delete(this.teacher,'job')
Vue.delete(this.teacher,'job')
2、针对数组
operAry1(){
/*
this.names[4]="Jack"//非响应式
this.$forceUpdate()
*/
//this.$set(this.names,4,"Dollr")
Vue.set(this.names,4,"Dollr")
},
clearAry(){
//this.names.length=0//非响应式
//this.names=[]
this.names.splice(0)
}
八、样式操作
1、class类样式绑定
1)字符串语法
<template>
<div>
<div class="box" :class="cs" @click="operClsStyle"></div>
</div>
</template>
<script>
export default {
data(){
return{
cs:''
}
},
methods:{
operClsStyle(){
this.cs="c1"
}
}
}
</script>
<style>
.box{
width: 100px;
height: 100px;
border: 1px solid #000;
border-radius: 50%;
}
.c1{
background-color: orange;
}
</style>
2)数组语法
<template>
<div>
<div class="box" :class="csAry" @click="m1" @dblclick="m2" @mouseout="m3">🐌</div>
</div>
</template>
<script>
export default {
data(){
return{
csAry:[]
}
},
methods:{
m1(){
this.csAry.push('c1')
},
m2(){
this.csAry.push('c2')
},
m3(){
this.csAry.push('c3')
}
}
}
</script>
<style>
.box{
width: 100px;
height: 100px;
border: 1px solid #000;
border-radius: 50%;
transition: 3s;
text-align: center;
line-height: 100px;
}
.c1{
background: linear-gradient(red,tomato,orange,yellow);
}
.c2{
box-shadow: 10px 10px 10px gray;
}
.c3{
transform: rotate(360deg);
}
</style>
3)对象语法
<template>
<div>
<div :class="clsObj" @click="m1" @dblclick="m2" @mouseout="m3"></div>
</div>
</template>
<script>
import Vue from 'vue'
export default {
data(){
return{
clsObj:{
box:true
}
}
},
methods:{
m1(){
this.$set(this.clsObj,'c1',true)
},
m2(){
Vue.set(this.clsObj,'c2',true)
},
m3(){
this.clsObj={
...this.clsObj,
c3:true
}
}
}
}
</script>
<style>
.box{
width: 100px;
height: 100px;
border: 1px solid #000;
border-radius: 50%;
transition: 3s;
text-align: center;
line-height: 100px;
}
.c1{
background: linear-gradient(red,tomato,orange,yellow);
}
.c2{
box-shadow: 10px 10px 10px gray;
}
.c3{
transform: rotate(360deg);
}
</style>
2、style样式绑定
1)对象语法
<template>
<div>
<div class="box" v-bind:style="{backgroundColor:activeColor}" @click="changeBgColor"></div>
</div>
</template>
<script>
export default {
data(){
return{
activeColor:'red'
}
},
methods:{
changeBgColor(){
this.activeColor='springgreen'
}
}
}
</script>
<style>
.box{
width: 100px;
height: 100px;
border:1px solid #000;
border-radius: 50%;
}
</style>
2)数组语法
<template>
<div :style="styleAry" @click="addStyleToAry"></div>
</template>
<script>
export default {
data(){
return{
styleAry:[{
width:'100px',
height:'100px',
border:'1px dashed #ccc',
borderRadius:'50%'
}]
}
},
methods:{
addStyleToAry(){
this.styleAry.push({
backgroundColor:'#987879'
})
}
}
}
</script>
<style>
</style>
九、列表渲染指令
在vue中提供了v-for
指令用来渲染列表的
1、基本使用
语法
在列表项的开始标签上编写
<ul>
<li v-for="项变量 in 列表">{{项变量}}</li>
</ul>
案例:完成省份的动态渲染
<template>
<div>
<ul>
<!--
v-for用来动态的渲染列表的指令
-->
<li v-for="item in proviceList" :key="item">{{item}}</li>
</ul>
</div>
</template>
<script>
export default {
data(){
return{
proviceList:['西藏','宁夏','陕西','北京','天津','重庆','四川']
}
}
}
</script>
案例2:渲染学生列表
<template>
<div>
<table>
<thead>
<tr>
<th>序号</th>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>电话</th>
<th>地址</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!--
v-for的语法
v-for="(项变量,当前项所在的下标位置) in 集合"
下标位置是从0开始的
-->
<tr v-for="(item,index) in students" :key="index">
<td>{{index+1}}</td>
<td>{{item.sid}}</td>
<td>{{item.sname}}</td>
<td>{{item.age}}</td>
<td>{{item.telephone}}</td>
<td>{{item.address}}</td>
<td>
<button>查看</button><button>删除</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data(){
return{
students:[
{
sid:'1001',
sname:'刘备',
age:33,
telephone:'13324567890',
address:'凤城一路'
},
{
sid:'1002',
sname:'关羽',
age:33,
telephone:'13324567890',
address:'凤城一路'
},
{
sid:'1003',
sname:'张飞',
age:33,
telephone:'13324567890',
address:'凤城一路'
},
{
sid:'1004',
sname:'赵云',
age:33,
telephone:'13324567890',
address:'凤城一路'
},
{
sid:'1005',
sname:'马超',
age:32,
telephone:'13324567890',
address:'凤城一路'
}
]
}
}
}
</script>
<style>
table{
border-collapse: collapse;
}
thead tr{
background-color: #ccc;
}
td,th{
border: 1px solid #000;
padding: 10px;
text-align: center;
}
</style>
2、v-for嵌套
<ol>
<li v-for="(item,index) in stars" :key="index">
<h3>{{item.name}}</h3>
<ul>
<li v-for="(sitem,sindex) in item.sings" :key="sindex">
{{sitem.name}}
</li>
</ul>
</li>
</ol>
stars:[
{
id:'1001',
name:'李荣浩',
sings:[
{
sid:'s1001',
name:'李白'
},
{
sid:'s1002',
name:'王妃'
}
]
},
{
id:'1002',
name:'张学友',
sings:[
{
sid:'s2001',
name:'吻别'
},
{
sid:'s2002',
name:'最真心的朋友'
}
]
}
]
3、v-for中key值的作用
回答思路:
1)key的作用:为了提高渲染能力
2)key的虚拟DOM的对比规则
-
新旧虚拟DOMkey存在的情况下,:将key值相同的虚拟DOM进行比对,如果新的虚拟DOM和旧的一样,一样的部分直接复用旧的,如果内容不一样,则重新创建
-
新的虚拟DOM的key旧的虚拟DOM不存在:直接创建真实DOM
好处:可以减少真实DOM生成,大大提高列表的渲染能力
注意:key值一般的值选择列表选项中的对象的id,身份证等唯一标识该对象的,不建议选择index
4、v-for和v-if的优先级
回答思路:
1)v-if和v-for不建议一起使用,vue2版本v-for优先级高于v-if,vue3版本中v-if优先级高于v-for
2)通过查看官网文档,或者是测试vue实例的$options的render方法来完成
十、双向绑定指令
1、vue中操作DOM
操作DOM的步骤
-
在指定的DOM元素上添加ref属性
<div class="box" @click="changeBgc" ref="boxEle"></div>
-
在methods的相关方法中使用
this.$refs.ref属性值
获取DOM元素
export default {
methods:{
changeBgc(){
this.$refs.boxEle.style.backgroundColor="skyblue"
this.$refs.boxEle.innerHTML="🐌"
this.$refs.boxEle.style.textAlign="center"
this.$refs.boxEle.style.lineHeight="100px"
}
}
}
2、MVVM模式
MVVM是由三部分组成
-
view:用户数据展示的
-
Model:用于完成逻辑操作
-
ViewModel:是中间桥梁,它是联系View和Model的
一旦数据发生变化,视图会自动发生变化,由Data Bindings来完成的,使用到了Vue响应式原理,底层实现:使用劫持(对象:Object.defineProperty+数据:通过对数据中常用方法的重写来完成)+发布订阅模式
如果一旦view视图发生变化,ViewModel通过DOM Listeners监听也会自定检测到视图变化,也会通知Model中相应数据变化
3、v-model
使用v-model完成表单数据的收集,能够将表单控件和data的数据一一对应起来,如果数据变化后表单项中的内容,如果表单项内容改变了也会驱动data数据的变化
<template>
<div>
<h1>注册</h1>
<div>
<label for="name">姓名:</label>
<input id="name" type="text" v-model="user.name" />
</div>
<div>
<label for="sex">性别</label>
<input type="radio" name="gender" value="1" v-model="user.gender">男
<input type="radio" name="gender" value="2" v-model="user.gender">女
</div>
<div>
<label for="sex">省份:</label>
<select v-model="user.provice">
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">天津</option>
</select>
</div>
<div>
<label for="hobby">爱好</label>
<input type="checkbox" value="1" v-model="user.hobby">听音乐
<input type="checkbox" value="2" v-model="user.hobby">打篮球
<input type="checkbox" value="3" v-model="user.hobby">踢足球
<input type="checkbox" value="4" v-model="user.hobby">打乒乓
<input type="checkbox" value="5" v-model="user.hobby">打游戏
</div>
<div>
<button @click="register">注册</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
user: {
name: "",
gender:1,
provice:2,
hobby:[]
},
};
},
methods:{
register(){
console.log(this.user);
}
}
};
</script>
4、修饰符
4.1、lazy
在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步 (除了上述输入法组合文字时)。你可以添加 lazy
修饰符,从而转为在 change
事件之后进行同步:
<input v-model.lazy="name"/>
4.2、number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 number
修饰符:
<input v-model.number="age" type="number">
这通常很有用,因为即使在 type="number"
时,HTML 输入元素的值也总会返回字符串。如果这个值无法被 parseFloat()
解析,则会返回原始的值
4.3、trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model
添加 trim
修饰符:
<input v-model.trim="msg">
5、实现v-model
<template>
<div>
<input type="text" v-bind:value="msg" ref="msgInputEle" @input="getMsgInput">
</div>
</template>
<script>
export default {
data(){
return{
msg:''
}
},
methods:{
getMsgInput(){
this.msg=this.$refs.msgInputEle.value
}
}
}
</script>
<style>
</style>