回顧
今天來晚辣,給公司做了一個小項目,一個瀑布流+動態視頻控制的DEMO,有需要的可以聯系我,公司的項目就不對外展示了(一個后端程序員真的要干前端了哈哈哈)。
書接上文,昨天正式的開始了Vue的代碼的學習,簡單的通過一些假的數據來展示了下個人博客的首頁列表,不知道大家是否還記得昨天講的什么,如果不太清楚呢,可以再回顧下《從壹開始前后端分離 [ Vue2.0+.NET Core2.1] 十七 ║Vue基礎:使用Vue.js 來畫博客首頁(一)》,我們主要說到了,Vue的核心語法是什么,MVVM體現在哪些方面,如何簡單安裝Vue環境(通過直接引用Vue.js文件的形式),以及常用的十大指令的前五個,並且通過講解,咱們做了一個小DEMO,就是一個個人的博客系統的首頁(這里是盜取網友的一個樣式,因為我看着着實比較喜歡哈哈)。其實主要記住一點,用Vue這類MVVM框架開發,一定要擺脫之前的DOM操作的習慣,改成操作數據來控制View,如果你Vue這一塊會的話,那學習微信小程序開發就是分分鍾的事兒,嗯~~~
關於后邊的實戰環節,我還沒有確定要用什么樣式的博客,如果大家看到有好的,可以留言下,咱們以它為基礎可以擴展,如果不行的話,我就自己寫一個簡單的吧,當然還是那句話,我只是一個拋磚引玉的作用,也給看到這篇文章的小伙伴們一丟丟的動力,這個時候要說下QQ群里的小伙伴,都已經開始用Vue,配合着前邊的教程和自己的.Net Core項目進行開發頁面了,我感覺也是很開心的!至少可以在平時的時間,一起學點兒東西也是不錯的。雖然不能手把手吧,但是一些建議還是盡量給提問題的小伙伴的。哈哈,{{ 強硬收回話題 }},今天我們接着上一篇的內容,繼續往下走,主要是:把 基本指令 介紹完,說下計算屬性和偵聽器,Class 與 Style 綁定,主要是這三部分,在博客頁面上設計 添加文章,刪除文章,篩選文章等功能。
零、今天完成左下角淺藍色的部分
一、VUE 常用的一些指令總結 ( 下 )
1、v-once 指令 —— 禁止修改
看名字就可以知道,這個是 一次 的意思,也就是說在第一次渲染以后,后期的無論數據的如何修改都不會影響該節點,只渲染元素和組件一次。隨后的重新渲染,元素/組件及其所有的子節點將被視為靜態內容並跳過。這可以用於優化更新性能。
注意:但是,我想說的是,這個指令一般情況不要使用,除非是含有大量的靜態數據,不想每次加載的時候占用時間,如果過多的使用該指令會出現很多意想不到的問題,因為數據的不刷新,不適合剛入門的小伙伴使用。
2、v-bind ( : )指令 —— 動態屬性
在昨天的博客首頁的聯系中,我們其實已經用到了這個指令,大家應該沒有注意到,就是文章列表陪着 href 屬性的時候。
v-bind
指令的作用和用法,它用於動態綁定DOM元素的屬性,比較常見的比如:<a>標簽的href屬性,<img>標簽的src屬性。
<ul class="post-list non-style-list"> <li v-for='item in list' class="post-list-item"> <!--這里用到了 v-bind 指令--> <a v-bind:href="'https://www.cnblogs.com/laozhang-is-phi/p/'+ item.id +'.html'">{{item.name}}</a> <!--還可以這樣寫 這里的linkUrl 是一個變量--> <a :href="linkUrl">{{item.name}}</a> <span class="post-list-date">({{item.date}})</span> </li> </ul>
還可以:動態地綁定一個或多個特性,或一個組件 prop 到表達式(這里要記得,是動態的綁定,就是指在特性中存在變量)。
<!-- 綁定一個有屬性的對象 --> <div v-bind="{ id: someProp, 'other-attr': otherProp }"></div> <!-- 通過 prop 修飾符綁定 DOM 屬性 --> <div v-bind:text-content.prop="text"></div>
3、v-on ( @ )指令——事件觸發
綁定事件監聽器。事件類型由參數指定。表達式可以是一個方法的名字或一個內聯語句,如果沒有修飾符也可以省略。
用在普通元素上時,只能監聽原生 DOM 事件。用在自定義元素組件上時,也可以監聽子組件觸發的自定義事件。相當於綁定事件的監聽器,綁定的事件觸發了,可以指定事件的處理函數。
我們可以簡單說個栗子,在我們的博客首頁的頭像上,增加一個點擊事件(就是之前的click事件),
// 注意這個alert是我自己寫的方法,讀者可以自行看文末我的在GitHub上的demo
<div v-on:click="alert('我是老張的哲學的頭像')"> </div>
//注意 v-on: 可以用@代替,比如
//<div @click="alert('我是老張的哲學的頭像')"> </div>
在我們的頁面里,我們可以用來觸發:添加、篩選功能
a、新建一個 input 標簽,添加一個 回車 事件
<input @keydown.enter="addArticle" type="text" class="edit" placeholder="按回車添加文章">
b、在 vue 實例的 methods 中,統一添加我們的 addArticle 方法。
//我們的方法都統一寫到這里 methods: { //添加事件 addArticle: function () { //將文章存入list數組,注意 this指向! //將數據反轉 this.list = this.list.reverse(); this.list.push(this.task); this.list = this.list.reverse(); //存入list[]后,重置task this.task = { name: '',//內容為空 id: 1000, date: " Just Now ", finished: false,//未完成 deleted: false//未刪除 } } },
c、這個時候,差最后一步,就是獲取 input 的指(這個時候可千萬不要再像以前那樣,根據id來獲取結果了)
還記得咱們前幾章將基本語法和Vue的核心功能的時候,說到了其中的一個很大的特性就是數據驅動 —— 雙向數據綁定,不僅我們可以給 Data 賦值,還可以通過在 DOM 操作的時候,將指獲取到 Data,沒錯就是下邊的這個指令,v-model。
此外,還有其他的一些用到的指令
4、v-model 指令 —— 雙向數據綁定
這是一個我認為很重要,也是經常使用到的指令,主要是表單操作,它可以很容易的實現表單控件和數據的雙向綁定,相對以前的手動更新DOM,這個上邊也說到了。
在之前的 input 輸入框中,添加 v-model 指令
<input @keydown.enter="addArticle" type="text" class="edit" v-model="task.name" placeholder="按回車添加文章">
這個時候,我們的博客添加的功能就好了(當然現在是最低端最low的,只是為了講解 v-model 指令用,博客添加到時候會用 express 后台管理)。
好啦,常用的 vue 指令已經講解完成,還有其他的一些不常用的幾個大家可以用到的時候了解下。
二、計算屬性 Computed
1、計算屬性的原理
在模板內使用表達式很便利,但是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。例如:
<div id="example"> {{ message.split('').reverse().join('') }} </div>
在這個地方,模板不再是簡單的聲明式邏輯。你必須看一段時間才能意識到,這里是想要顯示變量 message
的翻轉字符串。當你想要在模板中多次引用此處的翻轉字符串時,就會更加難以處理,然后如果大量的使用這樣的表達式,會使得整個頁面不僅不好看,還很繁重。
所以,對於任何復雜邏輯,你都應當使用計算屬性。
就比如上邊的栗子,我們就可以寫成這樣:
<div id="example"> //1、這里是我們在 computed中定義的值,而不是在data中 <p>message: "{{ reversedMessage }}"</p> </div> var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // 計算屬性的 getter reversedMessage: function () { // 注意 !`this` 指向 vm 實例 return this.message.split('').reverse().join('') } } })
這樣看起來就清晰明了,減輕頁面的負重。這里你可能會好奇,這就像一個data的中間件一樣,不用做任何的其他操作,都可以實現這個邏輯,就好像data的影子一樣,沒錯!計算屬性就是一個getter器。
你可以像綁定普通屬性一樣在模板中綁定計算屬性。Vue 知道 vm.reversedMessage
依賴於 vm.message
,因此當 vm.message
發生改變時,所有依賴 vm.reversedMessage
的綁定也會更新。而且最妙的是我們已經以聲明的方式創建了這種依賴關系:計算屬性的 getter 函數是沒有副作用 (side effect) 的,這使它更易於測試和理解。
2、知道了他的原理和如何使用,那么我們就可以在我們的項目中使用 計算屬性 來達到我們的動態查詢文章的功能
我們首先添加一個計算屬性來過濾我們的文章list數據
//通過計算屬性過濾數據 computed: { listSearch: function () { //為什么要存這個this呢,因為filter過濾器會改變this的指向 let that = this; return this.list.filter(function (item) { //簡單的 判斷文章name是否包含 input中的值,因為雙向綁定,所以也就是 task.name return item.name.indexOf(that.$data.task.name) >= 0; }); } }
接下來,我們就需要把我們的計算屬性 listSearch 替換掉view中的 list,從而達到過濾:
<li v-for='item in listSearch' class="post-list-item"> <span class="post-list-date">({{item.date}})</span> </li>
最后我們可以看看效果:
注意:計算屬性默認只有 getter ,不過在需要時你也可以提供一個 setter :
computed: { fullName: { // getter get: function () { return this.firstName + ' ' + this.lastName }, // setter set: function (newValue) { var names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1] } } }
現在再運行 vm.fullName = '老張 哲學'
時,setter 會被調用,vm.firstName
和 vm.lastName
也會相應地被更新。
三、偵聽器 (不建議多使用)
雖然計算屬性在大多數情況下更合適,但有時也需要一個自定義的偵聽器。這就是為什么 Vue 通過 watch
選項提供了一個更通用的方法,來響應數據的變化。當需要在數據變化時執行異步或開銷較大的操作時,這個方式是最有用的(這個要強調,是異步操作,或者開銷較大的操作)。
在這里,我們監聽下我們的 input 輸入的數據變化,也就是 task.name 的值
一般的寫法是這樣的:(這是監聽單一屬性)
new Vue({ data: { author: "老張的哲學", task: { name: '',//內容為空 id: 100, date: " Just Now ", finished: false,//未完成 deleted: false//未刪除 }, }, watch: { author: function (newval, oldVal) { console.log("author 變化辣,") } } })
注意:vm.author 和 vm._data.author 是一樣的。
但是在我們的栗子中,是監聽一個對象的中某個屬性,也就是 task.name,
所以我們就會這么寫:
watch: { task.name() { //這里面可以執行一旦監聽的值發生變化你想做的操作 } },
但是,這樣寫是不符合規則的,必須是一個變量,因此會報錯:
1、這里提供兩個方法:第一個深度監聽,第二個配合計算屬性監聽
首先先說下深度監聽:
如果我們要監聽 task 對象屬性變化的話——比如:應用場景是,如果我們是異步獲取數據的,這個時候就可以監聽是否獲取到了值。可以在一般方法上,直接加上 deep:true
vm=new Vue({ data: { author: "老張的哲學", task: { name: '',//內容為空 id: 100, date: " Just Now ", finished: false,//未完成 deleted: false//未刪除 }, }, watch: { author: function (newval, oldVal) { console.log(`author 變化辣,從 ${oldVal} 變成了 ${newval} `) }, task:{ handler:(Value) =>{ console.log(`task被修改了${Value.name}`); }, deep:true //表示監視對象的屬性變化 } } })
注意:vm.task.name 和 vm._data.task.name 是一樣的。
2、通過計算屬性監聽
所以我們就需要還是用到 計算屬性來定義,還記得計算屬性是干什么的么,它就像一個數據的中間件,把原始數據再封裝一下,
那正好,我們可以把 task.name 給封裝下,最終會是這樣的:
vm=new Vue({ data: { author: "老張的哲學", task: { name: '',//內容為空 id: 100, date: " Just Now ", finished: false,//未完成 deleted: false//未刪除 }, }, watch: { author: function (newval, oldVal) { console.log("author 變化辣,") }, nameCpt: function (newval, oldVal) { console.log("task.name 變化辣,") }, }, //通過計算屬性來操作我們需要用到的任何數據 computed: { nameCpt() { return this.task.name } } })
3、當然watch 也可以寫在全局的
vm.$watch('author',function(newValue,oldValue){ console.log('author被修改了,'newValue,oldValue) })
注意:雖然Vue 提供了一種更通用的方式來觀察和響應 Vue 實例上的數據變動:偵聽屬性。但是
監聽是特別浪費資源的,當我們有一些數據需要隨着其它數據變動而變動時,我們很容易濫用 watch,
因此通常更好的做法是使用計算屬性而不是命令式的 watch
回調。
四、匆匆結語
今天時間晚了些,動態Class 與 Style 綁定沒有說到,那我們就下次再說吧!今天呢,我們主要說了常用的指令,主要的是 v-model、v-bind、v-on三個指令,然后還說了計算屬性和偵聽器,我在開發的過程中,計算屬性是使用較多的,但是某些時候,watch 偵聽器會發揮不一樣的作用!好啦,下次咱們繼續說說 動態Class 與 Style 綁定 和 很重要的 生命周期講解 吧。