輕量級框架:只關注視圖層,是一個構建數據的視圖集合,大小隻有幾十kb;css
簡單易學:國人開發,中文文檔,不存在語言障礙 ,易於理解和學習;html
雙向數據綁定:保留了angular的特色,在數據操做方面更爲簡單;前端
組件化:保留了react的優勢,實現了html的封裝和重用,在構建單頁面應用方面有着獨特的優點;vue
視圖,數據,結構分離:使數據的更改更爲簡單,不須要進行邏輯代碼的修改,只須要操做數據就能完成相關操做;node
虛擬DOM:dom操做是很是耗費性能的,再也不使用原生的dom操做節點,極大解放dom操做,但具體操做的仍是dom不過是換了另外一種方式;react
運行速度更快:相比較與react而言,一樣是操做虛擬dom,就性能而言,vue存在很大的優點。webpack
總共分爲8個階段建立前/後,載入前/後,更新前/後,銷燬前/後。ios
建立前/後: 在beforeCreate階段,vue實例的掛載元素el和數據對象data都爲undefined,還未初始化。在created階段,vue實例的數據對象data有了,el爲undefined,還未初始化。git
載入前/後:在beforeMount階段,vue實例的$el和data都初始化了,但仍是掛載以前爲虛擬的dom節點,data.message還未替換。在mounted階段,vue實例掛載完成,data.message成功渲染。es6
更新前/後:當data變化時,會觸發beforeUpdate和updated方法
銷燬前/後:在執行destroy方法後,對data的改變不會再觸發周期函數,說明此時vue實例已經解除了事件監聽以及和dom的綁定,可是dom結構依然存在
對象爲引用類型,當複用組件時,因爲數據對象都指向同一個data對象,當在一個組件中修改data時,其餘重用的組件中的data會同時被修改;而使用返回對象的函數,因爲每次返回的都是一個新對象(Object的實例),引用地址不一樣,則不會出現這個問題。
v-if和v-show看起來彷佛差很少,當條件不成立時,其所對應的標籤元素都不可見,可是這兩個選項是有區別的:
一、v-if在條件切換時,會對標籤進行適當的建立和銷燬,而v-show則僅在初始化時加載一次,所以v-if的開銷相對來講會比v-show大。
二、v-if是惰性的,只有當條件爲真時纔會真正渲染標籤;若是初始條件不爲真,則v-if不會去渲染標籤。v-show則不管初始條件是否成立,都會渲染標籤,它僅僅作的只是簡單的CSS切換。
immediate:組件加載當即觸發回調函數執行
watch: {
firstName: { handler(newName, oldName) { this.fullName = newName + ' ' + this.lastName; }, // 表明在wacth裏聲明瞭firstName這個方法以後當即執行handler方法 immediate: true } } 複製代碼
deep: deep的意思就是深刻觀察,監聽器會一層層的往下遍歷,給對象的全部屬性都加上這個監聽器,可是這樣性能開銷就會很是大了,任何修改obj裏面任何一個屬性都會觸發這個監聽器裏的 handler
watch: {
obj: { handler(newName, oldName) { console.log('obj.a changed'); }, immediate: true, deep: true } } 複製代碼
優化:咱們可使用字符串的形式監聽
watch: {
'obj.a': { handler(newName, oldName) { console.log('obj.a changed'); }, immediate: true, // deep: true } } 複製代碼
這樣Vue.js纔會一層一層解析下去,直到遇到屬性a,而後纔給a設置監聽函數。
vue文件的一個加載器,跟template/js/style轉換成js模塊。
vue實現響應式並非數據發生變化後dom當即變化,而是按照必定的策略來進行dom更新。
nextTick 是在下次 DOM 更新循環結束以後執行延遲迴調,在修改數據以後使用nextTick,則能夠在回調中獲取更新後的 DOM
當Vue用 v-for 正在更新已渲染過的元素列表是,它默認用「就地複用」策略。若是數據項的順序被改變,Vue將不是移動DOM元素來匹配數據項的改變,而是簡單複用此處每一個元素,而且確保它在特定索引下顯示已被渲染過的每一個元素。
爲了給Vue一個提示,以便它能跟蹤每一個節點的身份,從而重用和從新排序現有元素,你須要爲每項提供一個惟一 key 屬性。key屬性的類型只能爲 string或者number類型。
key 的特殊屬性主要用在Vue的虛擬DOM算法,在新舊nodes對比時辨識VNodes。若是不使用 key,Vue會使用一種最大限度減小動態元素而且儘量的嘗試修復/再利用相同類型元素的算法。使用key,它會基於key的變化從新排列元素順序,而且會移除 key 不存在的元素。
vue.js 是採用數據劫持結合發佈者-訂閱者模式的方式,經過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變動的雙向綁定效果。
經過props傳遞
父組件: <child value = '傳遞的數據' />
子組件: props['value'],接收數據,接受以後使用和data中定義數據使用方式同樣 複製代碼
在父組件中給子組件綁定一個自定義的事件,子組件經過$emit()觸發該事件並傳值。
父組件: <child @receive = 'receive' />
子組件: this.$emit('receive','傳遞的數據') 複製代碼
A:methods :{ 函數{bus.$emit(‘自定義事件名’,數據)} 發送
B:created (){bus.$on(‘A發送過來的自定義事件名’,函數)} 進行數據接收
咱們在父組件給子組件傳值的時候,能夠指定該props的默認值及類型,當傳遞數據類型不正確的時候,vue會發出警告
props: {
visible: { default: true, type: Boolean, required: true }, }, 複製代碼
首先,組件能夠提高整個項目的開發效率。可以把頁面抽象成多個相對獨立的模塊,解決了咱們傳統項目開發:效率低、難維護、複用性等問題。
而後,使用Vue.extend方法建立一個組件,而後使用Vue.component方法註冊組件。子組件須要數據,能夠在props中接受定義。而子組件修改好數據後,想把數據傳遞給父組件。能夠採用emit方法。
簡而言之,就是先轉化成AST樹,再獲得的render函數返回VNode(Vue的虛擬DOM節點),詳細步驟以下:
首先,經過compile編譯器把template編譯成AST語法樹(abstract syntax tree 即 源代碼的抽象語法結構的樹狀表現形式),compile是createCompiler的返回值,createCompiler是用以建立編譯器的。另外compile還負責合併option。
而後,AST會通過generate(將AST語法樹轉化成render funtion字符串的過程)獲得render函數,render的返回值是VNode,VNode是Vue的虛擬DOM節點,裏面有(標籤名、子節點、文本等等)
css的預編譯,使用步驟以下:
第一步:用npm 下三個loader(sass-loader、css-loader、node-sass)
第二步:在build目錄找到webpack.base.config.js,在那個extends屬性中加一個拓展.scss
第三步:仍是在同一個文件,配置一個module屬性
第四步:而後在組件的style標籤加上lang屬性 ,例如:lang=」scss」
特性主要有:
當在項目中直接設置數組的某一項的值,或者直接設置對象的某個屬性值,這個時候,你會發現頁面並無更新。這是由於Object.defineProperty()限制,監聽不到變化。
解決方式:
this.$set(this.arr, 0, "OBKoro1"); // 改變數組
this.$set(this.obj, "c", "OBKoro1"); // 改變對象 複製代碼
splice()、 push()、pop()、shift()、unshift()、sort()、reverse()
複製代碼
vue源碼裏緩存了array的原型鏈,而後重寫了這幾個方法,觸發這幾個方法的時候會observer數據,意思是使用這些方法不用咱們再進行額外的操做,視圖自動進行更新。 推薦使用splice方法會比較好自定義,由於splice能夠在數組的任何位置進行刪除/添加操做
從 2.3.0 起vue從新引入了.sync修飾符,可是此次它只是做爲一個編譯時的語法糖存在。它會被擴展爲一個自動更新父組件屬性的 v-on 監聽器。示例代碼以下:
<comp :foo.sync="bar"></comp>
複製代碼
會被擴展爲:
<comp :foo="bar" @update:foo="val => bar = val"></comp>
複製代碼
當子組件須要更新 foo 的值時,它須要顯式地觸發一個更新事件:
this.$emit('update:foo', newValue)
複製代碼
先給標籤設置一個ref值,再經過this.$refs.domName獲取,例如:
<div ref="test"></div>
const dom = this.$refs.test 複製代碼
是能夠的,來個例子:
<input type="text" v-on="{ input:onInput,focus:onFocus,blur:onBlur, }">
複製代碼
這兩個都是用來存放項目中所使用的靜態資源文件。
二者的區別:
assets中的文件在運行npm run build的時候會打包,簡單來講就是會被壓縮體積,代碼格式化之類的。打包以後也會放到static中。
static中的文件則不會被打包。
建議:將圖片等未處理的文件放在assets中,打包減小體積。而對於第三方引入的一些資源文件如iconfont.css等能夠放在static中,由於這些文件已經通過處理了。
不少時候,咱們封裝了一個子組件以後,在父組件使用的時候,想添加一些dom元素,這個時候就可使用slot插槽了,可是這些dom是否顯示以及在哪裏顯示,則是看子組件中slot組件的位置了。
使用vue開發時,在vue初始化以前,因爲div是不歸vue管的,因此咱們寫的代碼在尚未解析的狀況下會容易出現花屏現象,看到相似於{{message}}的字樣,雖然通常狀況下這個時間很短暫,可是咱們仍是有必要讓解決這個問題的。
首先:在css里加上如下代碼
[v-cloak] { display: none; } 複製代碼
若是沒有完全解決問題,則在根元素加上style="display: none;" :style="{display: 'block'}"
Vuex 是一個專爲 Vue.js應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。Vuex 也集成到 Vue 的官方調試工具 devtools extension,提供了諸如零配置的 time-travel 調試、狀態快照導入導出等高級調試功能。
第一步安裝
npm install vuex -S
複製代碼
第二步建立store
import Vue from 'vue';
import Vuex from 'vuex'; Vue.use(Vuex); //不是在生產環境debug爲true const debug = process.env.NODE_ENV !== 'production'; //建立Vuex實例對象 const store = new Vuex.Store({ strict:debug,//在不是生產環境下都開啓嚴格模式 state:{ }, getters:{ }, mutations:{ }, actions:{ } }) export default store; 複製代碼
第三步注入vuex
import Vue from 'vue';
import App from './App.vue'; import store from './store'; const vm = new Vue({ store:store, render: h => h(App) }).$mount('#app') 複製代碼
一共有5個核心屬性,分別是:
const store = new Vuex.Store({
state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) } } }) store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }] 複製代碼
const store = new Vuex.Store({
state: { count: 1 }, mutations: { increment (state) { // 變動狀態 state.count++ } } }) store.commit('increment') 複製代碼
const store = new Vuex.Store({
state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit('increment') } } }) 複製代碼
const moduleA = { state: () => ({ ... }), mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: () => ({ ... }), mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) store.state.a // -> moduleA 的狀態 store.state.b // -> moduleB 的狀態 複製代碼
若是請求來的數據是否是要被其餘組件公用,僅僅在請求的組件內使用,就不須要放入vuex 的state裏。
若是被其餘地方複用,這個很大概率上是須要的,若是須要,請將請求放入action裏,方便複用。
從vuex中取的數據,不能直接更改,須要淺拷貝對象以後更改,不然報錯;
用sessionstorage 或者 localstorage 存儲數據
存儲: sessionStorage.setItem( '名', JSON.stringify(值) )
使用: sessionStorage.getItem('名') ---獲得的值爲字符串類型,用JSON.parse()去引號; 複製代碼
也能夠引入插件vuex-persist,使用方法以下:
npm install --save vuex-persist or yarn add vuex-persist 複製代碼
import VuexPersistence from 'vuex-persist'
複製代碼
const vuexLocal = new VuexPersistence({ storage: window.localStorage }) 複製代碼
const store = new Vuex.Store({ state: { ... }, mutations: { ... }, actions: { ... }, plugins: [vuexLocal.plugin] }) 複製代碼
經過以上設置,在圖3中各個頁面之間跳轉,若是刷新某個視圖,數據並不會丟失,依然存在,而且不須要在每一個 mutations 中手動存取 storage 。
在嚴格模式下,不管什麼時候發生了狀態變動且不是由mutation函數引發的,將會拋出錯誤。這能保證全部的狀態變動都能被調試工具跟蹤到。
在Vuex.Store 構造器選項中開啓,以下
const store = new Vuex.Store({
strict:true, }) 複製代碼
使用mapGetters輔助函數, 利用對象展開運算符將getter混入computed 對象中
import {mapGetters} from 'vuex'
export default{ computed:{ ...mapGetters(['total','discountTotal']) } } 複製代碼
使用mapMutations輔助函數,在組件中這麼使用
import { mapMutations } from 'vuex'
methods:{ ...mapMutations({ setNumber:'SET_NUMBER', }) } 複製代碼
而後調用this.setNumber(10)至關調用this.$store.commit('SET_NUMBER',10)
action 是用this.store.dispatch('ACTION_NAME',data)來提交。
mutation是用this.$store.commit('SET_NUMBER',10)來提交 複製代碼
{ state, // 等同於 `store.state`,若在模塊中則爲局部狀態 rootState, // 等同於 `store.state`,只存在於模塊中 commit, // 等同於 `store.commit` dispatch, // 等同於 `store.dispatch` getters, // 等同於 `store.getters` rootGetters // 等同於 `store.getters`,只存在於模塊中 } 複製代碼
須要經過computed計算屬性來轉換。
<input v-model="message">
// ... computed: { message: { get () { return this.$store.state.message }, set (value) { this.$store.commit('updateMessage', value) } } } 複製代碼
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,讓構建單頁面應用變得易如反掌。包含的功能有:
第一步安裝
npm install vue-router -S 複製代碼
第二步在main.js中使用Vue Router組件
第三步配置路由
路由組件能夠是直接定義,也能夠是導入已經定義好的組件。這裏導入已經定義好的組件。以下
定義路由對象數組。對象的path是自定義的路徑(即便用這個路徑能夠找到對應的組件),component是指該路由對應的組件。以下:
調用Vue Router的構造方法建立一個Vue Router的實例對象,將上一步定義的路由對象數組做爲參數對象的值傳入。以下
第四步在App.vue中使用路由
在App.vue中使用標籤來顯示路由對應的組件,使用標籤指定當點擊時顯示的對應的組件,to屬性就是指定組件對應的路由。以下:
在router目錄下的index.js文件中,對path屬性加上/:id。使用router對象的params.id獲取動態參數
經常使用的是router.beforeEach(to,from,next),在跳轉前進行權限判斷。一共有三種:
使用query方法傳入的參數使用this.$route.query接受
使用params方式傳入的參數使用this.$route.params接受
route爲當前router跳轉對象裏面能夠獲取name、path、query、params等
router爲VueRouter實例,想要導航到不一樣URL,則使用router.push方法
找到入口文件main.js裏的new Vue(),必須使用router名,不能把router改爲Router或者其餘的別名
// 引入路由
import router from './routers/router.js' new Vue({ el: '#app', router, // 這個名字必須使用router render: h => h(App) }); 複製代碼
隨着項目功能模塊的增長,引入的文件數量劇增。若是不作任何處理,那麼首屏加載會至關的緩慢,這個時候,路由按需加載就閃亮登場了。
webpack< 2.4 時
{ path:'/', name:'home', components:resolve=>require(['@/components/home'],resolve) } webpack> 2.4 時 { path:'/', name:'home', components:()=>import('@/components/home') } 複製代碼
import()方法是由es6提出的,動態加載返回一個Promise對象,then方法的參數是加載到的模塊。相似於Node.js的require方法,主要import()方法是異步加載的。
Vue路由在Android機上有問題,babel問題,安裝babel polypill插件解決
使用@click.native。緣由:router-link會阻止click事件,.native指直接監聽一個原生事件
這個模塊請看個人另外一篇文章,此處再也不整理(我太懶了)
這個模塊請看個人另外一篇文章,此處再也不整理(我太懶了)
類型:String
默認:'/'
部署應用包時的基本 URL。默認狀況下,Vue CLI會假設你的應用是被部署在一個域名的根路徑上,例如https://www.my-app.com/。若是應用被部署在一個子路徑上,你就須要用這個選項指定這個子路徑。例如,若是你的應用被部署在https://www.my-app.com/my-app/,則設置publicPath爲/my-app/
這個值也能夠被設置爲空字符串 ('') 或是相對路徑 ('./'),這樣全部的資源都會被連接爲相對路徑,這樣打出來的包能夠被部署在任意路徑,也能夠用在相似 Cordova hybrid 應用的文件系統中。
類型:boolean
moren:true
不容許打包時生成項目來源映射文件,在生產環境下能夠顯著的減小包的體積
注 Source map的做用:針對打包後的代碼進行的處理,就是一個信息文件,裏面儲存着位置信息。也就是說,轉換後的代碼的每個位置,所對應的轉換前的位置。有了它,出錯的時候,除錯工具將直接顯示原始代碼,而不是轉換後的代碼。這無疑給開發者帶來了很大方便
放置生成的靜態資源 (js、css、img、fonts) 的 (相對於 outputDir 的) 目錄,默認是'',
指定生成的 index.html 的輸出路徑(相對於outputDir)。也能夠是一個絕對路徑。默認是'index.html'
是否在每次保存時使用eslint檢查,這個對語法的要求比較嚴格,對本身有要求的同窗可使用
css: {
//是否啓用css分離插件,默認是true,若是不啓用css樣式分離插件,打包出來的css是經過內聯樣式的方式注入至dom中的, extract: true, sourceMap: false,//效果同上 modules: false,// 爲全部的 CSS 及其預處理文件開啓 CSS Modules。 // 這個選項不會影響 `*.vue` 文件。 }, 複製代碼
本地開發服務器配置,此處直接貼上我經常使用的配置,以註釋的方式介紹
devServer: {
//配置開發服務器 host: "0.0.0.0", //是否啓用熱加載,就是每次更新代碼,是否須要從新刷新瀏覽器才能看到新代碼效果 hot: true, //服務啓動端口 port: "8080", //是否自動打開瀏覽器默認爲false open: false, //配置http代理 proxy: { "/api": { //若是ajax請求的地址是http://192.168.0.118:9999/api1那麼你就能夠在jajx中使用/api/api1路徑,其請求路徑會解析 // http://192.168.0.118:9999/api1,固然你在瀏覽器上開到的仍是http://localhost:8080/api/api1; target: "http://192.168.0.118:9999", //是否容許跨域,這裏是在開發環境會起做用,但在生產環境下,仍是由後臺去處理,因此沒必要太在乎 changeOrigin: true, pathRewrite: { //把多餘的路徑置爲'' "api": "" } }, "/api2": {//能夠配置多個代理,匹配上那個就使用哪一種解析方式 target: "http://api2", // ... } } }, 複製代碼
這是一個不進行任何 schema 驗證的對象,所以它能夠用來傳遞任何第三方插件選項,例如:
{
//定義一個全局的less文件,把公共樣式變量放入其中,這樣每次使用的時候就不用從新引用了 'style-resources-loader': { preProcessor: 'less', patterns: [ './src/assets/public.less' ] } } 複製代碼
是一個函數,會接收一個基於 webpack-chain 的 ChainableConfig 實例。容許對內部的 webpack 配置進行更細粒度的修改。例如:
chainWebpack(config) {
//添加一個路徑別名 假設有在assets/img/menu/目錄下有十張圖片,若是全路徑require("/assets/img/menu/img1.png") //去引入在不一樣的層級下實在是太不方便了,這時候向下方同樣定義一個路勁別名就很實用了 config.resolve.alias //添加多個別名支持鏈式調用 .set("assets", path.join(__dirname, "/src/assets")) .set("img", path.join(__dirname, "/src/assets/img/menu")) //引入圖片時只需require("img/img1.png");便可 } 複製代碼
參考:
一、Vue常見問題總結 https://blog.csdn.net/qq_27674439/article/details/99449197
二、vue常見面試題 https://zhuanlan.zhihu.com/p/92407628
三、vuex官網 https://vuex.vuejs.org/zh/
四、Vuex面試題彙總 https://juejin.im/post/5dba91e4518825647e4ef18b
五、Vue CLI官網 https://cli.vuejs.org/zh/
歷史好文推薦:
一、【萬字長文】史上最強css、html總結~看完漲薪再也不是夢
最後,若是喜歡小編,能夠關注小編的公衆號【小猴子web成長之路】,瞭解更多幹貨。關注以後後臺回覆知識體系,更可領取小編精心準備的前端知識體系,將來學習再也不迷茫。
本文使用 mdnice 排版