一、對於MVVM的理解
MVVM 是 Model-View-ViewModel 的縮寫。
- Model代表數據模型,也可以在Model中定義數據修改和操作的業務邏輯。
- View 代表視圖模型,它負責將數據模型轉化成UI 展現出來。View 層不負責處理狀態,View 層做的是 數據綁定的聲明、 指令的聲明、 事件綁定的聲明。
- ViewModel監聽數據的改變和控制視圖行為、處理用戶交互,它就是一個同步View 和 Model的對象,連接Model和View。
在MVVM架構下,View 和 Model 之間並沒有直接的聯系,而是通過ViewModel進行交互,Model 和 View 之間的交互是雙向的, 因此View 數據的變化會同步到Model中,而Model 數據的變化也會立即反應到View 上。
ViewModel通過雙向數據綁定把View層和Model層連接起來,而View和Model之間的同步工作完全是自動的,無需人為干涉,因此開發者只需要關注業務邏輯,不需要手動操作DOM,不需要關注數據狀態的同步問題,復雜的數據狀態維護完全由MVVM來統一管理
MVVM優缺點
- 優點:
1)分離視圖(View)和模型(Model),降低代碼耦合,提高視圖或者邏輯的重用性
2)提高可測試性: ViewModel的存在可以幫助開發者更好地編寫測試代碼
3)自動更新dom: 利用雙向綁定,數據更新后視圖自動更新,讓開發者從繁瑣的dom操作中解放 - 缺點:
1)Bug很難被調試:數據綁定使得一個位置的Bug被快速傳遞到別的位置,要定位原始出問題的地方就變得不那么容易了。另外,數據綁定的聲明是指令式地寫在View的模版當中的,這些內容是沒辦法去打斷點debug的
2)一個大的模塊中model也會很大,雖然使用方便也並保證了數據的一致性,當時長期持有,不釋放內存就造成了花費更多的內存
3)對於大型的圖形應用程序,視圖狀態較多,ViewModel的構建和維護的成本都會比較高
vue對css的操作可以通過綁定class或者綁定style。
二、vue框架與jQuery類庫的區別
-
Vue直接操作視圖層,它通過Vue對象將數據和View完全分離開來了。對數據進行操作不需要引用相應的DOM節點,只需要關注邏輯,完全實現了視圖層和邏輯層的解耦;
-
Jquery的操作是基於DOM節點的操作,jQuery是使用選擇器($)選取DOM對象,對其進行賦值、取值、事件綁定等操作,其實和原生的js的區別只在於可以更方便的選取和操作DOM對象,而數據和界面是在一起的。它的優勢在於良好的封裝和兼容,使調用簡單方便。
三、vue的生命周期
Vue 實例從創建到銷毀的過程,就是生命周期。從開始創建、初始化數據、編譯模板、掛載Dom→渲染、更新→渲染、銷毀等一系列過程,稱之為 Vue 的生命周期。
vue的生命周期中有多個事件鈎子,讓我們在控制整個Vue實例的過程時更容易形成好的邏輯。它可以總共分為8個階段:創建前/后, 載入前/后,更新前/后,銷毀前/銷毀后。
第一次頁面加載會觸發 beforeCreate, created, beforeMount, mounted 這幾個鈎子函數;DOM 渲染在 mounted 中就已經完成了。官方實例的異步請求是在mounted生命周期中調用的,而實際上也可以在created生命周期中調用。
beforeCreate(創建前) :數據觀測和初始化事件還未開始
created(創建后):完成數據觀測,屬性和方法的運算,初始化事件,el屬性還沒有顯示出來。
beforeMount(掛載前) :在掛載開始之前被調用,相關render函數首次被調用。實例完成以下配置:編譯模板,把data里面的數據和模板生成html,但是沒有掛載html到頁面中。
mounted(掛載后):掛載到實例之后被調用,實例完成以下配置:用上面編譯好的html內容替換el屬性指向的DOM對象。完成模板中的html渲染到html頁面中。此過程中進行ajax交互。
beforeUpdate(更新前):在數據更新之前調用,發生在虛擬DOM重新渲染和打補丁之前。可以在該鈎子中進一步地更改狀態,不會觸發附加的重渲染過程。
updated(更新后):在由於數據更改導致的虛擬DOM重新渲染和打補丁之后調用。調用時,組件DOM已經更新,所以可以執行依賴於DOM的操作。然而在大多數情況下,應該避免在此期間更改狀態,因為這可能會導致更新無限循環。該鈎子在服務器端渲染期間不被調用。
beforeDestroy(銷毀前): 在實例銷毀之前調用。實例仍然完全可用。
destroyed(銷毀后): 在實例銷毀之后調用。調用后,所有的事件監聽器會被移除,所有的子實例也會被銷毀。該鈎子在服務器端渲染期間不被調用。
activited:keep-alive專屬,組件被激活時調用
deactivated:keep-alive專屬,組件被激活時調用
四、Vue實現數據雙向綁定的原理:Object.defineProperty()
vue實現數據雙向綁定主要是:采用數據劫持結合發布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變動時發布消息給訂閱者,觸發相應監聽回調。
要想實現mvvm,主要包含兩個方面,視圖變化更新數據,數據變化更新視圖.
- 1)view變化更新data:可以通過事件監聽實現
- 2)data變化更新view:通過
Object.defineProperty( )對屬性設置一個set函數,當屬性變化時就會觸發這個函數,所以我們只需要將一些更新的方法放在set函數中就可以實現data變化更新view了. - 3)具體過程:
首先要對數據進行劫持監聽,所以要設置一個監聽器Observer,用來監聽所有的屬性,當屬性變化時,就通知訂閱者Watcher,看是否需要更新。屬性可能是多個,所以會有多個訂閱者,故需要一個消息訂閱器Dep來專門收集這些訂閱者,並在監聽器Observer和訂閱者Watcher之間進行統一的管理。
因為在節點元素上可能存在一些指令,所以還需要一個指令解析器Compile,對每個節點元素進行掃描和解析,將相關指令初始化成一個訂閱者Watcher,並替換模板數據並綁定相應的函數,這時候當訂閱者Watcher接受到相應屬性的變化,就會執行相對應的更新函數,從而更新視圖.
總結:
1.實現一個監聽器Observer,用來劫持並監聽所有屬性,如果有變動的,就通知訂閱者。
2.實現一個訂閱者Watcher,可以收到屬性的變化通知並執行相應的函數,從而更新視圖。
3.實現一個解析器Compile,可以掃描和解析每個節點的相關指令,並根據初始化模板數據以及初始化相應的訂閱器。
詳情請讀:
https://www.jianshu.com/p/0c0a4513d2a6
五、vue-cli是什么?
Vue.js提供一個官方命令行工具,可用於快速搭建大型單頁應用(在一個完成的應用或者站點中,只有一個完整的HTML頁面,這個頁面有一個容器,可以把需要加載的代碼(以組件的方式)插入到該容器中)。
該工具提供開箱即用的構建工具配置,帶來現代化的前端開發流程。只需幾分鍾即可創建並啟動一個帶熱重載、保存時靜態檢查以及可用於生產環境的構建配置的項目。

