文章目录
- vue常用指令
- 内容渲染指令
- `v-text`
- `v-html`
- 条件渲染指令
- `v-show`
- `v-if`
- `v-else`、`v-else-if`
- `template`标签
- 事件绑定指令
- `v-on`
- 事件处理函数传参
- 事件处理函数的事件对象
- 属性绑定指令
- `v-bind`
- 双向绑定指令
- `v-model`
- `v-model`的双向绑定实现原理
- 用在表单元素上
- 用在组件实现父子数据双向绑定
- 列表渲染指令
- `v-for`
- 其它指令
- `v-pre`
- `v-cloak`
- `v-once`
- `v-for` 中的 `key`
- `v-bind` 和 `v-model`区别
- `v-if`和`v-show`
- `v-bind`操作class
- 字符串写法
- 对象写法
- 数组写法
- 案例:tab 栏切换
- `v-bind`操作style
- 字符串写法
- 对象写法
- 数组写法
- `v-bind`脚手架环境绑定图片src
- 关于key的面试题
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); // loveconsole.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.jssetTimeout(() => {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" />