vue的常用指令
v-bind指令
作用:动态绑定一个或多个属性,属性值是一个动态的【值是依赖于data中的数据源】
使用方式:
<!-- v-bind绑定href属性值 -->
<a v-bind:href='url'>跳转</a>
<!-- v-bind绑定href属性值(简写形式) -->
<a :href='url'>跳转</a>
绑定
绑定HTML Class
1.对象绑定
– html代码
<ul class='app' :class="{'Fone':isOne, 'Ftwo':isTwo}"></ul>
– js代码
var vue = new Vue({
el:'.app',
data:{
isOne:true,
isTwo:true
}
})
最终渲染为
<ul class='app Fone Ftwo' ></ul>
当data里的 isOne 或 isTwo 变化时,class列表会相应更新
以上代码等价于
// html代码
<ul class='app' :class="classObject"></ul>
// js代码
var vue = new Vue({
el:'.app',
data:{
classObject:{
'Fone':true,
'Ftwo':true
}
}
})
2.数组语法
— html代码
<ul class="box" :class="[classA, classB]"></ul>
— js代码
var vm= new Vue({
el:'.box',
data:{
classA:'Fone',
classB:'Ftwo'
}
})
补充
可以使用三目运算符
— html代码
<ul class="box" :class="[isA ? classA:'', classB]"></ul>
— js代码
var vm= new Vue({
el:'.box',
data:{
classA:'Fone',
classB:'Ftwo'
isA:false
}
})
:属性=“data中的属性数据/methods/props/computed”
:属性=“js表达式环境,认为它就是可以直接写js了,字符串相关就要用引号”
— html代码
<a :href="`http://www.baidu.com?id=${id}`">百度一下</a>
<hr>
<a :href="`http://www.baidu.com?id=`+id">百度一下</a>
— js代码
const app = new Vue({
el: '#app',
data: {
url: 'http://img.1314000.cn/face.png',
id: 100
},
})
绑定 HTML css
- 对象绑定
— html代码
<div id="box" :style="{color:activeColor, fontSize:size, textShadow:shadow}">社恐泡面</div>
— js代码
var vm= new Vue({
el:'#box',
data:{
activeColor:'#f00',
size:'30px',
shadow:'5px 2px 6px #000'
}
})
或者
— html代码
<div id="box" :style="styleObject">社恐泡面</div>
— js代码
var vm= new Vue({
el:'#box',
data:{
styleObject:{
color:'red',
fontSize:'30px'
}
}
})
2.数组语法
举个栗子
— html代码
<div id="app">
<!-- 样式class它也是属性,动态属性 :class="对象|数组" -->
<h3 class="title" :class="activeObj">我是一个标题</h3>
<!-- 数组 -->
<!--
如果新增样式,则默认情况下,对象无法直接生效,而数组可以生效
如果对已有的样式,进行开关操作,建议用对象
-->
<!-- <h3 :class="activeArr">我是一个标题</h3> -->
<button @click="setActive">让标题高亮</button>
</div>
— js代码
const app = new Vue({
el: '#app',
data: {
// 对象的方式,key,定义的的style中的样式名称
activeObj: { active: true, font: true },
// 数组中的元素就是样式名
activeArr: []
},
methods: {
setActive() {
// Object.defineProperty
// this.activeObj.active = true
// this.activeObj.font = true
// this.activeObj = { active: false, font: true }
// this.activeObj = { ...this.activeObj, font: true }
// Object方法完成对象的合并,返回一个新对象,引用地址不同
// this.activeObj = Object.assign({},this.activeObj,{font: true})
// vue2中为了解决Object.defineProperty动态添加属性无法监听问题,提供一个成员方法 $set
// 参数1:对象是谁
// 参数2:属性名称
// 参数3:值
// 推荐
// this.$set(this.activeObj, 'font', true)
// 触发视图更新
// this.$delete(this.activeObj, 'font')
// this.activeArr.length == 0 ? this.activeArr.push('active') : this.activeArr.pop()
// this.activeArr.push('font')
}
}
})
设置内联样式
— html代码
<div id="app">
<!-- 内联样式,它的优先级更高,一般用于已有样式的覆盖 -->
<div :style="styleObj">我是style样式 -- 对象</div>
<hr>
<div :style="styleArr">我是style样式 -- 数组</div>
</div>
— js代码
const app = new Vue({
el: '#app',
data: {
// styleObj: { color: 'red', fontSize: '50px' }
styleObj: { color: 'red', 'font-size': '50px' },
styleArr: [{ color: 'blue' }, { fontSize: '30px' }]
}
})
属性里有函数
— html代码
<img :src="getImg()" alt="">
— js代码
const app = new Vue({
el: '#app',
data: {
url: 'http://img.1314000.cn/face.png',
id: 100
},
methods: {
getImg() {
return 'http://img.1314000.cn/face.png'
}
}
})
注意: 有()
v-for
用于循环取出列数中的数据
语法:v-for="(item,index) in/of 数组"
语法:v-for="(item,key,index) in/of 对象"
注:
v-for中建议在迭代时,最好是给第个迭代的元素添加一个唯一不重复的key值,以达到提升性能
key值尽量不要用index索引导它的key值,index索引,如果目标增加或删除,则会触发index值的变化,这样达不到性能优化,index塌陷
今后在和后端合作,通过请求接口拿数据时,一定要确保拿过来数据中一定要有id值
如果你指定了key,新key在的节点中找不到,则创建,旧的key如果在新的节点中找不到,删除
使用:
— html代码
<div id="app">
<ul>
<!-- <li v-for="item,index of users" :key="index"> -->
<li v-for="item,index of users" :key="item">
<span>{{index}}</span>
<span>{{item}}</span>
</li>
</ul>
<hr>
<!-- 迭代对象方案,在工作中很少有,了解就可以,如果用到知道它可以就可以 -->
<div v-for="item,key,index in info">
{{key}} -- {{index}} -- {{item}}
</div>
</div>
— js代码
const app = new Vue({
el: '#app',
data: {
users: [
// {id:1,name:'张三'}
'张三',
'李四',
'王五'
],
info: { id: 1, name: '赵六', age: 100 }
}
})
v-on
事件绑定:v-on:事件名="绑定的方法" : vue中的绑定的方法可以加小括号也可以不加括号
绑定的方法定义的位置:data/methods,推荐写在methods
因为事件绑定在工作中经常用,简单 @事件名="方法" 【h函数中 onClick】
事件对象 event
1.如果绑定的方法没有写小括号,则vue事件系统会自动注入一个event对象到实现在的方法形参中
2.如果绑定的方法有写小括号,则你需要手动把event对象传过来去,vue提供一个变量 $event
如果你的绑定的方法,需要传实现的参数,则写小括号,如果还用到事件对象,则手动传一下,一般我们手动传的事件对象,都写在第1个形参
试一试
— html代码
<div id="app">
<h3>{{num}}</h3>
<!-- <button v-on:click="addNum">++++</button> -->
<!-- <button @click="addNum">++++</button> -->
<!-- <button @click="addNum($event,2)">++++</button> -->
<button @click="addNum(2)">++++</button>
<hr>
<input type="text" @keyup="onEnter">
</div>
— js代码
const app = new Vue({
el: '#app',
data: {
num: 100
},
methods: {
// addNum(evt, n) {
// console.log(evt);
// this.num += n
// }
addNum(n) {
this.num += n
},
onEnter(evt) {
// console.log(evt)
// 如果我是回车,则获取数据
if ('Enter' === evt.key) {
console.log(evt.target.value)
evt.target.value = ''
}
}
}
})
事件修饰符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xtn3gZvZ-1668606202270)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\1668568835001.png)]
— html代码
<div id="app">
<div @click="click">
<!-- 阻止冒泡 stop -->
<div @click.stop="click">我是一个点击事件</div>
</div>
<!-- 绑定keyup的额组合按键 ctrl+enter -->
<input type="text" @keyup.ctrl.enter="onEnter">
<hr>
<!-- 阻止默认行为 prevent -->
<a href="http://www.baidu.com" @click.prevent="gourl">百度</a>
</div>
— js代码
const app = new Vue({
el: '#app',
data: {
},
methods: {
onEnter(evt) {
console.log(evt.target.value)
},
click() {
console.log('click');
},
gourl() {
console.log('百度一下');
}
}
})
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dyrLOp7z-1668606202272)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\1668605424230.png)]
按键修饰符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sgEtdXfG-1668606202273)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\1668605439477.png)]
v-model
vue中一个语法糖:快捷方式
v-model: 绑值 事件 ==> 双向数据绑定
text/radio/checkbox ==> value/input checked/change
title它是在data中定义的数据
受控组件
<input type="text" :value="title" @input="onInput">
<input type="text" v-model="title">
举个栗子
— html代码
<div id="app">
<input type="text" v-model="title">
<hr>
<!-- 多行文本 -->
<textarea v-model="intro"></textarea>
<hr>
<!-- 单个复选框 全选 、记住登录、声明确认 -- 状态只有两个 true/false -->
<!-- false则不选中,为true选中 事件和状态修改 -->
<input type="checkbox" v-model="checked" @change="changeHandle">
<hr>
<ul>
<li v-for="item of targetCourse">
<label>
<input type="checkbox" :value="item.id" v-model="course" @change="changeOneHandle">
{{item.title}}
</label>
</li>
</ul>
<hr>
<div>
<input type="radio" value="1" v-model="sex">先生
<input type="radio" value="2" v-model="sex">女士
</div>
<hr>
<select v-model="city" @change="aa">
<option value="0">请选择所在城市</option>
<option value="1">芜湖</option>
<option value="2">杭州</option>
<option value="3">南京</option>
</select>
<select v-model="region">
<option value="10">镜湖区</option>
<option value="11">鸠江区</option>
</select>
<button @click="login">提交信息</button>
</div>
— js代码
const app = new Vue({
el: '#app',
data: {
title: 'aa',
intro: 'bb',
// 单个复选框,用boolean
checked: false,
// 多个复选框,array,数组中的元素值,和value值相同时,则界面中选中
course: [],
targetCourse: [
{ id: 1, title: '浠浠呀小白入门' },
{ id: 2, title: '浠浠呀你不知道的js' },
{ id: 3, title: 'kerwin老师精品大师' },
],
sex: '2',
city: '1',
region: ''
},
methods: {
login() {
console.log({ ...this.$data });
},
changeHandle() {
let course = []
if (this.checked) {
course = this.targetCourse.map(({ id }) => id)
}
this.course = course
},
changeOneHandle(){
this.checked = this.course.length==this.targetCourse.length ? true : false;
},
aa() {
console.log(this.city);
}
}
})
v-model修饰符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fCmofASN-1668606202273)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\1668605832908.png)]
— html代码
<div id="app">
<!--
v-model修饰符
.number把表单项中的字符串转为数字,
如果你的字符是以数字开头,则转为数字,如果不能转为数字,则不转
-->
<input type="text" v-model.number="n1"> +
<input type="number" v-model.number="n2">
<button @click="onCalc">结果</button>
{{sum}}
<hr>
<!-- 去除两边空格 -->
<input type="text" v-model.trim="title">
<!-- 延时更新,优化用 -->
<input type="text" v-model.trim.lazy="title">
</div>
— js代码
const app = new Vue({
el: '#app',
data: {
n1: 1,
n2: 2,
sum: 3,
title: ''
},
methods: {
onCalc() {
// this.sum = +this.n1++this.n2
// this.sum = Number(this.n1) + Number(this.n2)
this.sum = this.n1 + this.n2
}
}
})
自定义指令
除了用内置的指令完成vue工作需要后,还可以根据vue提供的方案完成自定义指令
自定义指令:操作dom
dom对象.style.color='red'
自定义指令它提供了5个钩子函数,它可以帮我们实现所需要的各种业务场景
el 当前绑定到指令元素的dom对象,bindings 修饰符和传入的值
bind 第一次绑定到元素时调用
inserted 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)
update 数据更新时调用
componentUpdated 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind 只调用一次,指令与元素解绑时调用。
// 定义自定义指令有两种方案
// 1.全局 --- 本项目中所有的组件都能使用
// 2.局部 --- 当前组件可以用
注:自定义指令中不能使用 this来获取 new Vue组件中的data和方法
举个栗子–定义主题颜色
— html代码
<div id="app">
<div v-red v-if="show">
<span>我是标题</span>
<div>
<input type="text" v-model="title">
</div>
<button v-red>蓝色</button>
</div>
</div>
<div id="app2">
<div v-red>我是一个标题App2</div>
</div>
— js代码
// 1.定义全局指令 -- 定义一次,全局可用
// 参数1:指定指令的名称,不要v-开头
// 参数2:对象[定义这5个钩子函数实现] | 回调函数[它是bind/update简写]
Vue.directive('red', {
bind(el) {
el.style.cssText = `color:red;
font-size: 30px;`
}
})
const app = new Vue({
el: '#app',
data: {
title: '',
show: true
}
})
const app2 = new Vue({
el: '#app2',
data: {
title: '',
show: true
}
})
举个栗子-- 表单验证
— html代码
<div id="app">
<div>
<div>
<!-- 用户名必须是以a开头 -->
<input type="text" v-model="username" v-username>
</div>
<div>
<input type="text" v-model="password" v-password>
</div>
</div>
</div>
— js代码
// Vue.directive('username', {
// bind(el) {
// // 用户名必须是以a开头
// if (el.value.startsWith('a')) {
// // el.style.color = 'red'
// el.style.cssText = `border: 1px solid red;outline:none;`
// } else {
// // el.style.color = 'black'
// el.style.cssText = `border: 1px solid black;`
// }
// },
// update(el) {
// // 用户名必须是以a开头
// // console.log(el.value);
// // console.log(el.value.startsWith('a'))
// // 输出的账号中不能有a字母
// // console.log(el.value.includes('a'))
// // 用户名必须是以a开头
// if (el.value.startsWith('a')) {
// // el.style.color = 'red'
// el.style.cssText = `border: 1px solid red;outline:none;`
// } else {
// // el.style.color = 'black'
// el.style.cssText = `border: 1px solid black;`
// }
// }
// })
// 简写,它相当于 bind/update合集
Vue.directive('username', el => {
// 用户名必须是以a开头
if (el.value.startsWith('a')) {
el.style.cssText = `border: 1px solid red;outline:none;`
// 当前我没有兄弟,创建
if (!el.nextSibling) {
const spanDom = document.createElement('span')
spanDom.innerHTML = '账号不能以a字母开头'
el.parentNode.appendChild(spanDom)
}
} else {
el.style.cssText = `border: 1px solid black;`
// el?.nextSibling?.remove()
el && el.nextSibling && el.nextSibling.remove()
}
})
Vue.directive('password', el => { })
const app = new Vue({
el: '#app',
data: {
username: '',
password: ''
}
})
=> {
// 用户名必须是以a开头
if (el.value.startsWith('a')) {
el.style.cssText = `border: 1px solid red;outline:none;`
// 当前我没有兄弟,创建
if (!el.nextSibling) {
const spanDom = document.createElement('span')
spanDom.innerHTML = '账号不能以a字母开头'
el.parentNode.appendChild(spanDom)
}
} else {
el.style.cssText = `border: 1px solid black;`
// el?.nextSibling?.remove()
el && el.nextSibling && el.nextSibling.remove()
}
})
Vue.directive('password', el => { })
const app = new Vue({
el: '#app',
data: {
username: '',
password: ''
}
})