assets文件夾是放靜態資源;components是放組件;router是定義路由相關的配置;view視圖;app.vue是一個應用主組件;main.js是入口文件等等
六、Vue組件如何通信
props/$emit+v-on: 通過props將數據自上而下傳遞,而通過$emit和v-on來向上傳遞信息。- 中央事件總線
EventBus: 通過EventBus進行信息的發布與訂閱,實現非父子組件之間的通信 - vuex: 是全局數據管理庫,可以通過vuex管理全局的數據流
v-model方式:直接綁定父組件變量,把數據從子組件傳回父組件
七、vuex是什么?
Vuex 類似 Redux 的狀態管理器,用來管理Vue的所有組件狀態。
八、vue組件中的data為什么是一個函數?
組件是可復用的vue實例,一個組件被創建好之后,就可能被用在各個地方,而組件不管被復用了多少次,組件中的data數據都應該是相互隔離,互不影響的,基於這一理念,組件每復用一次,data數據就應該被復制一次,之后,當某一處復用的地方組件內data數據被改變時,其他復用地方組件的data數據不受影響。
類似於給每個組件實例創建一個私有的數據空間,讓各個組件實例維護各自的數據。而單純的寫成對象形式,就使得所有組件實例共用了一份data,就會造成一個變了全都會變的結果。
九、computed和watch有什么區別?
- computed:
1、computed是計算屬性,也就是計算值
2、computed具有緩存性,computed的值在getter執行后是會緩存的,只有在它依賴的屬性值改變之后,下一次獲取computed的值時才會重新調用對應的getter來計算
3、computed適用於計算比較消耗性能的計算場景
data: {
message: 'Hello'
},
computed: {
// 計算屬性的 getter
reversedMessage: function () {
// `this` 指向 vm 實例
return this.message.split('').reverse().join('')
}
}
- ** watch**
1、Vue 提供了一種更通用的方式來觀察和響應 Vue 實例上的數據變動:偵聽屬性。
2、無緩存性,頁面重新渲染時值不變化也會執行
watch: {
// 如果 `question` 發生改變,這個函數就會運行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
