一、v-once
顾名思义,元素和组件只渲染一次,不会随着数据变化而变化
<h2>{{message}}</h2>
<h2 v-once>{{message}}</h2>
第一次渲染完成后,data中的message改变,第一个h2会随之改变,第二个h2不会改变
二、v-html
若字符串是html代码,v-html指令可以将html代码进行解析
<body>
<div id="app">
<h2>{{url}}</h2>
<h2 v-html="url"></h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
url: '<a href="http://www.baidu.com">百度一下</a>'
}
})
</script>
</body>
三、v-text
<h2>{{message}}</h2>
<h2 v-text="message"></h2>
这两个语句的效果是一样的
但是一般不会使用v-text指令,因为太不灵活,例如:
<body>
<div id="app">
<h2>{{message}},世界</h2>
<h2 v-text="message">,世界</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好'
}
})
</script>
</body>
v-text指令会覆盖标签的内容,不能灵活进行字符串拼接
四、v-pre
跳过这个元素和它的子元素的编译过程,显示原本的内容,一般也不会用
<h2>{{message}}</h2>
<h2 v-pre>{{message}}</h2>
五、v-cloak
- 在某些情况下,js代码执行可能遇到卡顿,或js代码执行有延迟,会导致vue没有被及时的加载出来,这会导致浏览器直接显示未编译的Mustache标签
- 为了避免这种情况,可以加入v-cloak指令,然后给这一指令加入特定css样式
- 在vue解析之前,标签中有一个属性v-cloak;在vue解析之后,标签中没有一个属性v-cloak
- 下面的代码中,我们用
setTimeout
模拟js执行延迟;div没有v-cloak指令会先显示一段{{message}}
再显示内容,div有v-cloak指令会先空白一段(这是设置的样式)再显示内容
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<h2>{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
setTimeout(function () {
const app = new Vue({
el: '#app',
data: {
message: '你好'
}
})
}, 1000)
</script>
</body>
六、v-bind
用于动态绑定属性
- 比如动态绑定a元素的href属性
- 比如动态绑定img元素的src属性
<div id="app">
<img v-bind:src="imgurl" alt=""><br>
<a v-bind:href="ahref">百度一下</a>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
imgurl: 'https://img-blog.csdnimg.cn/20200409165249908.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1NTU19CZW5qYW1pbg==,size_16,color_FFFFFF,t_70#pic_center',
ahref: 'http://www.baidu.com'
}
})
</script>
</body>
语法糖: v-bind:src
简写为:src
<img :src="imgurl" alt=""><br>
<a :href="ahref">百度一下</a>
v-bind动态绑定class的对象语法
- class作为一个属性也可以通过v-bind进行动态绑定
- 可以使用一种更方便的方式进行class的动态绑定:通过对象
v-bind:class=""
引号中可以放一个对象,对象中是键值对,键值对可以是类名加一个布尔型变量,当布尔型变量为true时这个类添加到该标签,为false时不添加这个类 - 下面的例子用这种方式实现点击按钮切换文字颜色
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<style>
.active{
color: red;
}
</style>
<body>
<div id="app">
<h2 :class="{active: isActive, line: isLine}">{{message}}</h2>
<button @click="btnClick">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好!',
isActive: true,
isLine: true
},
methods: {
btnClick: function () {
this.isActive = !this.isActive
}
}
})
</script>
</body>
- 可以通过函数返回的方式缩短该行标签的长度
<div id="app">
<h2 :class="{active: isActive, line: isLine}">{{message}}</h2>
<h2 :class="getClasses()">{{message}}</h2>
<button @click="btnClick">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好!',
isActive: true,
isLine: true
},
methods: {
btnClick: function () {
this.isActive = !this.isActive
},
getClasses: function () {
return {active: this.isActive, line: this.isLine}
}
}
})
</script>
</body>
两行h2的变化是相同的
v-bind动态绑定class的数组语法
用的很少
<h2 :class="['active','line']">{{message}}</h2>
<!--这两行代码效果是一样的-->
<h2 class="active line">{{message}}</h2>
数组里面也可以是变量,变量的值是字符串,字符串是class的名字
<h2 :class="[active,line]">{{message}}</h2>
标签在动态绑定class的同时还可以有静态绑定的class
解析时会进行合并
<h2 class="title" :class="{active: true, line: false}">{{message}}</h2>
v-for与v-bind结合
下面实现列表中点击哪条就哪条变色(active类与上面的相同,这不重要)
<body>
<div id="app">
<ul>
<li v-for="(m, index) in movies" @click="cur = index" :class="cur == index ? 'active' : ''">{{m}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
movies: ['大赢家','囧妈','大黄蜂','无问西东'],
cur: 5
}
})
</script>
</body>
v-bind动态绑定style的对象语法
与动态绑定class的对象语法类似,键值对是css属性名和属性值
<body>
<div id="app">
<h2 :style="{fontSize: finalSize + 'px', backgroundColor: finalColor}">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好!',
finalSize: 100,
finalColor: 'red'
}
})
</script>
</body>
font-size
、background-color
这种属性要写成驼峰命名法的形式fontSize
、backgroundColor
,-
会被解析成操作符- 属性值为具体数值时要加上单引号写成字符串的形式,否则会当做一个变量去解析
<h2 :style="{fontSize: '50px'}">{{message}}</h2>
- 也可以通过上面
getClasses()
函数返回的方式缩短该行标签长度
v-bind动态绑定style的数组语法
与动态绑定class的数组语法类似,更加注重将对象放进数组
<body>
<div id="app">
<h2 :style="[baseStyle1, baseStyle2]">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好!',
baseStyle1: {backgroundColor: 'red'},
baseStyle2: {fontSize: '100px'}
}
})
</script>
</body>
有关methods中函数的写法:ES6中对象字面量的增强写法
七、事件监听 v-on
基本使用
<body>
<div id="app">
<h2>当前计数:{{counter}}</h2>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increment() {
console.log('increment被执行');
this.counter++
},
decrement() {
console.log('decrement被执行');
this.counter--
}
}
})
</script>
</body>
语法糖: 简写 v-on:click
简写为@click
<button @click="increment">+</button>
<button @click="decrement">-</button>
如果绑定的操作很简单,无需绑定函数,也可以下面这样
<body>
<div id="app">
<h2>当前计数:{{counter}}</h2>
<button @click="counter++">+</button>
<button @click="counter--">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
counter: 0
}
})
</script>
</body>
传递参数
<body>
<div id="app">
<!--事件调用的方法没有参数-->
<button @click="btn1Click()">按钮1.1</button>
<button @click="btn1Click">按钮1.2</button>
<!--在事件定义时,写方法时省略了小括号,但是方法本身需要参数-->
<!--这种情况vue会默认将浏览器生成的event事件对象作为参数传入到方法-->
<button @click="btn2Click(123)">按钮2.1</button>
<button @click="btn2Click()">按钮2.2</button>
<button @click="btn2Click">按钮2.3</button>
<!--方法定义时,我们需要event对象,同时又需要其他参数-->
<button @click="btn3Click">按钮3.1</button>
<button @click="btn3Click(123, event)">按钮3.2</button>
<button @click="btn3Click(123, $event)">按钮3.3</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
},
methods: {
btn1Click() {
console.log("btn1Click");
},
btn2Click(abc) {
console.log(abc);
},
btn3Click(abc, event) {
console.log(abc, event);
}
}
})
</script>
</body>
1. 事件调用的方法没有参数
按钮1.1 按钮1.2
- 没有参数时,方法名后面的括号可有可无
2. 事件调用的方法需要参数
按钮2.1 按钮2.2 按钮2.3
- 按钮2.1可以正常传参
- 按钮2.2未传入参数,打印出undefined,与普通的JavaScript函数调用未传参是一样的
- 按钮2.3方法名后没有括号,这种情况vue会默认将浏览器生成的event事件对象作为参数传入到方法
3. 需要event对象,同时又需要其他参数
按钮3.1 按钮3.2 按钮3.3
- 按钮3.1方法名后没有括号,vue将浏览器生成的event传给第一个参数abc后打印,第二个参数event没有东西传入打印出undefined
- 按钮3.2那样写是错误的,event被当做一个变量,会在data中寻找这个变量,未定义则会报错
- 按钮3.3是正确写法
修饰符
<body>
<div id="app">
<!--1. .stop修饰符的使用-->
<!--阻止事件冒泡-->
<div @click="divClick">
aaaaaaa
<button @click.stop="btnClick">按钮</button>
</div>
<!--2. .prevent修饰符的使用-->
<!--取消默认事件-->
<br>
<form action="baidu">
<input type="submit" value="提交" @click.prevent="submitClick"></input>
</form>
<!--3. 监听某个键盘的键帽-->
<!--特定按键触发时回调-->
<!--格式:键修饰符.键别名(keyAlias)或键代码(keyCode)-->
<input type="text" @keyup.enter="keyUp">
<!--4. .once修饰符的使用-->
<!--只触发一次回调-->
<br>
<button @click.once="btn2Click">按钮2</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
},
methods: {
divClick() {
console.log('divClick');
},
btnClick() {
console.log('btnClick');
},
submitClick() {
console.log('submitClick');
},
keyUp() {
console.log('keyUp')
},
btn2Click() {
console.log('btn2Click');
},
}
})
</script>
</body>
- 知识点补充:事件冒泡与事件捕获、原生JS阻止冒泡和取消默认事件
- 默认事件:比如a标签默认点击会跳转,type为submit的input标签默认点击会提交,这些都是默认事件,上面的示例中.prevent修饰符会使input标签点击后不提交仅执行绑定的点击事件
八、条件判断
v-if
<body>
<div id="app">
<h2 v-if="isShow">
<div>{{message}}</div>
<div>{{message}}</div>
<div>{{message}}</div>
<div>{{message}}</div>
</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊世界!',
isShow: true
}
})
</script>
</body>
v-else-if与v-else
<body>
<div id="app">
<h2 v-if="score>=90">优秀</h2>
<h2 v-else-if="score>=80">良好</h2>
<h2 v-else-if="score>=60">及格</h2>
<h2 v-else>不及格</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
score: 66
}
})
</script>
</body>
- 但是这样复杂的逻辑判断如果用v-else-if指令写会显得很麻烦且不易阅读,所以v-else-if指令不常用
- 可以用计算属性写成下面的形式
<body>
<div id="app">
<h2>{{result}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
score: 66
},
computed: {
result() {
let showMessage = '';
if (this.score >= 90) {
showMessage = '优秀'
} else if (this.score >= 80) {
showMessage = '良好'
} else if (this.score >= 60) {
showMessage = '及格'
} else {
showMessage = '不及格'
}
return showMessage
}
}
})
</script>
</body>
用户登录方式切换的案例
点击按钮实现登录方式的切换
<body>
<div id="app">
<span v-if="isUser">
<label for="username">用户账号</label>
<input type="text" id="username" placeholder="用户账号">
</span>
<span v-else>
<label for="email">用户邮箱</label>
<input type="text" id="email" placeholder="用户邮箱">
</span>
<button @click="isUser = !isUser">切换类型</button>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
isUser: true
}
})
</script>
</body>
案例中的小问题
在本案例中,若在输入框中输入内容之后再点击按钮,会发现切换后输入框中的内容依然存在没有被清除
- 原因:这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素
- 在本案例中,虚拟DOM中会对两个input和label进行对比,将不一样的内容进行修改,剩下的就用之前的
- 解决方案:如果不希望出现类似重复利用的问题,可以给对应的元素添加key,并且保证key的不同;若key相同,则被认为是可以复用的
<div id="app">
<span v-if="isUser">
<label for="username">用户账号</label>
<input type="text" id="username" placeholder="用户账号" key="username">
</span>
<span v-else>
<label for="email">用户邮箱</label>
<input type="text" id="email" placeholder="用户邮箱" key="email">
</span>
<button @click="isUser = !isUser">切换类型</button>
</div>
v-show
v-show与v-if的用法相同,控制节点的方式不同
<div v-show="isShow">{{msg}}</div>
- v-show控制的是节点的display属性,v-if是将节点从DOM中删除了,这一点可以通过F12看到
- 所以如果节点需要频繁的显示隐藏,使用v-show性能更佳;只有一次切换,使用v-if
v-for遍历
1.遍历数组
<body>
<div id="app">
<!-- 遍历过程中没有使用索引值(下标值) -->
<ul>
<li v-for="item in names">{{item}}</li>
</ul>
<!-- 遍历过程中获取使用索引值(下标值) -->
<ul>
<li v-for="(item, index) in names">{{index + 1}}.{{item}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊世界!',
names: ['hammer', 'sister', 'hs']
}
})
</script>
</body>
2.遍历对象
<body>
<div id="app">
<!-- 只获取一个值,取到的是value -->
<ul>
<li v-for="item in info">{{item}}</li>
</ul>
<!-- 获取key和value -->
<ul>
<li v-for="(value, key) in info">{{key}}-{{value}}</li>
</ul>
<!-- 获取key和value和index -->
<ul>
<li v-for="(value, key, index) in info">{{index}}-{{key}}-{{value}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
info: {
name: 'hammer',
age: 20,
height: 1.81
}
}
})
</script>
</body>
key
<body>
<div id="app">
<ul>
<!-- 绑定key的时候要绑定和item一一对应唯一性的 -->
<!-- 这个地方不能绑定index,index与item不是一一对应唯一性的,例如在中间插上一个元素,后面的index全都变了 -->
<!-- 但如果有重复元素的数组,也不能绑定item -->
<li v-for="item in letters" :key="item">{{item}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
letters: ['A','B','C','D','E','F']
}
})
</script>