附:「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」
1. 模板语法
1.1 什么是模板语法?
Vue中在 template 里写HTML,这个就是模板语法。示例代码如下:
<template>
<div :class="active ? active : '' ">Hello World</div>
</template>
1.2 开发模式:React VS Vue
(1)React
- React使用的 jsx ,所以对应的代码就是编写的类似于JS的一种语法。之后通过Babel将jsx编译成 React.createElement 函数调用。
(2)Vue
- Vue也支持jsx的开发模式,但是大多数情况下,使用基于HTML的模板语法
- 在模板中,允许开发者以声明式的方式将 DOM 和 底层组件实例的数据 绑定在一起。
- 在底层的实现中,Vue将模板编译成虚拟DOM渲染函数。
1.3 Mustche双大括号语法
如果我们希望把数据显示到模板(template)中,使用最多的语法是“Mustache”语法(双大括号)的文本插值。示例代码如下:
(1)正确的用法:
<!-- 1. Mustache的基本使用 -->
<div>{{ message }}</div>
<!-- 2. 里面可以写表达式 -->
<div>{{ count * 10}}</div>
<div>{{ message.split(" ").reverse().join(" ") }}</div>
<!-- 3. 支持三元运算符 -->
<div>{{ isShow ? '哈哈哈' : ''}}</div>
<button @click="toggle">切换</button>
<!-- 4. 也可以用计算属性 -->
<div>{{ getReverseMessage }}</div>
(2)错误用法
<!-- 1. 不能写赋值语句 -->
<div>{{ var name = "abc"}}</div>
<!-- 2. 不能写if语句 -->
<div>{{ if(isShow) return "哈哈哈"}}</div>
2. 基本指令
2.1 v-once
- 该指令用于指定元素或者组件只渲染一次。当数据发生变化时,元素或者组件以及其所有的子元素将视为静态内容并且跳过。
- 该指令可以用于性能优化。
<div>当前计数:{{ count }}</div>
<div v-once>当前计数:{{ count }}</div>
<button @click="add">+1</button>
2.2 v-text
该指令用于更新元素的文本内容
<div v-text="message"></div>
<!-- 上面代码相当于 <div>{{message}}</div> -->
输出结果:
2.3 v-html
- 默认情况下,如果要展示的内容本身是 html 的,那么vue并不会对其进行特殊的解析。
- 如果我们希望这个内容被Vue可以解析出来,那么可以使用 v-html 来展示。
<body>
<div id="app"></div>
<template id="my-app">
<div v-html="info"></div>
</template>
<script src="js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
info: `<span style="color: red; font-size: 22px">哈哈哈</span>`
}
},
methods: {}
}
Vue.createApp(App).mount('#app');
</script>
</body>
输出结果:
2.4 v-pre
- 该指令用于跳过元素和它的子元素的编译过程,显示原始的Mustache标签。跳过不需要编译的节点,加快编译的速度。
<template id="my-app">
<div v-pre>这个是添加v-pre的:{{ message }}</div>
<div>这个是没有添加v-pre的:{{ message }}</div>
</template>
输出结果:
2.5 v-bind 绑定属性、class、style
- 该指令用于给属性动态绑定。比如动态绑定a元素的href属性或者是动态绑定img元素的src属性。
- v-bind可以绑定一个或多个属性值,或者向另一个组件传递props值。
- v-bind的语法糖写法是
:
<!-- 1. v-bind的基本使用 -->
<img v-bind:src="imgUrl">
<a v-bind:href="link" target="_blank">百度一下</a>
<!-- 2. v-bind的语法糖 -->
<img :src="imgUrl">
<a :href="link" target="_blank">百度一下</a>
输出结果:
2.5.1 绑定class
在开发中,有时候我们的元素class也是动态的,比如:当数据为某个状态时,字体显示红色。当数据另一个状态时,字体显示黑色。class一般都是键值对的写法,如果值为true就加class,反则不加
绑定class有两种方式:对象语法、数组语法
(1)对象语法
<template id="my-app">
<!-- 1. 普通的绑定方式 -->
<div :class="className">{{ message }}</div>
<!-- 2. 对象绑定 -->
<!-- 动态添加类名,value为true会给当前元素添加类名,false则不添加 -->
<div class="xiaohe1" :class="{xiaohe2:false,xiaohe3: true}">{{ message }}</div>
<!-- 3. 绑定对象 -->
<div :class="classObj">{{ message }}</div>
<!-- 4. 从methods中获取添加 -->
<div :class="classObj2()">{{ message }}</div>
</template>
<script>
export default {
data(){
return {
message: "Hello World",
className: 'xiaohe',
classObj:{
xiaohe1: true,
xiaohe2: true,
xiaohe3: false
}
}
},
methods: {
classObj2(){
return {
xiaohe4: true,
xiaohe5: true
}
}
}
}
</script>
(2)数组语法
<body>
<div id="app"></div>
<template id="my-app">
<div :class="['abc1', title]">哈哈哈哈</div>
<div :class="['abc1', title, isActive ? 'active': '']">哈哈哈哈</div>
<div :class="['abc1', title, {active: isActive}]">哈哈哈哈</div>
</template>
<script src="../js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
title: "abc2",
isActive: true
}
}
}
Vue.createApp(App).mount('#app');
</script>
</body>
(3)注意事项
- key和value可以不用加引号,如:container:true
- 默认class和动态class可以结合使用
2.5.2 绑定style
我们可以利用 v-bind:style 来绑定一些CSS内联样式,比如某段文字的颜色、大小等
绑定style有两种方式:对象语法、数组语法
(1)对象语法
<body>
<div id="app"></div>
<template id="my-app">
<!-- 1. 基本使用 -->
<div :style="{color: 'red' , fontSize: '30px' }">{{message}}</div>
<!-- 2. 对象数据 -->
<div :style="styleObj">{{ message }}</div>
<!-- 3. 调用一个方法 -->
<div :style="styleObj2()">{{ message }}</div>
</template>
<script src="js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
styleObj:{
'font-size': '30px',
'color': 'red',
'background-color': 'skyblue'
}
}
},
methods: {
styleObj2(){
return {
'font-size': '30px',
'color': 'red',
'background-color': 'green'
}
}
}
}
Vue.createApp(App).mount('#app');
</script>
</body>
输出结果:
(2)数组语法
<body>
<div id="app"></div>
<template id="my-app">
<div :style="[styleObj1]">{{message}}</div>
</template>
<script src="js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
styleObj1:{
'font-size': '30px',
'color': 'red',
'background-color': 'green'
}
}
},
}
Vue.createApp(App).mount('#app');
</script>
</body>
输出结果:
(3)注意事项
- key可以不用加引号,但是value一定要加。如:font-size: "24px"。与绑定style不一样,要注意一下
- font-size 这样多一个
-的写法,绑定style是不认识的这种写法的,会报错。如果一定要使用,可以用引号圈起来,如:'font-size' 或者使用驼峰语法 fontSize ,
2.5.3 动态绑定属性
在某些情况下,我们属性的名称可能也不是固定的:
- 前端我们无论绑定src、href、class、style,属性名称都是固定的
- 如果属性名称不是固定的,我们可以使用
:[属性名] = "值"的格式来定义
- 这种绑定的方式,我们称之为动态绑定属性
<template id="my-app">
<!-- 1. 绑定单个属性名称 -->
<div :[name]="value">{{message}}</div>
<!-- 2. 绑定一个对象的属性名称 -->
<div v-bind="info">{{message}}</div>
</template>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
name: 'name1',
value: 'xiaohe',
info: {
name: 'xiaohe',
age: 18,
hobby: 'run'
}
}
},
}
</script>
输出结果:
2.6 v-on 绑定事件
- 该指令用于监听用户发生的事件,比如点击、拖拽、键盘事件等等
2.6.1 基本使用
<template id="my-app">
<div>{{ count }}</div>
<!-- 1. 绑定一个表达式 -->
<button @click="btnClick1">按钮1</button>
<!-- 2. 绑定到一个 methods 方法中 -->
<button @click="btnClick2">按钮2</button>
<!-- 3. 绑定鼠标移动事件 -->
<div class="box" @mousemove="mouseMove">mousemove</div>
<!-- 4. 绑定多个事件 -->
<!-- 事件名: 事件处理函数-->
<div v-on="{click:btnClick3, mousemove: mouseMove2}" class="box2">click、mousemove</div>
</template>
<script>
const App = {
template: '#my-app',
data() {
return {
count: 0
}
},
methods: {
btnClick1(){
this.count++
},
btnClick2(){
this.count++
},
mouseMove(){
console.log('鼠标移动了');
},
btnClick3(){
this.count++
}
}
}
</script>
2.6.2 参数传递
<template id="my-app">
<div>{{ count }}</div>
<!-- 1. 默认会把 event 对象传入 -->
<button @click="btnClick">+1</button>
<!-- 2. 传入其他参数 -->
<!-- 如果需要传递其他参数,需要使用$event-->
<button @click="btnClick2($event, 'xiaohe')">+1</button>
</template>
<script>
const App = {
template: '#my-app',
data() {
return {
count: 0
}
},
methods: {
btnClick(event){
console.log(event);
},
btnClick2(event,name){
console.log(event,name);
}
},
}
</script>
注意事项:
- 如果该方法不需要额外参数,那么方法后的()可以不添加。但是要注意,如果方法本身中有一个参数,那么会默认将原生事件 event 参数传递进去。
- 如果需要同时传入某个参数,同时需要 event 时,可以通过$event传入事件。
2.6.3 修饰符
v-on支持修饰符,修饰符相当于对事件进行了一些特殊的处理,示例代码如下:
<template id="my-app">
<!-- 修饰符 -->
<!-- 1. 默认当我们点击按钮的时候,事件处理函数会冒泡到 divClick,当我们在按钮上加了.stop,就会阻止冒泡了 -->
<div @click="divClick">
<button @click.stop="btnClick">按钮</button>
</div>
<!-- 2. 回车后才触发 -->
<input type="text" @keyup.enter="onEnter">
</template>
<script src="js/vue.js"></script>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
}
},
methods: {
divClick() {
console.log('divClick');
},
btnClick() {
console.log('btnClick');
},
onEnter(event) {
console.log(event.target.value);
}
}
}
</script>
3. 条件渲染
3.1 v-if、v-else-if、v-else
该指令用于根据条件来渲染某一块的内容,这些内容只有在条件为 true 时,才会被渲染出来。示例代码如下:
3.1.1 单个内容使用(v-if)
<template id="my-app">
<div v-if="isShow">{{ message }}</div>
<button @click="toggle">切换</button>
</template>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
isShow: true
}
},
methods: {
toggle(){
this.isShow = !this.isShow;
}
}
}
</script>
输出结果:
3.1.2 多个内容使用(v-if、v-else-if、v-else)
这里我用了 template 做包裹来判断,减少了DOM的操作。
<template id="my-app">
<template v-if="isShow">
<div>哈哈哈</div>
<div>哈哈哈</div>
<div>哈哈哈</div>
</template>
<template v-else>
<div>呵呵呵</div>
<div>呵呵呵</div>
<div>呵呵呵</div>
</template>
<button @click="toggle">切换</button>
</template>
<script>
const App = {
template: '#my-app',
data() {
return {
isShow: true
}
},
methods: {
toggle(){
this.isShow = !this.isShow;
}
}
}
</script>
3.1.3 案例
<template id="my-app">
<span>本次成绩:</span>
<span v-if="scores > 90">优秀</span>
<span v-else-if="scores > 60 ">良好</span>
<span v-else>不及格</span>
<div>
<input type="text" v-model="scores">
</div>
</template>
<script>
const App = {
template: '#my-app',
data() {
return {
scores: 80
}
},
}
</script>
输出结果:
3.2 v-show
v-show和v-if的用法看起来是一致的,也是根据一个条件决定是否显示元素或者组件。示例代码如下:
<template id="my-app">
<div v-show="isShow">{{ message }}</div>
</template>
<script>
const App = {
template: '#my-app',
data() {
return {
message: "Hello World",
isShow: true
}
}
}
</script>
输出结果:
3.3 v-if和v-show的区别
(1)本质的区别
- v-show元素无论是否需要显示到浏览器上,它的DOM实际都是有渲染的,只是通过CSS的display属性来进行切换;
- v-if当条件为false时,其对应的元素压根不会被渲染到DOM中;
(2)开发时选择
- 如果我们的元素需要在显示和隐藏之间频繁的切换,那么使用v-show;
- 如果不会频繁的发生切换,那么使用v-if;
4. 列表渲染
在真实开发中,我们往往会从服务器拿到一组数据,并且需要对其进行渲染。 这个时候我们可以使用 v-for 来完成; v-for类似于JavaScript的for循环,可以用于遍历一组数据;
4.1 v-for 基本使用
v-for的基本格式是 "item in 数组": 数组通常是来自data或者prop,也可以是其他方式; item是我们给每项元素起的一个别名,这个别名可以自定来定义;我们知道,在遍历一个数组的时候会经常需要拿到数组的索引: 如果我们需要索引,可以使用格式: "(item, index) in 数组";注意上面的顺序:数组元素项item是在前面的,索引项index是在后面的;
4.1.1 遍历数组
语法:(item,index) in 数组,第一个是item是数组的每一项,第二个index是数组每一项的索引。
<template id="my-app">
<!-- 1. 每一项 -->
<ul>
<li v-for="movie in movies">{{ movie }}</li>
</ul>
<!-- 2. 每一项 + 索引 -->
<ul>
<li v-for="(movie,index) in movies">{{index}} ---- {{ movie }}</li>
</ul>
</template>
<script>
const App = {
template: '#my-app',
data() {
return {
movies: [
'流浪地球',
'功勋',
'我和我的父辈',
'战狼'
]
}
},
}
</script>
输出结果:
4.1.2 遍历对象
语法:(value,key,index) in 对象
<template id="my-app">
<ul>
<li v-for="(value,key,index) in info">{{index}}-{{key}}-{{value}}</li>
</ul>
</template>
<script>
const App = {
template: '#my-app',
data() {
return {
info:{
name: 'xiaohe',
age: 18,
hobby: 'run'
}
}
},
}
</script>
输出结果:
4.1.3 遍历数字
语法:(item,index)in 数字
<template id="my-app">
<ul>
<li v-for="(item,index) in 10">{{index}}--{{item}}</li>
</ul>
</template>
<script>
const App = {
template: '#my-app',
data() {
return {}
},
}
</script>
输出结果:
5. template VS div
template元素是不会被渲染到浏览器上的,而 div 是会被渲染到浏览器上,很多情况下使用 v-if 和 v-for,如果需要一个占位应该优先考虑 template。
(1)第一种情况:v-if时,如果你用 div 会增加一次DOM操作,而使用 template则不会。
<template id="my-app">
<template v-if="isShow">
<div>哈哈哈</div>
<div>哈哈哈</div>
<div>哈哈哈</div>
</template>
<template v-else>
<div>呵呵呵</div>
<div>呵呵呵</div>
<div>呵呵呵</div>
</template>
</template>
(2)第二种情况:v-for时
<template id="my-app">
<ul>
<template v-for="(value,key) in info">
<li>{{ key }}</li>
<li>{{ value }}</li>
<hr>
</template>
</ul>
</template>
注意:
- v-show 是不支持template的