一. 基本指令
1. v-for
數據准備
data() {
return {
userInfo: { name: 'ypf', age: 18, school: '北大' },
movies: ["星際穿越", "盜夢空間", "大話西游", "教父", ],
userList: [
{ name: 'ypf1', age: 18, school: '北大1' },
{ name: 'ypf2', age: 19, school: '北大2' },
{ name: 'ypf3', age: 20, school: '北大3' }
]
}
}
(1). 遍歷對象
格式:
<h4>1.遍歷對象</h4> <ul> <li v-for="(value,key,index) in userInfo" :key='index'> {{index}}-{{key}}--{{value}} </li> </ul>
(2). 遍歷數字
格式: item in 數字
<h4>2.遍歷數字</h4> <ul> <li v-for="value in 5"> {{value}} </li> </ul>
(3). 遍歷數組【重點】
格式:item in 數組
(item, index) in 數組
A. 普通數組
<h5>3.1 普通數組</h5> <ul> <li v-for="(item,index) in movies" :key='index'>{{index}}-{{item}}</li> </ul>
B. 數組對象
<h5>3.2 數組對象</h5> <ul> <li v-for="(item,index) in userList" :key='index'> {{index}}-{{item.name}}-{{item.age}}-{{item.school}} </li> </ul>
補充:
我們發現,每個v-for,我們都賦值了一個key屬性,key屬性里的內容建議用唯一值,這里涉及到diff算法,提高效率,后面章節重點剖析。
2. 數組方法
(1).變異方法:
背景:在 Vue 中,直接修改對象屬性的值無法觸發響應式。當你直接修改了對象屬性的值,你會發現,只有數據改了,但是頁面內容並沒有改變。所以:Vue中引入變異數組方法,即保持數組方法原有功能不變的前提下對其進行功能拓展,使其支持響應式。
常用方法:
a. push: 往數組最后面添加一個元素,成功返回當前數組的長度。
b. pop: 刪除數組的最后一個元素,成功返回刪除元素的值
c. shift: 刪除數組的第一個元素,成功返回刪除元素的值
d. unshift: 往數組最前面添加一個元素,成功返回當前數組的長度
e. splice: 刪除,有三個參數,第一個要刪除元素的下標(必選),第二個要刪除元素的個數(必選),第三個刪除后想在原位置替換的值
f. sort: 將數組按照字符編碼從小到大排序,成功返回排序后的數組
g. reverse: 將數組倒序排列,並返回倒敘后的數組
(2).替換數組
含義: 不會影響原始的數組數據,而是形成一個新的數組.
常用方法:
a. filter: 創建一個新的數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素。
b. concat: 用於連接兩個或多個數組,該方法不會改變現有的數組。
c. slice: 從已有的數組中返回選定的元素。該方法並不會修改數組,而是返回一個子數組
eg:從第0個開始,獲取兩個元素 this.list = this.list.slice(0, 2);
案例參考:
https://www.cnblogs.com/yaopengfei/p/12315704.html 底部的圖書管理代碼。
二. v-model
1. 基本使用和原理
v-model指令可以在表單 input、textarea以及select元素上創建雙向數據綁定;它會根據控件類型自動選取正確的方法來更新元素;盡管有些神奇,但 v-model 本質上不過是語法糖,它負責監聽用戶的輸入事件來更新數據,並在某種極端場景下進行一些特殊處理;
<body> <div id="app"></div> <template id="myApp"> <div> <input v-model="msg" /> <h5>等價於</h5> <!-- 等價於 --> <input :value="msg" @input="change1"> </div> </template> <script src="../js/vue3.js" ></script> <script> Vue.createApp({ template: '#myApp', data() { return { msg: 'Hello Vue3!' } }, methods:{ change1(event){ this.msg=event.target.value; } } }).mount('#app'); </script> </body>
剖析本質:v-model的原理其實是背后有兩個操作:
(1). v-bind綁定value屬性的值;
(2). v-on綁定input事件監聽到函數中,函數會獲取最新的值賦值到綁定的屬性中;
2. 綁定常用標簽
v-model還可以綁定:textarea、checkbox、radio、select。
代碼分享:

