- 2.1 v-on可以監(jiān)聽多個(gè)方法嗎?
- v-on 綁定單個(gè)或多個(gè)事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" :value="name" @input="onInput" @focus="onFocus" @blur="onBlur" />
<input v-on:keyup.enter="submit" v-on:focus="onFocus">
<!-- <button v-on:click="myclick('hello','world','你好世界',$event)" >button1</button> -->
<button @click="myclick('hello','world','你好世界',$event)">點(diǎn)我text</button>
<!-- v-on綁定多個(gè)事件教程里這樣子寫,但是貌似已經(jīng)不支持這樣子的寫法了,
內(nèi)聯(lián)方式下事件處理器只能綁定一個(gè)方法,要是想要綁定多個(gè)事件,用下面第二行的方式-->
<!-- <button v-on="{mouseenter: onEnter,mouseleave: onLeave}">鼠標(biāo)進(jìn)來</button> -->
<button @mouseenter="onEnter" @mouseleave="onLeave">鼠標(biāo)進(jìn)來</button>
<!-- 一個(gè)事件綁定多個(gè)函數(shù),按順序執(zhí)行,這里分隔函數(shù)可以用逗號(hào)也可以用分號(hào)-->
<button @click="a(),b()">點(diǎn)我ab</button>
<button @click="one()">點(diǎn)我onetwothree</button>
<!-- v-on修飾符 .stop .prevent .capture .self 以及指定按鍵.{keyCode|keyAlias} -->
<!-- 這里的.stop 和 .prevent也可以通過傳入&event進(jìn)行操作 -->
<!-- 全部按鍵別名有:enter tab delete esc space up down left right -->
<form @keyup.delete="onKeyup" @submit.prevent="onSubmit">
<input type="text" placeholder="在這里按delete">
<button type="submit">點(diǎn)我提交</button>
</form>
</div>
<script src="vue221.js"></script>
<script>
var vm = new Vue({
el:"#app",
methods:{
//這里是es6對象里函數(shù)寫法
a(){console.log("a");},
b(){console.log("b");},
one(){
console.log("one");
this.two();
this.three();
},
two(){
console.log("two");
},
three(){
console.log("three");
},
myclick(msg1,msg2,msg3,event){
console.log(msg1+msg2+"--"+msg3);
console.log(event);
},
onKeyup(){
console.log("you press 'delete'");
},
onSubmit(){
console.log("sumited");
},
onEnter(){
console.log("mouse enter");
},
onLeave(){
console.log("mouse leave");
}
}
});
</script>
</body>
</html>
- 2.2 vue中 key 值的作用
數(shù)組的v-for
item in items
item of items
item,index in items
(item,index) in items
對象的v-for(鍵值,鍵名,索引)
value in object
(value, key) in object
(value, key, index) in object
key的作用主要是為了高效的更新虛擬DOM。
另外vue中在使用相同標(biāo)簽名元素的過渡切換時(shí),也會(huì)使用到key屬性,
其目的也是為了讓vue可以區(qū)分它們,
否則vue只會(huì)替換其內(nèi)部屬性而不會(huì)觸發(fā)過渡效果。
key的用法一般是:key='id',意思是為元素綁定一個(gè)key屬性,這個(gè)key屬性為元素添加了一個(gè)唯一身份標(biāo)識(shí)符。
之后,當(dāng)數(shù)據(jù)改變,Vue底層通過對比能夠更快的獲取到更新的內(nèi)容并顯示到頁面上。
總之就是一句話,key屬性能夠提升性能(主要作用于數(shù)據(jù)更新時(shí))。
- 2.3 vue-cli工程升級(jí)vue版本
package.json 里面修改vue的版本 同時(shí)修改 vue-template-compiler 為相同的版本.后者在devdepen....里面.然后npm install;
在項(xiàng)目目錄里運(yùn)行 npm upgrade vue vue-template-compiler,不出意外的話,可以正常運(yùn)行和 build。如果有任何問題,刪除 node_modules 文件夾然后重新運(yùn)行 npm i 即可。
- 2.4 基于Vue cli生成的Vue項(xiàng)目的webpack4升級(jí)
參考大佬https://www.colabug.com/3206468.html
https://github.com/littlematch0123/blog-client
https://github.com/littlematch0123
- 2.5 vue事件中如何使用event對象?
div id="app">
<button v-on:click="click">click me</button>
</div>
...
var app = new Vue({
el: '#app',
methods: {
click(event) {
console.log(typeof event); // object
}
}
});
<div id="app">
<button v-on:click="click()">click me</button>
</div>
...
var app = new Vue({
el: '#app',
methods: {
click(event) {
console.log(typeof event); // undefined
}
}
});
<div id="app">
<button v-on:click="click($event, 233)">click me</button>
</div>
...
//獲取事件對象 , 方法參數(shù)傳遞 $event
var app = new Vue({
el: '#app',
methods: {
click(event, val) {
console.log(typeof event); // object
}
}
});
<div id="app">
<button v-on:click="click(233)">click me</button>
</div>
...
var app = new Vue({
el: '#app',
methods: {
click(val) {
console.log(typeof event); // object
}
}
});
第一種是沒有帶圓括號(hào),注意這時(shí)在處理函數(shù)的形參中是定義了 event 的,vue 在執(zhí)行的時(shí)候,自動(dòng)將 event 對象作為參數(shù)傳入到其中了,所以我們?nèi)〉降?event 對象其實(shí)是真正傳入到處理函數(shù)中的參數(shù),一定程度上可以理解成是該函數(shù)的局部變量;
第二種是帶了圓括號(hào)的,這時(shí)的形參表里并沒有定義 event 這一個(gè)參數(shù),當(dāng)前作用域并沒有定義 evnet 這一個(gè)對象,所以 js 會(huì)嘗試在定義這個(gè)處理函數(shù)的上級(jí)作用域中搜索 event 變量,仍未找到,最終到達(dá)全局作用域上,找到了 window.event 這一個(gè)對象,但是這一個(gè)對象并不是我們期望的 event 對象。
準(zhǔn)確的說,是因?yàn)檫@一個(gè)對象存在兼容性問題,js 代碼中常見的 var event = event || window.event; 就是這個(gè)道理,查 MDN 上說只有 IE/Edge/Chrome 支持。(實(shí)際上 Safari 也支持)
<li v-for="img in willLoadImg" @click="selectImg($event)">
<img class="loadimg" :src="img.url" :data-id="img.id" alt="">
</li>
currentTarget:currentTarget 事件屬性返回其監(jiān)聽器觸發(fā)事件的節(jié)點(diǎn),即當(dāng)前處理該事件的元素、文檔或窗口。
通俗一點(diǎn)說,就是你的點(diǎn)擊事件綁定在哪一個(gè)元素上,currentTarget獲取到的就是哪一個(gè)元素。
target:target 事件屬性可返回事件的目標(biāo)節(jié)點(diǎn)(觸發(fā)該事件的節(jié)點(diǎn)),如生成事件的元素、文檔或窗口。
通俗一點(diǎn)說,就是你當(dāng)前點(diǎn)擊的是哪一個(gè)元素,target獲取到的就是哪一個(gè)元素。
methods: {
selectImg(event) {
console.log(event.currentTarget);
console.log(event.target);
}
}
//獲得event對象兼容性寫法
event || (event = window.event);
//獲得target兼容型寫法
event.target||event.srcElement
//阻止瀏覽器默認(rèn)行為兼容性寫法
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
//阻止冒泡寫法
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);
- 2.6 $nextTick的使用
this.$nextTick()將回調(diào)延遲到下次 DOM 更新循環(huán)之后執(zhí)行。在修改數(shù)據(jù)之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一樣,不同的是回調(diào)的 this 自動(dòng)綁定到調(diào)用它的實(shí)例上。
假設(shè)我們更改了某個(gè)dom元素內(nèi)部的文本,而這時(shí)候我們想直接打印出這個(gè)被改變后的文本是需要dom更新之后才會(huì)實(shí)現(xiàn)的,也就好比我們將打印輸出的代碼放在setTimeout(fn, 0)中;
- 2.7 Vue 組件中 data 為什么必須是函數(shù)?
類比引用數(shù)據(jù)類型
Object是引用數(shù)據(jù)類型,如果不用function 返回,每個(gè)組件的data 都是內(nèi)存的同一個(gè)地址,一個(gè)數(shù)據(jù)改變了其他也改變了;
javascipt只有函數(shù)構(gòu)成作用域(注意理解作用域,只有函數(shù)的{}構(gòu)成作用域,對象的{}以及 if(){}都不構(gòu)成作用域),data是一個(gè)函數(shù)時(shí),每個(gè)組件實(shí)例都有自己的作用域,每個(gè)實(shí)例相互獨(dú)立,不會(huì)相互影響
const MyComponent = function() {};
MyComponent.prototype.data = {
a: 1,
b: 2,
}
const component1 = new MyComponent();
const component2 = new MyComponent();
component1.data.a === component2.data.a; // true;
component1.data.b = 5;
component2.data.b // 5
如果兩個(gè)實(shí)例同時(shí)引用一個(gè)對象,那么當(dāng)你修改其中一個(gè)屬性的時(shí)候,另外一個(gè)實(shí)例也會(huì)跟著改;
兩個(gè)實(shí)例應(yīng)該有自己各自的域才對,需要通過下面的方法來進(jìn)行處理
const MyComponent = function() {
this.data = this.data();
};
MyComponent.prototype.data = function() {
return {
a: 1,
b: 2,
}
};
這樣每一個(gè)實(shí)例的data屬性都是獨(dú)立的,不會(huì)相互影響了.因此每個(gè)實(shí)例可以維護(hù)一份被返回對象的獨(dú)立的拷貝
所以,你現(xiàn)在知道為什么vue組件的data必須是函數(shù)了吧。這都是因?yàn)閖s本身的特性帶來的,跟vue本身設(shè)計(jì)無關(guān)。其實(shí)vue不應(yīng)該把這個(gè)方法名取為data(),應(yīng)該叫setData或其他更容易理解的方法名。
- 2.8 v-for 與 v-if 的優(yōu)先級(jí)
當(dāng)它們處于同一節(jié)點(diǎn),v-for 的優(yōu)先級(jí)比 v-if 更高,這意味著 v-if 將分別重復(fù)運(yùn)行于每個(gè) v-for 循環(huán)中。當(dāng)你想為僅有的一些項(xiàng)渲染節(jié)點(diǎn)時(shí),這種優(yōu)先級(jí)的機(jī)制會(huì)十分有用,如下:
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>
上面的代碼只傳遞了未完成的 todos。
而如果你的目的是有條件地跳過循環(huán)的執(zhí)行,那么可以將 v-if 置于外層元素 (或 <template>)上。如:
<ul v-if="todos.length">
<li v-for="todo in todos">
{{ todo }}
</li>
</ul>
<p v-else>No todos left!</p>
題外話
永遠(yuǎn)不要把 v-if 和 v-for 同時(shí)用在同一個(gè)元素上。
一般我們在兩種常見的情況下會(huì)傾向于這樣做:
為了過濾一個(gè)列表中的項(xiàng)目 (比如 v-for="user in users" v-if="user.isActive")。在這種情形下,請將 users 替換為一個(gè)計(jì)算屬性 (比如 activeUsers),讓其返回過濾后的列表。
為了避免渲染本應(yīng)該被隱藏的列表 (比如 v-for="user in users" v-if="shouldShowUsers")。這種情形下,請將 v-if 移動(dòng)至容器元素上 (比如 ul, ol)。
<ul v-if="shouldShowUsers">
<li
v-for="user in users"
:key="user.id"
>
{{ user.name }}
</li>
</ul>