Vue 基础指令(模板语法)
✍目录总览:(模板语法概述、基础指令)
Vue模板语法
1. 如何理解前端渲染?
- 把数据填充到HTML标签中
2. 前端渲染的方式
- 前端渲染的方式主要有三种:
- 原生js拼接字符串
- 使用前端模板引擎
- 使用vue特有的模板语法
2.1 原生js拼接字符串
- 基本上就是将数据以字符串的方式拼接到HTML标签中,前端代码风格大体上如下图所示。
var d = data.weather;
var info = document.getElementById('info');
info.innerHTML = '';
for(var i=0;i<d.length;i++){
var date = d[i].date;
var day = d[i].info.day;
var night = d[i].info.night;
var tag = '';
tag += '<span>日期:'+date+'</sapn><ul>';
tag += '<li>白天天气:'+day[1]+'</li>'
tag += '<li>白天温度:'+day[2]+'</li>'
tag += '<li>白天风向:'+day[3]+'</li>'
tag += '<li>白天风速:'+day[4]+'</li>'
tag += '</ul>';
var div = document.createElement('div');
div.innerHTML = tag;
info.appendChild(div);
}
**缺点:**不同开发人员的代码风格差别很大,随着业务的复杂,后期的维护变得逐渐困难起来。
2.2 使用前端模板引擎
- 下图代码是基于模板引擎art-template的一段代码,与拼接字符串相比,代码明显规范了很多,它拥有自己的一套模板语法规则。
<script id="abc" type="text/html">
{{if isAdmin}}
<h1>{{title}}</h1>
<ul>
{{each list as value i}}
<li>索引 {{i + 1}} :{{value}}</li>
{{/each}}
</ul>
{{/if}}
</script>
**优点:**大家都遵循同样的规则写代码,代码可读性明显提高了,方便后期的维护。
**缺点:**没有专门提供事件机制。
2.3 使用vue特有的模板语法(重点)
-
Vue基础指令:
-
差值表达式
-
指令
-
事件绑定
-
属性绑定
-
样式绑定
-
分支循环结构
-
Vue指令
一、内容渲染指令
1.1 插值表达式(mustache语法)
内容渲染指令就是插值操作,如何将data中的文本数据,插入到HTML中呢?插值表达式
可以通过Mustache语法(也就是 双大括号{{}}),也叫做插值表达式
- 双括号里面是变量
<div id="app">
<h1>{{message}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
message: '你好Vue3!'
}
}
}).mount('#app');
</script>
- 双括号里面是表达式
<div id="app">
<h1>{{message}}</h1>
<h1>{{message+site}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
message: '你好Vue3!',
site: 'www.newmood.top',
}
}
}).mount('#app');
</script>
- 双括号里面表达式加空格或者字符
<div id="app">
<h1>{{message}}</h1>
<h1>{{message+ '空格或者字符' + site}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
message: '你好Vue3!',
site: 'www.newmood.top',
}
}
}).mount('#app');
</script>
- 双括号后加双括号
<div id="app">
<h1>{{message}}</h1>
<h1>{{message}} {{site}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
message: '你好Vue3!',
site: 'www.newmood.top',
}
}
}).mount('#app');
</script>
- 双括号后跟字符
<div id="app">
<h1>{{message}}</h1>
<h1>{{message}},生命里那束光</h1>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
message: '你好Vue3!',
site: 'www.newmood.top',
}
}
}).mount('#app');
</script>
- 双括号只能写在标签内部,不能写在标签属性里面
<div id="app">
<h1>{{message}}</h1>
<!-- <h1 {{message}}> {{message}},生命里那束光 </h1> 报错-->
</div>
- 双括号里面还能进行变量计算
<div id="app">
<h1>{{message}}</h1>
<h1>计算{{count * 2}}</h1>
</div>
1.2 v-once
我们有时候希望展示的部分数据不会随着Vue的响应式而发生变化,要怎么做呢?先来看一个例子:
<div id="app">
<h1>会变化{{message}}</h1>
<h1>不会变化{{message}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
message: '你好Vue3',
}
}
}).mount('#app');
</script>
我们在Console控制台修改 app.messgae="Vue3"
,会发现message都发生了变化
要想第二个message不发生变化,我们给第二个h1标签添加v-once
属性
<div id="app">
<h1>会变化{{message}}</h1>
<h1 v-once>不会变化{{message}}</h1>
</div>
1.3 v-text
v-text
作用和 插值表达式
比较相似:都是用于将数据显示在界面中
v-text
是放在标签属性中
<div id="app">
<h1>{{message}}</h1>
<h1 v-text="message"></h1>
</div>
- 对于v-text和插值表达式语法,我们更推荐使用插值表达式语法。
1.4 v-html
某些情况下,我们从服务器请求到的数据本身就是一个HTML代码
-
如果我们直接通过{{}} 来输出,会将HTML代码也一起输出
-
但是我们希望是按照HTML格式进行解析,并且显示对应的内容
如果我们希望解析出HTML展示
- 可以使用v-html指令
- 该指令后面往往会跟上一个string类型
- 会将string的html解析出来并且进行渲染
我们来看一个插值表达式例子:
<div id="app">
<h1>{{site}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
message: '你好Vue3!',
site: '<a href="www.newmood.top">那束光の博客</a>'
}
}
}).mount('#app');
</script>
- 有时候服务器给客户端返回的数据是带标签的数据,我们客户端拿到之后解析肯定不能如上图那样直接使用 mustache 语法,我们要对其进行处理
1.5 v-pre
该指令的作用是用于跳过这个元素和它子元素的编译过程,用于显示原本的 Mustache 语法
一般我们的mustache语法会去data里面找对应的变量然后解析,可是如果我们就想让其显示为 {{message}}
,这个时候需要加 v-pre
属性,如下:
<div id="app">
<h1>{{message}}</h1>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
message: '你好Vue3!',
}
}
}).mount('#app');
</script>
我们给标签增加 v-pre
属性
<div id="app">
<h1 v-pre>{{message}}</h1>
</div>
1.6 v-cloak
在实际开发中,我们data里面的数据可能是从服务器端获取来的,如果网络不好获取的比较慢,浏览器可能会直接显示出未编译的Mustache标签。那么页面在渲染时可能会先显示 {{message}} 之后变为 你好Vue3!。这种效果不是我们想要的,我们可以给标签添加 v-cloak 来避免这种效果。
解决办法:
- 加上v-clock 属性,并加上css。
- vue解析之前有 v-clock 属性时,让其不显示
- Vue解析之后没有v-clock 属性,再让其显示
<style>
[v-cloak] {
display: none;
}
</style>
<div id="app">
<h1 v-cloak>{{message}}</h1>
</div>
<script>
// 在vue解析之前, div中有一个属性v-cloak
// 在vue解析之后, div中没有一个属性v-cloak
setTimeout(function () {
const app = new Vue({
el: '#app',
data: {
message: '你好Vue3!'
}
})
}, 1000)
</script>
二、属性绑定指令
2.1 v-bind
前面的指令主要作用是将值插入到我们的模板的内容当中,但是,除了内容需要动态来决定外,某些属性我们也希望动态来绑定。
- 比如动态绑定a元素的 href 属性
- 比如动态绑定img元素的 src 属性
绑定 href、src 用法
在实际开发中,照片img的url值可能也是由服务器端获取,a标签的href值可能也是由服务器端获取的,那么我们如何动态绑定呢?例如我们看下面的例子:
<div id="app">
<h1>{{message}}</h1>
<a href="url">百度</a>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
message: '你好Vue3!',
url: 'http://www.baidu.com'
}
}
}).mount('#app');
</script>
- 如上图,我们给a标签的href是不能直接写url的,因为它不会解析。这个时候就需要给href前添加
v-bind
指令了。
<div id="app">
<h1>{{message}}</h1>
<a v-bind:href="url">百度</a>
</div>
语法糖写法如下: :href="url"
<div id="app">
<h1>{{message}}</h1>
<a :href="url">百度</a>
</div>
三、样式绑定指令
3.1 class样式处理
- 对象语法
<div v-bind:class="{ active: isActive }"></div>
- 数组语法
<div v-bind:class="[activeClass, errorClass]"></div>
样式绑定相关语法细节:
- 对象绑定和数组绑定可以结合使用
<div v-bind:class='[activeClass, errorClass, {test: isTest}]'>测试样式</div>
data: {
activeClass: 'active',
errorClass: 'error',
isTest: true
}
- class绑定的值可以简化处理
<div v-bind:class='arrClasses'>测试样式</div>
data: {
arrClasses: ['active', 'error']
}
- 默认的class会保留(base)
3.2 style样式处理
- 对象语法
<div v-bind:style="{ color: activeColor, fontSize: fontSize }"></div>
- 数组语法
<div v-bind:style="[baseStyles, overridingStyles]"></div>
四、事件监听指令
4.1 v-on
1. Vue如何处理事件?
- v-on指令用法
<input type=‘button' v-on:click='num++'/>
- v-on简写形式
<input type=‘button' @click='num++'/>
2. 事件函数的调用方式
- 直接绑定函数名称
<button v-on:click='say'>Hello</button>
- 调用函数
<button v-on:click='say()'>Say hi</button>
3. 事件函数参数传递
- 普通参数和事件对象
<button v-on:click='say("hi",$event)'>Say hi</button>
4.2 v-on修饰符
4. 事件修饰符
- .stop 阻止冒泡
<a v-on:click.stop="handle">跳转</a>
- .prevent 阻止默认行为
<a v-on:click.prevent="handle">跳转</a>
5. 按键修饰符
- .enter 回车键
<input v-on:keyup.enter='submit'>
- .esc 退出键
<input v-on:keyup.delete='handle'>
6. 自定义按键修饰符
- 全局 config.keyCodes 对象
Vue.config.keyCodes.f1 = 112
4.3 小结
.stop
- 调用event.stopPropagation()
.prevent
- 调用event.preventDefault()
.{keyCode|keyAlias}
- 只当事件是从特定键触发时才触发回调.once
- 只触发一次回调
五、条件渲染指令(分支结构)
条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏 。
v - if、
v-else-if、
v-else
- 这三个指令与JavaScript的条件语句 if、else、else if 类似
- Vue 的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件
5.1 v-if
<div id="app">
<p v-if="flag">今天要下雨</p>
<p v-else>今天不要下雨</p>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return{
flag: true
}
}
}).mount('#app');
</script>
</body>
v-if
的原理:
v-if
后面的条件为 false时,对应的元素以及子元素不会渲染- 也就是根本没有对应的标签出现在DOM中
5.2 v-if、v-else-if、v-else
我们一般不会使用 v-else-if,因为这样的代码不美观,我们一般想要切换的话使用如下代码:
<body>
<div id="app">
<p v-if="flag">今天要下雨</p>
<p v-else>今天不要下雨</p>
<button @click="toggle()">切换</button>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return{
flag: true
}
},
methods:{
toggle(){
return this.flag = !this.flag;
}
}
}).mount('#app');
</script>
</body>
5.3 v-show
v-show
的用法和v-if
非常相似,也用于决定一个元素是否渲染:
v-if
指令会 动态地创建或移除 DOM 元素 ,从而控制元素在页面上的显示与隐藏v-show
指令会动态为元素 添加或移除 style=“display: none;” 样式 ,从而控制元素的显示与隐藏
<body>
<div id="app">
<p v-show="flag">今天要下雨</p>
<p v-show="!flag">今天不要下雨</p>
<button @click="toggle()">切换</button>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return{
flag: true
}
},
methods:{
toggle(){
return this.flag = !this.flag;
}
}
}).mount('#app');
</script>
</body>
5.4 v-if与v-show的区别
- v-if控制元素是否渲染到页面(是否创建)
- v-show控制元素是否显示(已经创建,是否显示)
- 当需要在显示与隐藏之间切片很频繁时,使用
v-show
- 当只有一次切换时,通过
v-if
六、列表渲染指令(循环结构)
6.1 v-for(遍历数组)
- 遍历数组
//语法1
<li v-for='item in list'>{{item}}</li>
//语法2
<li v-for='(item,index) in list'>{{item}} + '---' +{{index}}</li>
例子:
<div>水果列表</div>
<ul>
<li :key='item.id' v-for='(item, index) in myFruits'>
<span>{{item.ename}}</span>
<span>-----</span>
<span>{{item.cname}}</span>
</li>
</ul>
</div>
data: {
fruits: ['apple', 'orange', 'banana'],
myFruits: [{
id: 1,
ename: 'apple',
cname: '苹果'
}, {
id: 2,
ename: 'orange',
cname: '橘子'
}, {
id: 3,
ename: 'banana',
cname: '香蕉'
}]
}
6.2 组件的key属性
-
官方推荐我们在使用 v-for时,给对应的元素或组件加上一个 :key属性,key的作用主要是为了高效的更新虚拟DOM
-
当列表的数据变化时,默认情况下, vue 会尽可能的复用已存在的 DOM 元素,从而提升渲染的性能 。
-
但这种默认的性能优化策略,会导致有状态的列表无法被正确更新 。为了给 vue 一个提示,以便它能跟踪每个节点的身份, 从而在保证有状态的列表被正确更新的前提下, 提升渲染的性能 。此时,需要为每项提供一个唯一的 key 属性
<div id="app">
<ul>
<li v-for="item in myFruits" :key="item">{{item.id}}</li>
</ul>
</div>
- key 的值只能是字符串或数字类型
- key 的值必须具有唯一性(即:key 的值不能重复)
- 建议把 数据项 id 属性的值 作为 key 的值(因为 id 属性的值具有唯一性)
- 使用 index 的值当作 key 的值没有任何意义(因为 index 的值不具有唯一性)
- 建议使用 v-for 指令时一定要指定 key 的值(既提升性能、又防止列表状态紊乱)
不绑定key的后果:
- 向数组添加数据
6.3 v-for(遍历对象)
<div v-for='(value, key, index) in object'></div>
v-if和v-for结合使用
<div v-if='value==12' v-for='(value, key, index) in object'></div>
例子:
//v-if判断值为13的记录,进行输出 v-for对obj里面的属性进行遍历
<div id="app">
<div v-if='v==13' v-for='(v,k,i) in obj'>{{v + '---' + k + '---' + i}}</div>
</div>
//定义的对象
data: {
obj: {
uname: 'zhangsan',
age: 13,
gender: 'female'
}
}
七、双向绑定指令
7.1 v-model
- 双向绑定指令也叫表单元素绑定,vue提供了
v-model
双向数据绑定 指令,用来辅助开发者在 不操作 DOM 的前提下, 快速获取表单的数据。 - vue中使用
v-model
指令来实现表单元素和数据的双向绑定,经常用于表单 input 和 textarea 元素。
<body>
<div id="app">
<input type="text" v-model="message">
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
message: '你好Vue3!'
}
}
}).mount('#app');
</script>
</body>
理解双向绑定:
- 我们来看上述代码,当我们在输入框输入内容时
- 因为 input 中的 v-model 绑定了message,所以会实时的将输入的内容传递给 message,message发生改变。
- 当message 发生改变时,因为上面我们使用 Mustache 语法,将 message 的值插入到 DOM 中,所以 DOM 会发生响应的改变。
- 所以,通过 v-model 实现了 双向的绑定
7.2 v-model底层原理实现
v-model
其实是一个语法糖,它的背后本质上是包含两个操作:
v-bind
绑定一个 value 属性v-on
指令给当前元素绑定 input 事件
也就是说下面的代码,等同于下面的代码:
<input type="text" v-model="message">
<!-- 等同于 -->
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
7.3 dom类型与 v-model
v-model:radio(单选框)
使得单选框只能选一个
<body>
<div id="app">
<label><input name="sex" type="radio" value="男" v-model="sex">男</label>
<label><input name="sex" type="radio" value="女" v-model="sex">女</label>
<h2>选择的性别是:{{sex}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
sex: '男'
}
}
}).mount('#app');
</script>
</body>
v-model:checkbox(单/多勾选框)
复选框分为两种情况:单个勾选框和多个勾选框
v-moduel
即为布尔值- 此时 input 的 value 并不影响
v-model
的值
<body>
<div id="app">
<label><input type="checkbox" v-model="isAgree">同意会员协议</label>
<h2>是否同意协议:{{isAgree ? '同意' : '不同意'}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
isAgree: 'false'
}
}
}).mount('#app');
</script>
</body>
- 当是多个复选框时,因为可以选中多个,所以对应的 data 中属性是一个数组
- 当选中某一个时,就会将 input 的 value 添加到数组中
<body>
<div id="app">
<input type="checkbox" value="篮球" v-model="hobbies">篮球
<input type="checkbox" value="足球" v-model="hobbies">足球
<input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
<input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球
<h2>您的爱好是: {{hobbies}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = Vue.createApp({
data(){
return {
hobbies: [], // 多选框,
}
}
}).mount('#app');
</script>
</body>
v-model:select(单选/多选下拉表单)
和 checkbox 一样,select 也分单选和多选两种情况
v-model
绑定的是一个值- 当我们选中 option 中的一个时,会将它对应的 vaule 赋值到 city 中
<body>
<div id="app">
<p>选择所在的城市:</p>
<select name="city" v-model="city">
<option value="上海">上海</option>
<option value="北京">北京</option>
<option value="天津">天津</option>
</select>
<p>选择的城市是:{{city}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
city: '上海'
}
}
}).mount('#app');
</script>
</body>
v-model
绑定的是一个数组- 当选中多个值时,就会将选中的 option 对应的 value 添加到数组 mySelects中
<body>
<div id="app">
<p>选择所在的城市:</p>
<select name="cities" v-model="cities" multiple>
<option value="上海">上海</option>
<option value="北京">北京</option>
<option value="天津">天津</option>
</select>
<p>选择的城市是:{{cities}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建Vue的实例对象
const app = Vue.createApp({
data(){
return {
cities: []
}
}
}).mount('#app');
</script>
</body>
7.4 v-model修饰符
为了方便对用户输入的内容进行处理,vue 为 v-model 指令提供了 3 个修饰符
修饰符 | 作用 | 示例 |
---|---|---|
.number | 自动将用户的输入值转化为数值类型 | <input v-model.number = "age" /> |
.trim | 自动过滤用户输入的首尾空白字符 | <input v-module.trim = "msg" /> |
.lazy | 在 change 时而非 input 时更新(失去焦点或回车时) | <input v-model.lazy = "msg" /> |