文章目录
vue常用指令
vue一共14个指令,常用的有大约10个
按照不同的用途可以分为如下 6 大类:
-
内容渲染指令(v-html、v-text)
-
条件渲染指令(v-show、v-if、v-else、v-else-if)
-
事件绑定指令(v-on)可简写为冒号:
-
属性绑定指令 (v-bind)可简写为@
-
双向绑定指令(v-model)
-
列表渲染指令(v-for)
内容渲染指令
内容渲染指令会覆盖掉元素中原有的内容
v-text
类似innerText,不可以解析标签
示例:
<div id="app" v-text="msg">我会被覆盖</div> <!--会覆盖掉div中原有的内容-->
<script>
new Vue({
el:'#app',
data:{
msg:`<a href="www.baidu.com">百度</a>`,
name:'小十七'
}
})
</script>
v-html
类似 innerHTML,可以解析标签
<div id="app" v-html="msg">我会被覆盖</div> <!--会覆盖掉div中原有的内容-->
<script>
new Vue({
el:'#app',
data:{
msg:`<a href="www.baidu.com">百度</a>`,
name:'小十七'
}
})
</script>
条件渲染指令
v-show
- 作用: 控制元素显示隐藏
- 语法:
v-show = "表达式"
,表达式值为 true 显示,为 false 隐藏 - 原理: 切换 display:none 控制显示隐藏
- 场景:频繁切换显示隐藏的场景
v-if
- 作用: 控制元素显示隐藏(条件渲染)
- 语法:
v-if = "表达式"
,表达式值 true 显示,为 false 隐藏 - 原理: 基于条件判断,是否创建或移除元素节点
- 场景: 要么显示,要么隐藏,不频繁切换的场景
示例:
<style>
p{
width: 100px;
height: 100px;
background-color: skyblue;
}
</style>
</head>
<body>
<div id="app">
<p v-show="flag">我是v-show</p>
<p v-if="flag">我是v-if</p>
</div>
<script>
new Vue({
el:'#app',
data(){
return{
flag:true
}
},
})
</script>
v-else
、v-else-if
- 作用:辅助v-if进行判断渲染(类似于if多分支语句)
- 语法:v-else ; v-else-if=“表达式” ;v-else后面不需要加表达式
- v-if v-else v-else-if 使用时需要紧挨着,中间不能断开
示例:
<div id="app">
<p v-if="gender === 1">性别:♂ 男</p>
<p v-else=>性别:♀ 女</p>
<hr>
<p v-if="score >=90">成绩评定A:奖励电脑一台</p>
<p v-else-if="score >=70">成绩评定B:奖励周末郊游</p>
<p v-else-if="score >=60">成绩评定C:奖励零食礼包</p>
<p v-else>成绩评定D:惩罚一周不能玩手机</p>
</div>
<script>
const app = new Vue({
el: '#app',
data() {
return {
gender: 1,
score: 95
}
}
})
</script>
template
标签
template标签/元素只是起到占位的作用,不会真正的出现在页面上,也不会影响页面的结构
示例:
<!-- 需求:同时控制以下3个标题一起出现或者隐藏
上述的需求就可以使用template标签去实现,普通标签虽然也可以但是多个结构
-->
<template v-if="false">
<h2>六下匹,人当送,内。</h2>
<h3>六下匹,人当送,内。</h3>
<h4>六下匹,人当送,内。</h4>
</template>
事件绑定指令
v-on
<button v-on:事件名="内联语句">按钮</button>
<button v-on:事件名="methods中的函数名">按钮</button>
<button v-on:事件名="处理函数(实参)">按钮</button>
v-on:可以简写为 @
<button @事件名="内联语句">按钮</button>
示例1:内联语句
<!--按钮加减功能-->
<div id="app">
<button v-on:click="count--">-</button>
<span>{{count}}</span>
<button @click="count++">+</button> <!-- v-on简写为@ -->
</div>
<script>
new Vue({
el:'#app',
data(){
return{
count:100,
}
}
})
</script>
示例2:methods
<div id="app">
<button @click="fn">切换显示隐藏</button>
<h1 v-show="isShow">我是小十七</h1>
</div>
<script>
const app = new Vue({
el:'#app',
data(){
return{
isShow:true
}
},
methods:{
fn(){
this.isShow=!this.isShow
}
}
})
</script>
事件处理函数传参
- 如果不传递任何参数,则方法无需加小括号
methods
方法中如果没有传参可以直接使用 e 当做事件对象- 如果传递了参数,则实参
$event
表示事件对象,固定用法
示例:减5、减10 的处理逻辑是一样的,所以可以封装成方法,在调用的时候传参
<div id="app">
<button @click="result(5)">减5</button> <!--如果不传入参数就不需要写小括号,直接写result-->
<button @click="result(10)">减10</button>
<p>余额{{money}}</p>
</div>
<script>
new Vue({
el: '#app',
data() {
return {
money: 100
}
},
methods:{
result(price){
this.money -= price
}
}
})
</script>
事件处理函数的事件对象
methods
方法中如果没有传参可以直接使用 e 当做事件对象
<div id ="root">
<button @click="fn">事件对象</button>
</div>
<script>
var vm = new Vue({
el: '#root',
methods:{
fn(e){
console.log(e) // 打印出事件对象
}
}
});
</script>
如果传递了参数,则实参 $event
表示事件对象,固定写法只能写成$event
<div id="root">
<button @click="fn($event,'love')">方法传参事件对象</button>
</div>
<script>
var vm = new Vue({
el: '#root',
methods: {
fn(str, e) {
console.log(str); // love
console.log(e); // 事件对象
}
}
});
</script>
属性绑定指令
v-bind
-
v-bind:
可以绑定元素的属性 -
语法:v-bind:属性名=“表达式”
-
v-bind:
可以简写成冒号 : -
表达式会关联到
data
的数据,只要data
的数据发生变化,v-bind
绑定属性后面的表达式执行结果立即发生变化 -
凡是标签体的内容想要动态,用插值语法
-
凡是需要标签的属性是动态的,就用指令语法
示例:点击随机变色
<!-- v-bind可以简写成 : -->
<div id="root" v-bind:style={backgroundColor:bgColor} style="width: 100px;height: 100px;">
<!--点击触发changeColor函数-->
<button @click="changeColor">变色</button>
</div>
<script>
var vm = new Vue({
el: '#root',
data() {
return {
bgColor: 'skyblue'
}
},
methods: {
changeColor() {
this.bgColor = this.getRandomColor()
},
// 随机色函数
getRandomColor() {
const letters = '0123456789ABCDEF'
let color = '#'
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)]
}
return color
}
}
})
</script>
双向绑定指令
v-model
-
v-model
双向数据绑定 -
v-model
只能用在表单元素- 输入框 input:text --> value
- 文本域 textarea --> value
- 复选框 input:checkbox --> checked
- 单选框 input:radio --> checked
- 下拉菜单 select
- …
-
可以快速获取或设置表单元素的内容
-
视图或数据变化,另一个自动更新
语法:
// 完整写法
v-model:value="表达式"
// 简写
v-model="表达式"
示例:
<style>
textarea {
display: block;
width: 240px;
height: 100px;
margin: 10px 0;
}
</style>
<div id="app">
<h3>小黑学习网</h3>
姓名:
<input type="text" v-model="uname">
<br><br>
是否单身:
<input type="checkbox" v-model="isSingle">
<br><br>
<!--
前置理解:
1. name: 给单选框加上 name 属性 可以分组 → 同一组互相会互斥
2. value: 给单选框加上 value 属性,用于提交给后台的数据
3.结合 Vue 使用 → v-model
4.使用 v-model时单选框的name属性可以不要,但是value属性必须要有
5.当 v-model 的值与某个单选框的 value 值相等时,Vue.js 会自动设置该单选框为选中状态
-->
性别:
<input type="radio" value="1" v-model="gender">男
<input type="radio" value="0" v-model="gender">女
<br><br>
<!--
前置理解:
1. option 需要设置 value 值,提交给后台
2. select 的 value 值,关联了选中的 option 的 value 值
3. 结合 Vue 使用 → v-model
-->
所在城市:
<!-- 当 v-model 的值与下拉菜单的某个选项的 value 值相等时,Vue.js 会自动设置该单选框为选中状态 -->
<select v-model="cityId">
<option value="101">北京</option>
<option value="102">上海</option>
<option value="103">成都</option>
<option value="104">南京</option>
</select>
<br><br>
自我描述:
<textarea v-model="text"></textarea>
<button>立即注册</button>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
uname:'',
isSingle:true,
gender:'1',
cityId:'102',
text:''
}
})
</script>
v-model
的双向绑定实现原理
用在表单元素上
- 文本框或密码框相当于:
:value="数据" + @input="数据=$event.target.value"
- 复选框:
:checked="数据" + @change="数据=$event.target.checked"
- 下拉列表:
:selected="数据" + @change="数据= $event.target.selected"
用v-on给表单控件绑定数据,此时数据是单向的,修改input的值data里面的数据不会发生变化,我们可以给输入框绑定input事件,给单/复选框、下拉框绑定change事件,触发事件时通过事件对象$event,拿到表单控件的值,然后赋值给data的数据,实现双向绑定
用在组件实现父子数据双向绑定
:value="数据" + @input=" 数据=$event"
列表渲染指令
v-for
- v-for 列表渲染指令
- 作用:基于数据循环,多次渲染整个元素
- 可以渲染 :Array | Object | number | string | Iterable (2.6 新增)
- 当和
v-if
一起使用时,v-for
的优先级比v-if
更高
遍历数组语法:
<div v-for="(item, index) in arr"> {{value}} </div>
<!-- 也可以写成这样v-for="(item, index) of arr 看自己的习惯 -->
<!--
item数组中的每一项,必须项
index 是每一项的索引,可选项,不需要可以省略
arr 是被遍历的数组
-->
<div v-for="item in arr"> {{value}} </div>
<!-- 省略index的写法 -->
也可以遍历 对象、数字
<!--遍历对象-->
<div v-for="(value, key, index) in object">{{value}}</div>
<!--
value:对象中的值
key:对象中的键
index:遍历索引从0开始
-->
<!--遍历数字-->
<p v-for="item in 10">{{item}}</p>
<!--item从1开始-->
遍历数组示例:
<div id="root">
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
<script>
let vm = new Vue({
el: '#root',
data() {
return {
list: ['西瓜', '苹果', '香蕉', '火龙果', '芒果']
}
}
})
</script>
其它指令
v-pre
-
不需要表达式
-
用法:
跳过这个元素和它的子元素的编译过程,可以用来显示原始标签,跳过大量没有指令的节点会加快编译
-
示例:
<span v-pre>{{ this will not be compiled }}</span>
v-cloak
- 不需要表达式
- 此指令会一直在元素身上,直到编译结束,会被去除
- 可用于隐藏尚未完成编译的 DOM 模板
- 场景:当文件加载速度慢,导致编译变慢,会将一些语法原样显示在页面,可以利用
v-cloak
作为属性选择器去隐藏,直到编译完成,v-cloak被去除,元素显示出来
场景模拟示例:
<style>
[v-cloak] {
display: none;
}
</style>
<body>
<div id="app">
<h1 v-cloak>{{msg}}</h1>
</div>
<script>
// 晚3s引入vue.js
setTimeout(() => {
let scriptElt = document.createElement("script");
scriptElt.src = "./js/vue.js";
document.head.append(scriptElt);
}, 3000);
// 晚4s创建vm实例
setTimeout(() => {
var vm = new Vue({
el: "#app",
data: {
msg: "v-cloak",
},
});
}, 4000);
</script>
编译结束在哪个阶段?
在Vue中,
v-cloak
指令主要用于解决插值表达式的闪烁问题。当Vue实例还没有编译完成时,v-cloak
所在的元素会保持隐藏状态,直到Vue实例编译结束,v-cloak
才会从DOM元素上移除,此时页面内容才会正常显示。关于Vue的生命周期,它主要分为四个阶段:初始化阶段、模板编译阶段、挂载阶段和卸载阶段。
- 初始化阶段:从创建Vue实例开始,到
beforeCreate
和created
这两个生命周期钩子之间的阶段。在这个阶段,Vue实例会进行初始化设置,包括数据观测(data observer),属性和方法的运算,以及e**l属性等等,但是还没有挂载‘el,且
$el`属性目前不可见。- 模板编译阶段:在
created
和beforeMount
这两个钩子之间的阶段。这个阶段主要是将模板编译为渲染函数,为后续的挂载阶段做准备。- 挂载阶段:在
beforeMount
和mounted
这两个钩子之间的阶段。Vue在这个阶段会将实例挂载到DOM元素上,即将模板渲染到指定的DOM元素上。此时,页面内容会正常显示,v-cloak
指令也会在这个阶段从DOM元素上移除。- 卸载阶段:当调用
vm.$destroy()
方法后,Vue实例会进入卸载阶段。在这个阶段,Vue会将自身从父组件中删除,取消实例上所有依赖的追踪并且移除所有的事件监听器。所以,对于
v-cloak
编译结束后消失的问题,编译结束实际上是指Vue实例的挂载阶段。当Vue实例完成模板编译并成功挂载到DOM元素上时,v-cloak
指令就会被移除,页面内容会正常显示
v-once
- 不需要传入参数
- 只能渲染一次,数据修改后也不会再渲染,相当于静态渲染,可以用于优化性能
<h1 v-once> {{msg}} </h1>
v-for
中的 key
v-for
的默认行为会尝试原地修改元素而不是移动它们(就地复用)- 要强制其重新排序元素,你需要用特殊 attribute
key
来提供一个排序提示 - key的作用:给元素添加的唯一标识
语法:
<div v-for="item in arr" :key="item.id"> {{ item.text }} </div>
示例:
<div id="app">
<h3>小黑的书架</h3>
<ul>
<li v-for="item in booksList" >
<span>{{item.name}}</span>
<span>{{item.author}}</span>
<button @click="del(item.id)">删除</button>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
booksList: [
{ id: 1, name: '《红楼梦》', author: '曹雪芹' },
{ id: 2, name: '《西游记》', author: '吴承恩' },
{ id: 3, name: '《水浒传》', author: '施耐庵' },
{ id: 4, name: '《三国演义》', author: '罗贯中' }
]
},
methods: {
del(id) {
this.booksList = this.booksList.filter(item => item.id !== id)
}
}
})
</script>
v-bind
和 v-model
区别
v-bind
和v-model
都可以完成数据的绑定 data ==> 视图v-bind
是单向数据绑定 data ==> 视图v-model
是双向数据绑定 data <==> 视图v-bind
可以用在任何html标签上,v-model
只能用在表单元素( input、radio、select、textarea等 )
v-if
和v-show
- v-show不论初始条件是什么,元素始终都会被渲染到 DOM 中,只是简单地通过切换 CSS 的 display 属性来控制其可见性
- v-if 指令是依据条件渲染元素,条件变化时需要重新渲染整个条件块,这包括销毁、重新创建和挂载元素;依靠销毁创建元素来控制可见性,性能不好
- 如果一个元素在页面上被频繁的隐藏和显示,建议使用v-show,因为用 v-if 反复创建和销毁节点性能不好
- v-if 的优点:v-show不论如何都要渲染整个元素,v-if 依据条件来判断是否渲染,所以页面加载速度快,能提高页面的渲染效率
v-bind
操作class
为了方便开发者进行样式控制, Vue 扩展了 v-bind 的语法,可以针对 class 类名 和 style 行内样式 进行控制
字符串写法
<style>
.big {
width: 200px;
height: 200px;
}
</style>
<div :class="styles"></div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
styles:"big"
})
</script>
对象写法
- 当class动态绑定的是对象时,键是类名
- 值是布尔值,值为true,就有这个类名,为false,就没有这类名
- 适用场景:一个类名,来回切换(例如tab栏切换)
<div class="box" :class="{ 类名1: 布尔值, 类名2: 布尔值 }"></div>
数组写法
- 当class动态绑定的是数组时,数组中所有的类,都会添加元素上
- 本质就是一个 class 列表
- 使用场景:批量添加或删除类
<div class="box" :class="[ 类名1, 类名2, 类名3 ]"></div>
案例:tab 栏切换
CSS
<style>
* { margin: 0;padding: 0;}
ul { display: flex;border-bottom: 2px solid #e01222;padding: 0 10px;}
li { width: 100px;height: 50px; line-height: 50px;list-style: none; text-align: center;}
li a { display: block; text-decoration: none; font-weight: bold;color: #333333; }
li a.active { background-color: #e01222; color: #fff; }
</style>
JS
<div id="app">
<ul>
<!-- v-for动态渲染,注册点击事件,更改activeIndex数值,数据渲染视图 -->
<li v-for="(item,index) in list" :key="item.id" @click="activeIndex=index">
<!-- 绑定class属性,对象写法,用于频繁切换 -->
<a :class="{active:index === activeIndex}" href="#">{{item.name}}</a>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
list: [
{ id: 1, name: '京东秒杀' },
{ id: 2, name: '每日特价' },
{ id: 3, name: '品类秒杀' }
],
activeIndex: 0
}
})
</script>
v-bind
操作style
字符串写法
示例:
<div id="app" class="box" :style="styleStr"></div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const vm = new Vue({
el: "#app",
data: {
// 用一个变量存储数据,不同样式之间用分号; 隔开
styleStr: "background-color:green; width:500px; height: 100px",
},
});
</script>
对象写法
语法:
<div class="box" :style="{ CSS属性名1: 'CSS属性值', CSS属性名2: 'CSS属性值' }"></div>
<!--
遇到background-color带横杠的css属性名,
可以用驼峰写法: backgroundColor
或者加上双引号:'background-color'
-->
<!--css属性值是需要加上双引号的,否则报错-->
示例:
<div :style="{ width: '100px' , height:'50px' , backgroundColor:'skyblue' }"> </div>
进度条案例:
CSS
<style>
.progress {height: 25px;width: 400px;border-radius: 15px;background-color: #272425;border: 3px solid #272425;box-sizing: border-box;margin-bottom: 30px;}
.inner {width: 50%;height: 20px;border-radius: 10px;text-align: right;position: relative;background-color: #409eff;background-size: 20px 20px;box-sizing: border-box;transition: all 1s;}
.inner span {position: absolute;right: -20px;bottom: -25px;}
</style>
JS
<div id="app">
<div class="progress">
<div class="inner" :style="{width: percent + '%'}">
<span>{{percent}}%</span>
</div>
</div>
<button @click="percent=25">设置25%</button>
<button @click="percent=50">设置50%</button>
<button @click="percent=75">设置75%</button>
<button @click="percent=100">设置100%</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
percent: 20
}
})
</script>
数组写法
示例:
<div id="app" class="static" :style="styleArr">动态写法:数组形式</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
styleArr:[{'background-color':'green'},{'color':'red'}]
}
})
</script>
v-bind
脚手架环境绑定图片src
在 Vue 中使用动态绑定图片地址时,如果你使用相对路径,并且是在构建后的环境中(比如通过 webpack 或其他打包工具打包后部署到服务器上),可能会遇到路径解析不正确的问题。这是因为打包工具会处理资源文件,并改变它们在构建后的目录结构
对于 Vue CLI 创建的项目,通常推荐使用require
或import
来引入图片资源,这样 webpack 可以正确地处理图片路径,并在构建时将其包含在输出中
这里,@
符号通常是 Vue CLI 项目中src
目录的别名。确保你的图片位于public
文件夹或src/assets
文件夹内,并相应地调整路径
如果你坚持使用相对路径,并且确实知道图片在构建后的位置,你可以直接绑定构建后的路径。但请注意,这通常不是推荐的做法,因为它依赖于构建后的目录结构,这可能在不同的部署环境中有所不同
<img :src="require(`../../public/img/${sendWeatherData.wea_img}.png`)" class="weather-icon" />