本文主要是介绍Vue知识点唠嗑之数据驱动,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Vue是一个以数据驱动的web前端框架。啥是数据驱动?以前写前端,最主要的就是jQuery大法,通过jQuery提供的定位DOM元素的方法直接操作DOM,这样的话,程序员在处理html页面的时候,既要考虑数据的格式和逻辑,又要考虑怎么使用DOM将数据渲染出来。不同水平的程序员渲染出来的页面速度层次不齐。而Vue就是将程序员从繁琐的DOM操作中释放出来,让程序员只需要关心数据就可以了,无需关心DOM怎么改,修改数据就可以自动修改对应的DOM。所以说,Vue是数据驱动的,所谓的数据驱动就是指只要改变变量,就可以改变DOM节点,程序员无需关注具体的DOM操作。
一个Vue的HelloWorld:
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta http-equiv="content-Type" charset="UTF-8"><meta http-equiv="x-ua-compatiable" content="IE=edge"><title>Hello</title><script src="./vue.js"></script>
</head>
<body><div id="app" v-text="greeting"></div><script>// 新建一个Vue实例new Vue({el:"#app",// 渲染哪个标签data:{greeting: "Hello Vue" //只要把greeting修改了,对应的页面的字也会跟着改变}})</script>
</body>
</html>
为什么Vue可以通过监听数据的变化来实现DOM的改变?
主要是使用了ES5中的Object.defineProperty 方法。所以不支持ES5的浏览器是无法使用Vue的。
// myname的属性被拦截了
Object.defineProperty(obj,"myname",{get(){console.log("get");},set(data){console.log(data);console.log("set");}}
)
// 定义了get和set方法,当通过obj.myname方式获取到值时,会自动触发get方法。通过obj.myname对myname属性值修改时,会自动触发set方法。即通过get、set方法拦截取值、赋值操作。
以下是Vue官网的一幅图片:
Vue的主要思想就是虚拟DOM的概念,因为修改DOM比较慢,但是更新DOM会比较快。在数据发生变化之后,Vue会根据新数据重新生成一个虚拟DOM,与原DOM进行比较,并在原DOM上进行修改,从而实现了较为快速的更新DOM。
但是Vue在更新数据响应方面有一些是无法进行响应的,主要就是对数组和对象的变化。
1.接下来围绕数据驱动,说说具体在哪些方面有体现:
11.通过指令得到体现
首先要说的是,指令的后面都会被Vue解析为data里面的变量。
v-html通过此属性的值会进行HTML转义。
v-bind 之后,属性值就是js代码。v-bind:class = :class,v-bind可以省略。此外v-bind还有一种绑定的方法,就是:
data() {return {name:'title',message: 'HelloWorld!'}
},
template: `<div:[name]="message">{{ message }}</div>`
上述使用:[name]的方式是属性的动态绑定,此时name就不是字符串 ,而是data中的name变量的值。
v-if 与 v-show:前者直接删除,后者不直接删除,只是加了display:none的属性
v-on:v-on:click="handleMyClicker",在methods中定义方法。可以省略为@click="handleMyClicker"
访问data中的数据,直接用this就可以。 v-once:DOM只渲染一次,data数据再改变也不会重新渲染DOM了
v-for:循环指令。一般为v-for="item in datalist"。对于这个指令需要注意的是in前面可以有两个参数,可以有三个参数。对于数组而言,可以有两个参数,即 v-for="(item,index) in datalist",item是指数组元素,index是指数组的元素索引,从0开始。item、index这两个可以随便写,Vue主要通过位置来判断哪个是值,哪个是索引。对于对象而言,就可以有三个参数了,如下:
有一个参数的情况:
objects:[
{id:1,message:"a"},
{id:2,message:"b"},
{id:3,message:"c"},
{id:4,message:"d"},
]一个参数很简单,通过点的方式获取到对象里的值:
<div v-for="item in objects">{{ item.id }} -- {{ item.message }}
</div>两个参数:
<div v-for="(item,data) in objects">{{ item.id }} -- {{ item.message }}
</div>
当然,索引和值在数组里面和在对象里面是不一样的。在数组里面索引是指数组元素的下标,但是在对象中则是键值。用v-for来遍历对象元素,如下:
<div id="app">
</div><script>const app = Vue.createApp({data(){return {listObj: {firstName: 'Dell',lastName: 'Lee'}}},template: `<div v-for="(value, key, index) in listObj">{{ value }} -- {{ key }} -- {{ index }}</div>`})app.$mount("#app")
</script>
v-for后面的循环条件,可以有of,也可以用in
v-for="items in objArr" objArr为列表
v-for="items in obj" obj为对象
v-for="items of obj" obj为对象,不可用of来遍历
v-for="items of objArr" 对于数组而言,in和of都可以
v-for还可以在标签内指定一个key值,个人认为这个key值的设置,主要作用就是提高Vue对DOM的渲染能力。一般会指定一个变量一个唯一的数值作为key,比如数据库查出来数据的主键值。那么key的作用到底是啥呢?前面说到改变数据后,Vue会对比两次的变化情况,以最小的代价对原DOM进行修改,那么在通过v-for输出数据后,对列表数据元素有插入或者删除,Vue并不知道插了那个元素还是删了哪个元素,只能从头开始一一对应的进行比对,被插入或删除的元素后所有的元素都会被重新渲染(错开了一个元素),所以比较好的解决办法就是列表的每个元素设置一个唯一的key值,Vue只要追踪这些key(key值相同的就不用再重新渲染),Vue就知道列表元素哪些被删掉,哪些被插入,从而以最小的代价修改DOM。当然,如果key值重复了,Vue就会报一个warn: Duplicate keys detected: 'XXX'. This may cause an update error.意思就是说key值重复了,可能会有错。简言之,如果对效率没啥要求,key设不设置都是一样的。在大型项目中,建议加入key值,特别是用Vue脚手架来开发程序。同时提醒key前面要加冒号,将赋值当做变量。
v-for还可以循环数字 v-for="item in 10" item会自动从1循环到10.
当v-for和v-if在一个标签中时,v-for的优先级比v-if要高,解决的办法就是用template标签嵌套div标签,外层template标签用v-for循环,内层div标签用v-if显示即可。
说到数据绑定,必须要说的一个指令就是:v-model指令,即双向数据绑定指令。啥叫双向数据绑定?即DOM改变了,影响数据,数据改变了又会影响DOM,这就是双向的意思。比如:<input type="text" v-model="mytext">{{ mytext }},换句话说数据驱动就是通过改变数据来改变DOM,这个一般是后端数据返回之后,会通过前端通过数据驱动将数据渲染到页面上。而用户对页面的一些操作,比如CheckBox勾选,比如input输入款输入数据,这些操作的结果返回至数据上就是数据的双向绑定。
既然是用户的输入会影响数据,那么不同的组件输入组件的如何呢?接下来就说说,说到与用户交互,第一点就是input框,这个很简单,背后就是一个字符串,这个没啥可说的。包括textarea背后也是一个字符串,接下来就是单/多选框,CheckBox:
只有一个checkbox的话,一般是传true或者false
<input type="checkbox" v-model="checkbox_value"/>a
上述,如果选中的话,checkbox_value的值就是true,没有选中的话就是false。如果不想使用true或者false,就可以在属性值上绑定true-value和false-value。
<input type="checkbox" v-model="checkbox_value" true-value="a" false-value="not_a"/>a
如果多选框有多个选项,如下:
<input type="checkbox" v-model="checkbox_value" value="a"/>a
<input type="checkbox" v-model="checkbox_value" value="b"/>b
<input type="checkbox" v-model="checkbox_value" value="c"/>c
<input type="checkbox" v-model="checkbox_value" value="d"/>d
CheckBox的标签有两个要素,一个是v-model还有一个就是value值。value值代表的是这个选项的值,v-model后面绑定的值代表的是这一个多选框组所的选中的值。v-model绑定同一个值,就代表是同一个多选框组。上图中最终的选值会形成一个数组赋值给checkbox_value。当然
如果是radio,即单选框,那么最终形成的绑定值不是一个数组,而是一个值。
<input type="radio" v-model="radio_value" value="a"/>a
<input type="radio" v-model="radio_value" value="b"/>b
<input type="radio" v-model="radio_value" value="c"/>c
<input type="radio" v-model="radio_value" value="d"/>d
选中哪个,就会把哪个value的值赋值给radio_value.
接下来,我们看看select如何进行数据双向绑定。
<select v-model="message"><option>A</option><option>B</option><option>C</option>
</select>
对于下拉选择框的绑定,则是通过字符串来进行绑定,选择哪个就会将哪个选项的标签内文字赋值给message,比如选择A,那么message的值就是A。如果给每个option标签增加一个value,那么与message进行双向数据绑定的值就是value的值。
多选的级联选择框,则message绑定出的就是一个数组,这一点与多选框与单选框是有相似的地方的。
option的value属性可以传一个对象,如下:
<select v-model="message"><option value={ value: 'A' }>A</option><option value={ value: 'B' }>B</option><option value={ value: 'C' }>C</option>
</select>
此时,message中传的就是{ value: 'A' }这样的一个对象。
插值表达式中可以放函数表达式,比如:{{ Func() }}。函数表达式的结果就是函数的返回值,在写的时候一定要加。
v-model有修饰符可以修饰一下,比如<input type='text' v-model.lazy="data" /> 就是给input框上加了一个懒加载的修饰符,这样的话,输入框就不会一有改变就会触发双向绑定,而是会在失去焦点时才会触发。这样的修饰符对于v-model来说还有两个,第一个是number:<input type='text' v-model.number="data" />就是可以将输入的数据转化为数字,当然,能转化的才会转化,不能转化的会变为空。第二个就是:<input type='text' v-model.trim="data" />,作用是去掉绑定字符串的首尾空格。
1.2.在class控制方面得到体现的。
如果我们有一个需求就是如果可以随机的根据需求来组合一些class,那么在传统的jQuery上,我们需要在业务上处理完数据之后,还要根据业务的数据需求来通过jQuery来操作DOM节点的class,也就是说动态调整class,如果这个需求在Vue里怎么通过数据驱动方式得到体现呢?
最基本的就是通过变量进行绑定:
<div id="app"><div :class="classString">我是内容</div>
</div><script>new Vue({el: '#app',data(){return {classString: 'red'}}})
</script>
<style>.red {color: red;}
</style>
第一种方法是对象方法,具体如下:
<div id="app"><div :class="classString">我是内容</div>
</div><script>new Vue({el: '#app',data(){return {classObj: { red: true, green: true }}}})
</script>
<style>.red {color: red;}.green {color: green}
</style>
还有一种方法就是数组写法。
<div id="app"><div :class="classArray">我是内容</div>
</div><script>new Vue({el: '#app',data(){return {classArray: [ 'red' , 'green']}}})
</script>
<style>.red {color: red;}.green {color: green}
</style>
也可以将数组和对象混合进行写:
<div id="app"><div :class="classArray">我是内容</div>
</div><script>new Vue({el: '#app',data(){return {classArray: [ 'red' , 'green', {brown: true}]}}})
</script>
<style>.red {color: red;}.green {color: green}.brown {color: brown}
</style>
class 在父子组件传值上也有一定的应用,如下代码:
<div id="app">
</div><script>const app = Vue.createApp({data(){return {classArray: [ 'red' , 'green', {brown: true}]}},template: `<div :class="classArray">我是内容<demo class="green" /></div>`})app.component('demo', {template: `<div :class="$attrs.class">one</div>`}app.$mount("#app")
</script>
<style>.red {color: red;}.green {color: green}.brown {color: brown}
</style>
子组件中,通过$attrs可以通过父组件向子组件传递class的值
1.3.在style控制方面得到体现。
与class控制相似,动态调整style也有对象方法和数组方法。首先看一下对象方法
<div id="app">
</div><script>const app = Vue.createApp({data(){return {classArray: [ 'red' , 'green', {brown: true}],styleString: 'color: yellow',styleObj: { color: 'orange' },}},template: `<div :style="styleString">我是内容</div><div :style="styleObj">我是内容2</div>`})app.$mount("#app")
</script>
<style>.red {color: red;}.green {color: green}.brown {color: brown}
</style>
从上可以看出通过数据绑定来扩展style的写法,也有字符串写法和对象写法两种。
1.4.特殊的地方
Vue是不能检测到通过索引值来改变数组的事件的。前面说到,Vue是通过重写了一些js的方法,在方法中重写了get、set函数拦截到值,再进行DOM更新的。而通过索引值改变数组,Vue无法通过get、set方法拦截到索引值,所以就无法通过数据响应来更新DOM值了。通过使用数组变更函数进行数组操作是可以响应DOM的,有push pop shift unshift reverse concat等函数。
在Vue3开始,就可以通过索引值操作数组,或者直接操作对象元素也会引起DOM的变化。
2.模糊查询之 filter
首先filter不会改变原数组。
filter()参数接受一个函数。函数返回false就是不通过,返回true就是通过。看如下代码:
arr=[1,2,3,4,5,6,7,8,9]
var arr2 = arr.filter(item=>{return item>3 这个就是将数组中元素值大于3的返回,item就是每次从数组中取的值
})换句话说就是挨个儿遍历数组,满足return后面条件的,就会返回。
3.关于事件处理器
事件触发器的三种写法:
{{ count }}
<button @click="handlerFunc()">点击我</button>
<button @click="handlerFunc2">点击我</button>
事件中不加小括号,会自动将事件对象传过来。
想要传参数只能加小括号。
如果又想拿到事件对象,又想传参,写法如下:
<button @click="handlerFunc3($event,a)">点击我</button>
a就是自己的参数,$event就是事件对象。$event是固定写法。
<button @click="count++">点击我</button> 简单的代码可以写在HTML中
<script>el:#appdata:{count:0}methods:{handlerFunc(){this.count++}handlerFunc2(){this.count++}}
</script>
事件会进行冒泡,即出发里面的时间,会从内向外将所有事件都触发一遍。那么如何阻止冒泡呢?
首先可以通过sopPropagation方法来阻止冒泡。即将事件对象拿到后,调用该函数。如事件对象通过$event传到形参evt中,直接evt.stopPropagation()就行了。
当然,也可以通过事件修饰符来进行阻止冒泡,阻止父标签的事件触发。<div @click.stop="handlerFunc">阻止冒泡</div>。这个方法是从孩子角度阻止事件冒泡到父标签。我们也可以通过父标签来阻止子标签的事件:<div @click.self="handlerFunc">...</div>,加上self的事件修饰符,标签只相应自己的事件,对于子标签冒泡上来的事件则会忽略。
阻止标签的默认行为,比如阻止a标签的href功能,同样也可以通过事件修饰符来完成。即:<a href="www.baidu.com" @click:prevent> 阻止默认行为</a>。当然也可以尝试用原始的preventDefault来完成。
还有一种事件修饰符是让事件只触发一次:<div @click.once="handlerFunc">...</div>。当然,我们也可以自己手动解绑事件:<div @click="isActive && handlerFunc()">手动事件解绑</div>。在handlerFunc函数中,将isActive赋值为false,就不会再触发handlerFunc函数了。
之前说的都是鼠标事件响应,那么按键的事件如何触发呢?
<input type="text" @keydown="handleKeyDown">按键触发</input>对于keydown传回的事件对象中会包含按键的值,即通过ev.keyCode拿到键值,ev为传回的时间对象。以上是通过事件对象传回来自己拿到键值判断的,那么如何像其他事件一样通过时间修饰符实现呢?比如:<input type="text" @keydown.enter="handleKeyDown">就是通过.enter的事件修饰符实现了只按下回车键的时候,才会触发handleKeyDown事件。同样的事件修饰符还有:.up .down .left .right :方向符号、.space:空格键。最厉害的还是可以直接点键值就行了,比如:@keydown.13="handleKeyDown"就会触发键值为13的按键按下事件。
v-on绑定事件事件修饰符有.stop .prevent .capture .self .once .passive用法为:@click.prevent="handleClick".
- .stop 调用
event.stopPropagation(),阻止事件冒泡。
- .prevent 调用
event.preventDefault()
- .capture 添加事件侦听器时使用 capture 模式。
- .self 只当事件是从侦听器绑定的元素本身触发时才触发回调。
-
点击按钮,则不会触发handleDivClick事件,只有在点击只有div的部分才会触发handleDivClick事件 <div @click.self="handleDivClick">{{ counter }}<button @click="handleClick">button</button> </div>
- .once 事件只触发一次
- .passive 提升页面滚动的性能
对应鼠标的事件修饰符有,使用方法为@click.left:
.left
.right
.middle
对应的键盘修饰符有,比如@keydown.enter:
.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta
提示
注意:在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。在 Sun 操作系统键盘上,meta 对应实心宝石键 (◆)。在其他特定键盘上,尤其在 MIT 和 Lisp 机器的键盘、以及其后继产品,比如 Knight 键盘、space-cadet 键盘,meta 被标记为“META”。在 Symbolics 键盘上,meta 被标记为“META”或者“Meta”。
上述的键盘修饰符指的都是别名,最全的还是通过之前所讲的,利用keyCode来实现键盘的监听。
此外还有精确修饰符.exact
@click.ctrl.exact 只有按住ctrl再点击才会触发事件,多按其他按键没有用。
事件修饰符还可以串联,比如:
<a @click.stop.prevent="doThat"></a>
还有就是之前在v-bind中所述的动态绑定在绑定事件的时候也会有所体现,如下:。
data() {return {event:'click',message: 'HelloWorld!'}
},
template: `<div@[event]="handleClick">{{ message }}</div>`
通过上述绑定,则[event]就指代了event所代表的值。
处理事件的方法第一个参数默认回调的是这个时间的本身,如:
<button @click="handleClick">点击</button>methods: {handleClick(event){此处的event默认指时间本身}
}
那么如果本身就要额外传递参数,同时又想获得事件对象,该怎么处理呢?
<button @click="handleClick(2, $event)">点击</button>methods: {handleClick(count,event){此处的event默认指时间本身}
}
如上,只要传一个$event参数就可以了。
如果绑定一个时间要执行多个函数,则采用:
<button @click="handleClick(), handleClick2()">点击</button>
4. 计算属性
定义起来像个方法,用起来像个属性。
<div id="app">{{ get_sum }}
</div><script>new Vue({el:#app,computed:{get_sum(){return 12}}
})
</script>
<style>.
</style>
用的时候不要加括号,如果加括号的话就是方法。
那为啥不直接用方法呢?
因为计算属性比方法的效率高。如果计算数不变(计算属性内的函数所涉及到的成员变量不变)的话,那么多次调用计算属性,计算属性只会计算一遍。而方法则是调用一次执行一次,效率不如计算属性那么高。换句话说,就是计算属性是带有缓存的,缓存的数据不变,是不会渲染页面的。
5. 监听器watch的使用
watch可以用来监听某一个值或者状态发生变化,会触发一个函数。
<div id="app">{{ get_sum }}
</div><script>new Vue({el:#app,data(){return{total:[]}}watch:{total(newValue,oldValue){这个watch用来监听data中的total变化情况。如果发生变化就会触发这个函数,并将新值和旧值分别传给newValue和oldValue}}
})
</script>
<style>.
</style>
默认情况下,watch在初始化之后是不执行的。如果想watch在页面初始化的时候,就执行,则需要换种写法,如下:
<div id="app">{{ get_sum }}
</div><script>new Vue({el:#app,data(){return{total:[]}}watch:{total: {immediate: true,// 此处设置为true就代表立即执行deep: true, // 如果监控的数据是对象、数组相互嵌套的,就需要进行设置这个选项handler(newValue,oldValue){这个watch用来监听data中的total变化情况。如果发生变化就会触发这个函数,并将新值和旧值分别传给newValue和oldValue}}}
})
</script>
<style>.
</style>
如果能用computed实现就用computed实现。但是computed与watch之前使用的还是有一些规律可循:
computed适合那些一个值受多个值控制,如果多个值中有一个值变化,那么就是用computed监控受影响的值。
watch适合一个值变化来影响其他值的情况。
computed有缓存属性。而监听器选项提供出了更通用的方法,适合执行异步操作或较大开销操作的情况。
6. 其他的注意点
- methods中的方法不要使用箭头函数,methods中的this指向Vue实例,但是如果使用箭头函数则
这篇关于Vue知识点唠嗑之数据驱动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!