- 建立前/後:在
beforeCreated
階段, 實例的掛載元素$el
和數據對象data
以及事件還未初始化。- 在
created
階段,Vue
實例的數據對象data
以及方法的運算有了,$el
尚未。- 載入前/後:在
beforeMount
階段,render
函數首次被調用,Vue
實例的$el
和data
都初始化了,但仍是掛載在虛擬的DOM
節點上。- 在
mounted
階段,Vue
實例掛載到實際的DOM
操做完成,通常在該過程進行Ajax
交互。 更新前/後:在數據更新以前調用,即發生在虛擬DOM
從新渲染和打補丁以前,調用beforeUpdate
。- 在虛擬
DOM
從新渲染和打補丁以後,會觸發updated
方法。- 銷燬前/後:在執行實例銷燬以前調用
beforeDestory
,此時實例仍然能夠調用。- 在執行
destroy
方法後,對data
的改變不會再觸發周期函數,說明此時Vue
實例已經解除了事件監聽以及和DOM
的綁定,可是DOM
結構依然存在。
首先建立一個vue
實例,Vue()
;html
在建立Vue
實例的時候,執行了init()
,在init
過程當中首先調用了beforeCreate
。前端
Created
以前,對data
內的數據進行了數據監聽,而且初始化了Vue
內部事件。具體以下:vue
完成了數據觀測;node
完成了屬性和方法的運算;jquery
完成了watch/event
事件的回調;ios
可是此時還未掛載dom
上,$el
屬性是不可見的;git
beforeMount
以前,完成了模板的編譯。把data
對象裏面的數據和vue的語法寫的模板編譯成了html
,可是此時尚未將編譯出來的html
渲染到頁面;github
template
屬性的時候,直接用內部的,而後調用render
函數去渲染。template
,就調用外部的html(「el」option(選項))
。實例內部的template
屬性比外部的優先級高。 render
函數 > template
屬性 > 外部html
;Mounted
以前執行了render
函數,將渲染出來的內容掛載到了DOM
節點上。mounted
是將html
掛載到頁面完成後觸發的鉤子函數;當mounted
執行完畢,整個實例算是走完了流程;在整個實例過程當中,mounted
僅執行一次;面試
beforeUpdate
:數據發生變化時,會調用beforeUpdate
,而後經歷virtual DOM
,最後updated
更新完成;ajax
beforeDestory
是實例銷燬前鉤子函數,銷燬了全部觀察者,子組件以及事件監聽;
destoryed
實例銷燬執行的鉤子函數;
若是有子組件的話,那麼調用順序爲:
父beforeCreate
-> 父created
-> 父beforeMount
-> 子beforeCreate
-> 子created
-> 子beforeMount
-> 子mounted
-> 父mounted
Vue
生命週期?Vue
實例從建立到銷燬的過程,就是生命週期。從開始建立、初始化數據、編譯模板、掛載 DOM
-> 渲染、更新 -> 渲染、銷燬等一系列過程,稱之爲 Vue
的生命週期。
Vue
哪幾個鉤子?會觸發 4 個生命鉤子:建立前/建立後、掛載前/掛載後
複製代碼
DOM
渲染在哪一個週期就已經完成?在 beforeMounted
時它執行了 render
函數,對$el
和 data
進行了初始化,但此時仍是掛載到虛擬的DOM
節點,而後它在 mounted
時就完成了 DOM
渲染,這時候咱們通常還進行 Ajax
交互。
Vue
的渲染過程vue
模板的本質是字符串,利用各類正則,把模板中的屬性去變成 js 中的變量,vif
,vshow
,vfor
等指令變成 js 中的邏輯render
函數render
函數執行返回 vNode
vNode
的 path
方法把 vNode
渲染成真實 DOM
Vue
的整個實現流程render
函數,把模板中的屬性去變成 js 中的變量,vif
,vshow
,vfor
等指令變成 js 中的邏輯render
函數,在初次渲染執行render
函數的過程當中 綁定屬性監聽,收集依賴,最終獲得 vNode
,利用 vNode
的 Path
方法,把 vNode
渲染成真實的 DOM
render
函數,不過這個時候就不須要綁定屬性和收集依賴了,最終生成新的vNode
vNode
和 舊的 vNode
去作對比,找出真正須要更新的 DOM
,渲染Vue
的響應式原理Vue 內部使用了 Object.defineProperty()
來實現數據響應式,經過這個函數能夠監聽到set
和 get
的事件。
1)首先利用 Object.defineProperty()
給 data
中的屬性去設置 set
, get
事件 遞歸的去把 data
中的每個屬性註冊爲被觀察者
2)解析模板時,在屬性的 get
事件中去收集觀察者依賴
3)當屬性的值發生改變時,在 set
事件中去通知每個觀察者,作到所有更新
vue vue-router
路由 vuex axios
1)父傳子
過程
2)子傳父
本質上是父組件使用子組件的數據
this.$emit('自定義事件名',this.qqq)
傳遞子組件的數據import Vue from 'vue'
const component = {
props: ['value1'],
template: `
<div>
<input type="text" @input="handleInput" :value="value1">
</div>
`,
data () {
return {
}
},
methods: {
handleInput (e) {
this.$emit('input', e.target.value)
}
}
}
new Vue({
components: {
CompOne: component
},
el: '#root',
template: `
<div>
<comp-one :value1="value" @input="value = arguments[0]"></comp-one>
</div>
`,
data () {
return {
value: '123'
}
}
})
複製代碼
3)非父子組件間的數據傳遞
兄弟組件傳值eventBus
,就是建立一個事件中心,至關於中轉站,能夠用它來傳遞事件和接收事件。
4)假設在工做中,有三個 .vue 文件:A.vue、B.vue、C.vue。A.vue 是主頁面,B.vue 和 C.vue 相似於頭部導航條和底部導航欄。如今,B.vue 點擊會切換路由,C.vue 須要獲取 B.vue 傳遞的信息。
A.vue
<template>
<div>
<top-nav></top-nav>
<div class="container">
<router-view></router-view>
</div>
<bottom-nav></bottom-nav>
</div>
</template>
複製代碼
bus.js
import Vue from 'vue';
// 使用 Event Bus
const bus = new Vue();
export default bus;
複製代碼
B.vue
<template>
<div class="bottom-nav">
<div class="nav-one" @click="goToPage({path: '/HomeIndex', meta:'首頁'})">
<i class="icon-home"></i>
<span>首頁</span>
</div>
</div>
</template>
<script>
import bus from '../utils/bus'
export default {
methods: {
goToPage(route) {
this.$router.push(route.path);
bus.$emit('meta', route.meta);
}
}
}
</script>
複製代碼
C.vue
<template>
<div class="top-nav">
<span class="title">{{title}}</span>
</div>
</template>
<script>
import bus from '../utils/bus'
export default {
data() {
return {
title: ''
}
},
created() {
bus.$on('meta', msg=> {
this.title = msg;
})
}
}
</script>
複製代碼
EventEmitter
方法EventEmitter
方法主要包含了 on
,emit
,once
,off
方法。
class Event {
constructor() {
this.events = Object.create(null);
}
on(name, fn) {
if (!this.events[name]) {
this.events[name] = []
}
this.events[name].push(fn);
return this;
}
emit(name, ...args) {
if (!this.events[name]) {
return this;
}
const fns = this.events[name]
fns.forEach(fn => fn.call(this, ...args))
return this;
}
off(name,fn) {
if (!this.events[name]) {
return this;
}
if (!fn) {
this.events[name] = null
return this
}
const index = this.events[name].indexOf(fn);
this.events[name].splice(index, 1);
return this;
}
once(name,fn) {
const only = () => {
fn.apply(this, arguments);
this.off(name, only);
};
this.on(name, only);
return this;
}
}
複製代碼
Vue
採用 數據劫持 結合 發佈者-訂閱者 模式的方式,經過 Object.defineProperty()
來劫持各個屬性的 setter
以及getter
,在數據變更時發佈消息給訂閱者,觸發相應的監聽回調。
第一步:須要 Observe
的數據對象進行遞歸遍歷,包括子屬性對象的屬性,都加上 setter
和 getter
。這樣的話,給這個對象的某個值賦值,就會觸發setter
,那麼就能監聽到了數據變化。
第二步:Compile
解析模板指令,將模板中的變量替換成數據,而後初始化渲染頁面視圖,並將每一個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦數據有變更,收到通知,更新數據。
第三步:Watcher
訂閱者是Observer
和 Compile
之間通訊的橋樑,主要作的事情有:
屬性訂閱器(dep)
裏面添加本身。update()
方法dep.notice()
通知時,能調用自身的update()
方法,並觸發 Compile
中綁定的回調,則功成身退。第四步:MVVM
做爲數據綁定的入口,整合 Observer
、Compile
和 Watcher
三者,經過 Observer
來監聽本身的 model
數據變化,經過 Compile
來解析編譯模板指令,最終利用 Watcher
搭起 Observer
和 Compile
之間的橋樑,達到數據變化 -> 視圖更新;視圖交互變化(input) -> 數據 model 變動的雙向綁定效果。
key
值的做用使用 v-for
更新已渲染的元素列表時,默認用就地複用策略。
列表數據修改的時候,他會根據key值去判斷某個值是否修改:若是修改,則從新渲染這一項;不然複用以前的dom,僅修改value
值。
當數據發生改變時,set
方法會讓調用Dep.notify
通知全部訂閱者Watcher
,訂閱者就會調用patch
給真實的DOM
打補丁,更新相應的視圖。
diff流程
patch
函數接收兩個參數oldVnode
和Vnode
分別表明新的節點和以前的舊節點
patchVnode
;Vnode
替換oldVnode
;patchVnode
:當咱們肯定兩個節點值得比較以後咱們會對兩個節點指定patchVnode
方法;
Vnode
和oldVnode
是否指向同一個對象,若是是,那麼直接return
;updateChildren
函數比較子節點,這一步很重要;updateChildren函數圖解
如今分別對oldS、oldE、S、E兩兩作sameVnode比較,有四種比較方式,當其中兩個能匹配上那麼真實dom中的相應節點會移到Vnode相應的位置,這句話有點繞,打個比方:
能夠分紅三部分
答案:
compile
編譯器把template
編譯成AST
語法樹(abstract syntax tree 即 源代碼的抽象語法結構的樹狀表現形式),compile
是createCompiler
的返回值,createCompiler
是用以- 建立編譯器的。另外compile
還負責合併option
。AST
會通過generate
(將AST語法樹轉化成render funtion字符串的過程)獲得render
函數,render的返回值是VNode
,VNode是Vue的虛擬DOM節點,裏面有(標籤名、子節點、文本等等);computed
是計算一個新的屬性,並將該屬性掛載到 vm(Vue 實例)上,而 watch 是監聽已經存在且已掛載到 vm 上的數據,因此用 watch
一樣能夠監聽 computed 計算屬性的變化(其它還有 data、props)
computed
本質是一個惰性求值的觀察者,具備緩存性,只有當依賴變化後,第一次訪問 computed 屬性,纔會計算新的值,而watch
則是當數據發生變化便會調用執行函數 從使用場景上說,computed 適用一個數據被多個數據影響,而 watch 適用一個數據影響多個數據;
vuex
就像一個全局的倉庫,公共的狀態或者複雜組件交互的狀態咱們會抽離出來放進裏面。
vuex的核心主要包括如下幾個部分:
state
:state裏面就是存放的咱們須要使用的狀態,他是單向數據流,在 vue 中不容許直接對他進行修改,而是使用 mutations 去進行修改mutations
: mutations 就是存放如何更改狀態的一些方法actions
: actions 是來作異步修改的,他能夠等待異步結束後,再去使用 commit mutations 去修改狀態getters
: 至關因而 state 的計算屬性使用:
computed
中使用 this.$store.state
獲得想要的狀態this.$store.commit
方法去修改狀態mapState,mapMutations
輔助函數指令都是行內屬性
`v-model`放在input、textarea、select>option上的,實現雙向數據綁定
`v-text` 展現對應的文本
`v-once` 對應的標籤只渲染一次
`v-show=布爾` 是否能顯示,true能顯示,false不能顯示(存在隱式轉化)
`v-html` 把值中的標籤渲染出來
複製代碼
v-for
循環顯示元素
能夠循環數組、對象、數字、字符串
最好加:key='a+i'
v-for='item in ary'
複製代碼
v-bind
用於綁定行內屬性
簡寫成:
複製代碼
v-if
控制是否渲染該元素
值是true,則渲染該元素;false則不渲染
與v-else v-else-if連着使用
可使用template標籤,就不會出現多餘標籤
複製代碼
基本用法
步驟
- 一、聲明組件
- 二、編寫路由映射表
- 三、把編輯好的映射表注入到
router
實例中- 四、把
router
實例注入到根實例中router-link
控制跳轉的連接和顯示的文字router-view
控制顯示的組件內容active-class
控制選中對應路徑的類名tag
控制渲染成什麼標籤
<body>
<div id="app">
<router-link to='/home' active-class='current'>首頁</router-link>
<router-link to='/list' tag='div'>列表</router-link>
<router-view></router-view>
</div>
</body>
</html>
<template id="home">
<div>home</div>
</template>
<template id="list">
<div>list</div>
</template>
<script src="../node/node_modules/vue/dist/vue.js"></script>
<script src="../node_modules/vue-router/dist/vue-router.js"></script>
<script>
let home = {
template: '#home',
}
let list = {
template: '#list',
}
//路由映射表
let routes = [{
path: '/home',
component: home
},
{
path: '/list',
component: list
}
]
let router=new VueRouter({
routes:routes,
})
let vm = new Vue({
el: '#app',
data: {
name: "liu"
},
router,
})
</script>
複製代碼
傳參
提供了兩種傳參方式
- 一、
query
傳參(問號傳參) 路由映射表不用改動 :to={path:'',query:{}}或者:to={name:'',query:{}}
- 二、
params
傳參(路徑傳參) 在映射表中添加 /:變量 的形式; :to={name:'',params:{變量:''}}}
<router-link :to='{path:"/list",query:{id:123,e:name}}' tag='div'>
列表</router-link>
重定向redirect
let routes = [
{
path:'/',
redirect:'/son2/222'
},
{
path:'/son1',
// redirect:'/son2/5555',
name:'son1',
component:son1,
redirect:'/son1/sz',
children:[
{
path:'/son1/sz',
component:sz
}
]
},
{
path:'/son2/:bl1234',
name:'son2',
component:son2
},
{
path:'/*',
redirect:'/son1'
}
]
複製代碼
推薦文章 前端面試題—vue部分詳解
hash模式:在瀏覽器中符號「#」,#以及#後面的字符稱之爲hash,用
window.location.hash
讀取; 特色:hash
雖然在URL
中,但不被包括在HTTP
請求中;用來指導瀏覽器動做,對服務端安全無用,hash
不會重加載頁面。
hash 模式下,僅 hash 符號以前的內容會被包含在請求中,如
http://www.xxx.com
,所以對於後端來講,即便沒有作到對路由的全覆蓋,也不會返回 404 錯誤。
history模式:
history
採用HTML5
的新特性;且提供了兩個新方法:pushState()
,replaceState()
能夠對瀏覽器歷史記錄棧進行修改,以及popState
事件的監聽到狀態變動。
history 模式下,前端的
URL
必須和實際向後端發起請求的URL
一致,如http://www.xxx.com/items/id
。後端若是缺乏對/items/id
的路由處理,將返回 404 錯誤。
vue
組件的過程?1)首先,組件能夠提高整個項目的開發效率。可以把頁面抽象成多個相對獨立的模塊,解決了咱們傳統項目開發:效率低、難維護、複用性等問題。
2)使用Vue.extend
方法建立一個組件,而後使用Vue.component
方法註冊組件。子組件須要數據,能夠在props
中接受定義。而子組件修改好數據後,想把數據傳遞給父組件。能夠採用emit
方法。
v-if
和v-show
的共同點和區別(考察頻率:中)參考官方文檔
v-if
是「真正」的條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建。v-if
也是惰性的:若是在初始渲染時條件爲假,則什麼也不作——直到條件第一次變爲真時,纔會開始渲染條件塊。v-show
就簡單得多——無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於 CSS 進行切換。v-if
有更高的切換開銷,而v-show
有更高的初始渲染開銷。所以,若是須要很是頻繁地切換,則使用 v-show
較好;若是在運行時條件不多改變,則使用 v-if
較好。Vue 在 render
中 createElement
的時候,並非產生真實的 DOM 元素,實際上 createElement
描述爲 createNodeDescription
,由於它所包含的信息會告訴 Vue 頁面上須要渲染什麼樣的節點。 所以,咱們將這樣的節點描述爲 「虛擬節點」(Virtual Node),簡稱 VNode。「虛擬 DOM」 是咱們對由 Vue 組件樹創建的整個 VNode 樹的稱呼。
推薦:
一、體積小:
vue-resource
很是小巧,在壓縮之後只有大約12KB,服務端啓用gzip壓縮後只有4.5KB大小,這遠比jQuery
的體積要小得多。
二、支持主流瀏覽器:和
Vue.js
同樣,vue-resource
除了不支持IE 9如下的瀏覽器,其餘主流的瀏覽器都支持
三、支持
Promise API
和URI
Templates:Promise
是ES6
的特性,Promise
的中文含義爲「先知」,Promise
對象用於異步計算。URI Templates
表示URI
模板,有些相似於ASP.NET MVC
的路由模板
四、支持攔截器:攔截器是全局的,攔截器能夠在請求發送前和發送請求後作一些處理。 攔截器在一些場景下會很是有用,好比請求發送前在
headers
中設置access_token
,或者在請求失敗時,提供共通的處理方式。
1).基於全局Vue對象
使用http
Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback);
Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
複製代碼
2).在一個Vue實例
內使用$http
this.$http.get('/someUrl', [options]).then(successCallback, errorCallback);
this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
複製代碼
選項options
url
:發送請求的URL
body
:做爲請求主體發送的數據
headers
:標題對象做爲HTTP請求表頭發送
params
:做爲url參數發送的參數對象
$http
方式數據請求
- get
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://cdn.jsdelivr.net/vue.resource/1.2.1/vue-resource.min.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="sendGet()">發送get請求</button>
</div>
</body>
</html>
<script>
var vm = new Vue({
el: "#app",
methods: {
sendGet: function() {
//這裏的this指代的是 vm對象
var url = "http://127.0.0.1:3000/login?username=admin&password=123";
this.$http.get(url).then(function(res) {
console.log(res.data)
},function(err){
console.log(err)
})
}
}
})
</script>
複製代碼
- post
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://cdn.jsdelivr.net/vue.resource/1.2.1/vue-resource.min.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="sendPost()">發送post請求</button>
</div>
</body>
</html>
<script>
var vm = new Vue({
el: "#app",
methods: {
sendPost: function() {
//這裏的this指代的是 vm對象
var url = "http://127.0.0.1:3000/postLogin";
/**
* vue的post參數:若是是普通的post請求,最後一個就是{emulateJSON:true}
*
* 參數一:url
*
* 參數二:data-要傳遞的數據-對象的形式
*
* 參數三:若是是普通的post請求,最後一個就是{emulateJSON:true}
*
* */
this.$http.post(url, {
username: 'lisi',
password: 'lisi'
}, {
emulateJSON: true
}).then(function(res) {
console.log(res.data)
})
}
}
})
</script>
複製代碼
- jsonp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--引入js-->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://cdn.jsdelivr.net/vue.resource/1.2.1/vue-resource.min.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="sendPost()">發送post請求</button>
</div>
</body>
</html>
<script>
var vm = new Vue({
el: "#app",
methods: {
sendPost: function() {
//這裏的this指代的是 vm對象
var url = "http://127.0.0.1:3000/postLogin";
/**
* vue的post參數:若是是普通的post請求,最後一個就是{emulateJSON:true}
*
* 參數一:url
*
* 參數二:data-要傳遞的數據-對象的形式
*
* 參數三:若是是普通的post請求,最後一個就是{emulateJSON:true}
*
* */
this.$http.post(url, {
username: 'lisi',
password: 'lisi'
}, {
emulateJSON: true
}).then(function(res) {
console.log(res.data)
})
}
}
})
</script>
複製代碼
在Vue中發送AJAX請求:Vue自己並不支持發送ajax請求,須要使用第三方插件vue-resources(1.0,可是2.0中不建議使用)、官方推薦使用axis(2.0);可是也能夠用jQuery;
axios是一個基於promise的http請求客戶端,用來發送請求,也是vue2.0官方推薦使用的;在vue2.0官方推薦的,同時再也不對vue-resource進行更新和維護。
axios具體用來作什麼
從瀏覽器中建立XMLHttpRequests
讓HTTP從node.js的請求
支持Promise API
截取請求和響應
轉換請求和響應數據
取消請求
自動轉換JSON數據
客戶端支持防範XSRF
axios的github地址和使用方式:github.com/axios/axios
axios([options])
axios.get(url[,options])
;
傳參方式:
1.經過`url`傳參
2.經過`params`選項傳參
複製代碼
axios.post(url,data,[options])
;
`axios`默認發送數據時,數據格式是`Request` `Payload`,並不是咱們經常使用的`Form Data`格式,
因此參數必需要以鍵值對形式傳遞,不能以`json`形式傳參
傳參方式:
1.本身拼接爲鍵值對
2.使用`transformRequest`,在請求發送前將請求數據進行轉換
3.若是使用模塊化開發,可使用`qs`模塊進行轉換
複製代碼
axios
自己並不支持發送跨域的請求,沒有提供相應的API,因此只能使用第三方庫
客戶端經過jsonp或者vue-resource支持
若是服務端經過CORS支持跨域,則客戶端不須要處理跨域
vue
,引入jQuery
(由於等下用Ajax請求數據用到jQuery)<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
複製代碼
vue
首先在本身的網頁body
內添加一個div
包括全部內容,並給這個div
設置id
如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
//你的html代碼
</div>
</body>
</html>
複製代碼
vue
並掛載到頁面(若是在單首創建js
文件來寫,則需在htmll中引入這個js文件)建立以下:
window.onload = function() {
new Vue({
el: "#app",//將vue掛載到html中你建立的那個帶id="app"上
data: {
aboutData: [], //建一個空數組,用來保存調用接口獲取的數據
},
created: function() {
this.getRoute();
},
mounted() {
},
methods: {
getRoute: function() {
var that = this;
$.ajax({
type: "GET",
url:
"填寫你的數據接口地址",
dataType: "json",
success: function(response) {
aboutData = response;
//寫在獲取數據成功後你想進行的操做
},
error: function() {
alert("請求失敗");
}
});
}
});
};
複製代碼
html
代碼中調用vue
相關語法來寫進動態數據了微信小程序篇