<body> <div id="app"></div> <template id="myApp"> <!-- 1.綁定textarea --> <label for="intro"> 自我介紹 <textarea name="intro" id="intro" cols="30" rows="10" v-model="intro"></textarea> </label> <h2>intro: {{intro}}</h2> <!-- 2.checkbox --> <!-- 2.1.單選框 --> <label for="agree"> <input id="agree" type="checkbox" v-model="isAgree"> 同意協議 </label> <h2>isAgree: {{isAgree}}</h2> <!-- 2.2.多選框 --> <span>你的愛好: </span> <label for="basketball"> <input id="basketball" type="checkbox" v-model="hobbies" value="basketball"> 籃球 </label> <label for="football"> <input id="football" type="checkbox" v-model="hobbies" value="football"> 足球 </label> <label for="tennis"> <input id="tennis" type="checkbox" v-model="hobbies" value="tennis"> 網 球 </label> <h2>hobbies: {{hobbies}}</h2> <!-- 3.radio --> <span>你的愛好: </span> <label for="male"> <input id="male" type="radio" v-model="gender" value="male">男 </label> <label for="female"> <input id="female" type="radio" v-model="gender" value="female">女 </label> <h2>gender: {{gender}}</h2> <!-- 4.select --> <span>喜歡的水果: </span> <select v-model="fruit" multiple size="2"> <option value="apple">蘋果</option> <option value="orange">橘子</option> <option value="banana">香蕉</option> </select> <h2>fruit: {{fruit}}</h2> </template> <script src="../js/vue3.js"></script> <script> Vue.createApp({ template: '#myApp', data() { return { intro: "Hello World", isAgree: false, hobbies: ["basketball", "football"], gender: "", fruit: "orange" } } }).mount('#app'); </script> </body>
3. 修飾符
lazy修飾符的作用:
默認情況下,v-model在進行雙向綁定時,綁定的是input事件,那么會在每次內容輸入后就將最新的值和綁定的屬性進行同步;
如果我們在v-model后跟上lazy修飾符,那么會將綁定的事件切換為 change 事件,只有在提交時(比如回車)才會觸發;
number修飾符
代碼分享:
<body> <div id="app"></div> <template id="myApp"> <!-- 1.lazy修飾符 敲擊回車才有效--> <input type="text" v-model.lazy="message"> <br> <!-- 2.number修飾符 --> <input type="text" v-model.number="message"> <h2>{{message}}</h2> <button @click="showType">查看類型</button> <!-- 3.trim修飾符 --> <input type="text" v-model.trim="message"> <button @click="showResult">查看結果</button> </template> <script src="../js/vue3.js"></script> <script> Vue.createApp({ template: '#myApp', data() { return { message: "Hello World" } }, methods: { showType() { console.log(this.message, typeof this.message); }, showResult() { console.log(this.message); } } }).mount('#app'); </script> </body>
三. 計算屬性computed
1. 什么時候用計算屬性?
對於任何包含響應式數據的復雜邏輯,你都應該使用計算屬性;
計算屬性看起來像是一個函數,但是我們在使用的時候不需要加(),這個后面講setter和getter時會講到;
2. 基本用法
<body> <div id="app"></div> <template id="myApp"> <div> {{fullName}} </div> <div> {{finalResult}} </div> </template> <script src="../js/vue3.js"></script> <script> Vue.createApp({ template: '#myApp', data() { return { firstName: 'BBB', lastName: 'AAA', message: "Hello Vue3" } }, computed: { fullName() { return this.lastName + ' ' + this.firstName; }, finalResult() { return this.message.split(' ').reverse().join(' '); } } }).mount('#app'); </script> </body>
3. get 和 set方法
計算屬性在大多數情況下,只需要一個get方法即可,所以我們會將計算屬性直接寫成一個函數。
但是,如果我們確實想設置計算屬性的值呢?這個時候我們也可以給計算屬性設置一個set的方法

