1、样式操作
操作样式,就是属性绑定,只不过绑定的属性是class和style,vue中,给样式属性赋的值还可以是对象,数组。
- 绑定格式
<div v-bind:class="数据|属性|变量|表达式"></div>
<div v-bind:style="数据|属性|变量|表达式"></div>
- class使用对象
<div class="big-box" :class="{redbox:isRed,borderBox:isBorder}"></div>
let vm =new Vue({
el:"#box",
data:{
isRed:true,//为true类名生效
isBorder:true,
},
});
- class使用数组
<div class="big-box" :class="[bgcolor,border]" >
</div>
let vm =new Vue({
el:"#box",
data:{
bgcolor:'redbox',//类名
border:'borderBox',//类名
},
});
- style使用对象
<div class="big-box" :style="{width:w+'px',backgroundColor:bgColor
</div>
let vm =new Vue({
el:"#box",
data:{
w:100,
bgColor:'red'
},
});
- style使用数组
<div class="big-box" :style="[s1,s2]" ></div>
let vm =new Vue({
el:"#box",
data:{
s1:{
width:"200px",
height:"200px"
},
s2:{
"background-color":"red"
}
},
});
注意:vue绑定的class属性和普通的class属性可以共存。
经典案例1:vue实现进度条
<div class="jin">
<input type="button" value="开始加载" @click="changeW">
<div class="jin_w">
<div class="tiao" :class="{end_tiao:x}" v-bind:style="{width:w+'px'}"></div>
<span>{{(w/2).toFixed(2)+'%'}}</span>
</div>
</div>
let vm = new Vue({
el:'.jin',
data:{
w:0,
x:false,
},
methods:{
changeW(){
let timer = setInterval(()=>{
//此处this指向改变,不再是vue对象,故使用箭头函数
this.w +=2;
if(this.w>=200){
this.w=200;
window.clearInterval(timer);
this.x = true
}
},50)
}
}
})
效果图:
经典案例2:vue实现ToDoList
<div id="box">
<h3>
任务总数:{{todolist.length}},未完成:{{todolist.filter(todo=>todo.isF==false).length}}
<input type="button" value="删除已完成的事项" @click="remove">
</h3>
<ul>
<li v-for="todo in todolist">
<input type="checkbox" v-model="todo.isF"/>
<input type="text" v-model="todo.des" class="quBoder"
:class="{remove:todo.isF}" :disabled="todo.isF">
</li>
</ul>
<input type="text" v-model="mes">
<input type="button" value="添加" @click="add">
</div>
let vm = new Vue({
el:'#box',
data:{
todolist:[
{
des:"吃饭",
isF:false,
},
{
des:"睡觉",
isF:false,
},
],
mes:'',
},
methods:{
add(){
this.todolist.push({
des:this.mes,
isF:false,
})
//清空input框内容
this.mes = '';
},
remove(){
this.todolist = this.todolist.filter(todo=>todo.isF==false);
}
}
})
效果图
2、非响应式情况
2.1、什么是响应式
简单来说,响应式就是A改变了,使用A的地方也会改变,
非响应式就是使用A的地方并没有改变。
2.2、非响应式的情况
我们知道,vue使用了观察者模式,即响应式,但在vue中,使用某些方式改变数据(model层)时,vue不会把结果呈现在页面上(view层),以下就是vue出现的非响应式的情况:
对数组使用了 非变异 (non-mutating method) 方法(方法的调用不会改变原始数组的内容,如:concat)。因为,没有改变原始数组的内容(如:concat)
使用数组的索引(根索引)的方式改变数组的元素时
修改数组的长度时
给对象添加新的属性时。
一般来说,建议不要修改数组的根键,不要修改数组的长度,可以把未来需要的数据都声明在data选项内部,不要对数组使用非变异的api。
数组的变异方法请参考数组的变异api
2.3、vue提供的非响应式解决方案(尽量不要使用)
Vue.set|this.$set(数组, index, value)
Vue.set|this.$set(对象, key, value)
this.$forceUpdate() 强制刷新
3、Vue 实现数据绑定,响应式的原理
vue数据绑定是通过 数据劫持和观察者模式 的方式来实现的
-
数据劫持:
vue2.× 使用Object.defineProperty();
Vue3 使用的是proxy。当你把一个普通的 JavaScript 对象(json)传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
目的是:感知属性的变化。当给属性赋值时,程序是能够感知的(知道的)。如果知道的话,就可以控制属性值的有效范围,也可以改变其它属性的值等,在Vue中也可以去改变模板上的显示。
- 观察者模式(发布订阅模式)
目的:当属性发生变化时,所有使用该数据地方跟着变化