参考文章:
- https://www.cnblogs.com/fundebug/p/vue-virtual-dom.html
- https://blog.csdn.net/qq_42701999/article/details/102926774
vue基本语法
1. 插入到html中的{{}}
是动态变化的,随着括号内的变量的变化而变化
2. v-bind
和v-model
v-bind
和v-model
都是绑定属性的。v-model
只作用于表单元素的属性绑定,且它是双向绑定的。即在页面上的直接操作也会改变变量。v-bind
可以作用于所有属性,它是单向绑定的。在页面的直接操作不会改变变量。v-bind
可以简写为:
3. v-text
和v-html
v-text="变量名"
会将引号后的变量对应的值解析成纯文本。而v-html="变量名"
会将引号后的变量对应的值解析为html
4. 绑定class
- 绑定单个类:
v-bind:class="类名"
- 绑定多个类(四种方式):
①:class="[变量名1,变量名2]"
②:class="['类名1','类名2']
③:class="{类名1:true/false,类名2:true/false}"
:类名可以放到引号里,也可以直接写,即:class="{'类名1':true/false,'类名2':true/false}
也是正确的。
④:class="变量名"
:将所有类写到一个变量中,且多个类之间用空格间隔开,class
动态绑定该变量。
5. 绑定style
用对象的方式绑定。属性可以放到引号,也可以直接写。变量不能用引号引起来。不可以将对象写到变量中,然后style动态绑定该变量。这样会报错。
:style="{'color':activityColr,'fontSize':font}"
。
6. v-for
v-for
有两种写法:①v-for="(item,index) in 可遍历列表" :key="可唯一标识当前元素的变量"
②v-for="(item) in 可遍历列表" :key="可唯一标识当前元素的变量"
v-for
上不能直接写v-if
,会报警告,但是不会报错。
7. v-if
和v-show
v-show="boolean变量/boolean值/表达式"
代表显示隐藏。当boolean变量/值/表达式为true
时代表显示,否则为false
。用该方式来控制显示隐藏并不是将标签移除,而是隐藏起来(即对象未被移除,只是隐藏起来了)。v-if="boolean变量/boolean值/表达式"
。用v-if
控制的显示隐藏是将对象移除,等到再次显示时为重新创建v-if
、v-else-if
、v-else
8. 事件
插入一点之前的笔记:
① 事件的基本语法
- 用
v-on:事件="触发函数"
来给一个标签元素绑定触发事件。v-on
可以简写为@
- 在事件中访问
data
中的变量有两种方式:①this.变量名
②this._data.变量名
- 得到事件触发源:①
e.target
②e.srcElement
其中e为事件参数。在这里要注意,当触发事件没有给方法传参时,形参e即为事件参数。当有多个参数时,可以给方法传$event
参数。$event
即为事件参数.self
可理解为事件委托,将事件委托给自身,只有自身可以触发事件.prevent
:阻止事件的默认行为.capture
:相当于事件的捕获。 当给父亲写时,触发子元素事件会先触发父元素相关事件,再触发子元素事件。当给孩子写时,无效果.once
:事件只触发一次.stop
:阻止事件冒泡。eg:<div @click.capture.stop="sonMethod" class="test2">12345</div>
- 按键修饰符:只要按下特定键才会执行方法。eg:
@keyup.13="方法" = @keyup.enter="方法"
:只有当按下的按键的ascii码为13(即enter键)时才会触发后面的方法。(只有特定的按键才能直接使用名称。一般的键不能直接使用名称,只能使用keyCode值)
//下面例子中,2和3实际是相同含义
//1
<button v-on:click="test(1,$event)">点击变化isComplete</button>
test(num,event){
console.log(num,event);//1,event为事件参数
}
//2
<button v-on:click="test">点击变化isComplete</button>
test(event){
console.log(event);//event为事件参数
},
//3
<button v-on:click="test($event)">点击变化isComplete</button>
test(event){
console.log(event);//event为事件参数
},
② 键盘事件的执行参数
e.target=e.srcElement
:事件源e.key = e.code
:按键字符e.which = e.keycode
:按键字符ASCII码
③ 鼠标事件的执行参数
e.target=e.srcElement
e.clientX
、e.clientY
e.pageX
、e.pageY
e.timestamp
9. vue获取虚拟dom
- 为某一标签添加
ref
属性,可给该属性随意取名称,在任一方法中可通过this.$refs.xxx
来获取该标签(xxx为标签上ref
属性后面的值)- vue操作的是虚拟Dom,虚拟dom是真实dom的一层抽象,最终可以通过一系列操作使虚拟Dom这棵树映射到真实环境上。虚拟dom不会修改一次就立即操作Dom,而是等待修改完毕后才操作dom。可提高性能
- 模板转换为视图的步骤
① Vue.js通过编译将template
模板转换成渲染函数(render
) ,执行渲染函数就可以得到一个虚拟节点树
② 在对Model
进行操作的时候,会触发对应Dep
中的Watcher
对象。Watcher
对象会调用对应的update
来修改视图。这个过程主要是将新旧虚拟节点进行差异对比,然后根据对比结果进行DOM操作来更新视图
③ 模板转换为视图的过程:模板 → 渲染函数 → 虚拟DOM树 → 真实DOM- 虚拟DOM原理:
① 虚拟DOM的最终目标是将虚拟节点渲染到视图上。但是如果直接使用虚拟节点覆盖旧节点的话,会有很多不必要的DOM操作。例如:一个ul标签下很多个li标签,其中只有一个li有变化,这种情况下如果使用新的ul去替代旧的ul,因为这些不必要的DOM操作而造成了性能上的浪费。
② 为了避免不必要的DOM操作,虚拟DOM在虚拟节点映射到视图的过程中,将虚拟节点与上一次渲染视图所使用的旧虚拟节点(oldVnode)做对比,找出真正需要更新的节点来进行DOM操作,从而避免操作其他无需改动的DOM
③ 其实虚拟DOM在Vue.js主要做了两件事:
a. 提供与真实DOM节点所对应的虚拟节点vnode;
b. 将虚拟节点vnode和旧虚拟节点oldVnode进行对比,然后更新视图;
10. 计算属性computed
计算属性中的函数的调用方法和普通函数不同,其不需要加括号调用。只需写出方法名即可调用。
在计算属性中需要注意的几点;
① 如果在页面中动态绑定计算属性,计算属性必须有返回值。
② 在计算属性的方法中,方法中返回值的变量改变时都会调用该方法(对象和数组对其本身进行操作/引用改变时会调用(eg:数组进行push/splice操作以及重新给其赋值时会调用))
③ 计算属性的get
和set
方法(在下面例子中,改变firstName/secondName/fullName都会导致其余两个变化)
<input type="text" v-model="fullName"/>//当用户对该文本框中的文字进行修改时会调用fullName的set方法
//当用户对下两个文本框中的文字进行修改时都会调用fullName的get方法
<input type="text" v-model="firstName"/>
<input type="text" v-model="lastName"/>
fullName:{
get(){
//当firstName 和lastName任意一个变化时都会调用get方法,必须要return,否则不能动态双向绑定
return this.firstName+' '+this.lastName;
},
set(value){
//当fullName变化时调用set方法
const names = value.split(' ');
this.firstName = names[0]
this.lastName = names[1]
}
}
11. watch
- 监听变量的变化。函数名为变量名。
- 若改变数组的元素/对象属性值不会触发watch中的函数,只有当对数组/对象本身进行操作时才会触发(数组/对象的重新赋值、数组的增删)
- watch中的每个方法可以接收两个值==(newVal,oldVal)==,只有当数组和对象的引用改变时,新值和旧值时不同的。若只是对数组进行增加元素、删除元素操作,新旧值仍是相同的。
12. 过滤器:filters
使用:
- 在html中使用:
{{变量 | filters中定义的方法}}
- 在
filters:{}
中定义所有管道符后面的方法
几点注意事项:
- 只要管道符前面的变量变化就会重新执行一次对应的方法
- 在方法中,返回之前对值进行过滤
- 若方法只有一个参,则该参数为管道符前面的变量值
- 当给过滤器中的方法传的参改变时(非管道符前面的变量),也会调用对应方法。
- 不能在
v-for
的in
后直接写过滤器来过滤列表。可通过一个函数,将列表过滤
在例1中,如果不将val用扩展运算符赋值给array,会导致无限循环(当管道符前面的变量对应的值改变时会重新调用过滤器中对应的方法,而sort方法会改变原数组。故会陷入无限循环)
//1
<p>{{temp | mysort}}</p>// temp:[1,2,3,4,5,6],
filters:{
mysort(val){
//val为 变量temp对应的值
let array = [...val]
array.sort((a,b)=>(b-a));
return array;
},
}
在例2中,当sex
和sexTxt
值任意一个变化时都会重新调用sexList
方法。
//2
<input type="text" v-model="sexTxt">
<p>{{sex | sexList(sexTxt)}}</p>// sex:["男","女","男","男","男","女"],
filters:{
sexList(val,sexTxt){
console.log(1111)
let arr=[];
for(let i=0;i<val.length;i++){
if(val[i]==sexTxt){
arr.push(val[i]);
}
}
return arr;
}
},
在例3中,可以在li
里面写过滤器,但是不能在in
后面写过滤器。可以通过一个函数来返回过滤后的列表(若操作的是一个数组,则需要将该函数放置computed
里面,若放到methods
里面则仍需用扩展运算符来解决无限循环的问题。而在computed
里面可以直接对原数组进行操作(因为在computed
的方法里面,若返回值是数组,只有数组的引用变化或对数组进行增删操作时才会重新调用该方法,否则正常调用几次方法就执行几次))
//3
<ul>
//不能在v-for处直接写过滤器,可通过一个函数,将数组过滤
<li v-for="(item,index) in forSort" :key="index">
// {{item | neeVal}}
{{item}}
</li>
</ul>
forSort(){
return this.liList.sort((a,b)=>(b-a))
},