<body> <div id="app"></div> <template id="myApp"> <div> {{fullName1}} </div> <div> {{fullName2}} </div> </template> <script src="../js/vue3.js"></script> <script> Vue.createApp({ template: '#myApp', data() { return { firstName: 'BBB', lastName: 'AAA', } }, computed: { // 相當於get方法 fullName1() { return this.lastName + ' ' + this.firstName; }, fullName2: { get() { return this.lastName + ' ' + this.firstName; }, set(newValue) { this.firstName = newValue + this.firstName; } } } }).mount('#app'); </script> </body>
4. 計算屬性的緩存
計算屬性computed是有緩存的,計算屬性會基於它們的依賴關系進行緩存;
在數據不發生變化時,計算屬性是不需要重新計算的;但是如果依賴的數據發生變化,在使用時,計算屬性依然會重新進行計算;
PS. 與method的本質區別:method每次調用都需要重新計算,沒有緩存。
代碼分享:
<body> <div id="app"></div> <template id="myApp"> <!-- 1. 計算屬性調用--> <div>{{getFullName1()}}</div> <div>{{getFullName1()}}</div> <div>{{getFullName1()}}</div> <!-- 2. 方法調用 --> <div>{{getFullName2}}</div> <div>{{getFullName2}}</div> <div>{{getFullName2}}</div> <!-- 3.修改數據內容 --> <input type="text" v-model='firstName' /> </template> <script src="../js/vue3.js"></script> <script> Vue.createApp({ template: '#myApp', data() { return { firstName: 'BBB', lastName: 'AAA' } }, methods: { getFullName1() { console.log('我是方法調用'); return this.lastName + ' ' + this.firstName; } }, computed:{ getFullName2(){ console.log('我是計算屬性調用'); return this.lastName + ' ' + this.firstName; } } }).mount('#app'); </script> </body>
運行結果:
計算屬性只調用了1次,方法調用了三次。
修改數據值,計算屬性再次被調用了1次,方法調用了3次。
5. 擴展get和set的源碼
詳見章節:https://www.cnblogs.com/yaopengfei/p/15251328.html
四. 監聽器
1. 什么是監聽器(偵聽器)?
PS: 可以監聽data和computed中的數據。
2. 普通用法
<body> <div id="app"></div> <template id="myApp"> <h3>{{userInfo1.userName}}</h3> <div><button @click="Edit1">修改對象</button></div> <div><button @click="Edit2">修改userInfo1.userName</button></div> </template> <script src="../js/vue3.js"></script> <script> Vue.createApp({ template: '#myApp', data() { return { userInfo1: { userName: 'test1', age: 20, }, } }, watch: { // 普通監聽 // 默認情況下我們的偵聽器只會針對監聽的數據本身的改變(內部發生的改變是不能偵聽) userInfo1(newValue, oldValue) { console.log(oldValue, newValue); }, }, methods: { Edit1() { this.userInfo1 = { userName: 'test2' }; }, Edit2() { this.userInfo1.userName = 'test2'; } }).mount('#app'); </script> </body>
剖析:
Edit1方法中直接修改了對象,則普通用法中能監聽到,但像Edit2中的修改對象中的內容,是監聽不到的!!!
3. 深度監聽 和 立即執行
(1). 深度監聽
采用另一種寫法,並且需要配置 deep: true ,就可以監聽到對象內任何一個屬性的修改了。
<body> <div id="app"></div> <template id="myApp"> <h3>{{userInfo2.userName}}</h3> <div><button @click="Edit3">修改對象</button></div> <div><button @click="Edit4">修改userInfo2.userName</button></div> <div><button @click="Edit5">修改userInfo2.childInfo.cName</button></div> </template> <script src="../js/vue3.js"></script> <script> Vue.createApp({ template: '#myApp', data() { return { userInfo2: { userName: 'test1', age: 20, childInfo: { cName: 'ypf' } }, } }, watch: {// 深度監聽 // 內部發生的改變也偵聽到 // 發現一問題:新對象和舊對象中的userName值是相同的,這是因為引用類型賦值的問題,都是指向同一個內存地址(詳見后面的知識補充) userInfo2: { handler(newValue, oldValue) { console.log(oldValue, newValue); }, deep: true }, }, methods: { Edit3() { this.userInfo2 = { userName: 'test2' }; }, Edit4() { this.userInfo2.userName = 'test2'; }, Edit5() { this.userInfo2.childInfo.cName = 'lmr'; } } }).mount('#app'); </script> </body>
剖析:
無論是修改 userInfo2.userName 還是 userInfo2.childInfo.cName ,都可以監聽到。
發現一問題:
新對象和舊對象中的userName值是相同的,這是因為引用類型賦值的問題,都是指向同一個內存地址(詳見后面的知識補充)
(2). 立即執行
通過設置參數immediate: true,即不發生變化前,默認執行一次。
4. 其它寫法
(1). 直接監聽對象中某個屬性值
watch: {
// 特殊的監聽方式
// 直接監聽userName的值
'userInfo2.userName'(newValue, oldValue) {
console.log(oldValue, newValue);
}
},
(2). 在created生命周期中進行監聽
!
- 作 者 : Yaopengfei(姚鵬飛)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 聲 明1 : 如有錯誤,歡迎討論,請勿謾罵^_^。
- 聲 明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。