上家公司的項目主要是使用jQuery和Angular1,而後本身學了React,沒想到來到這家公司忽然開始作vue,不過vue仍是挺容易上手的。下面是vue技術棧的一些總結,都是來自官網,主要是本身對vue技術棧知識點的一些整理,所以此文很水,建議閱讀個人上一篇文章Vuejs技術棧從CLI到打包上線實戰全解析javascript
有兩種構建方式,獨立構建和運行構建。它們的區別在於前者包含模板編譯器然後者不包含。php
模板編譯器的職責是將模板字符串編譯爲純JavaScript的渲染函數。若是你想要在組件中使用template選項,你就須要編譯器。css
具體查看官網的流程圖,要注意的是created和mounted區別,created是vm實例已建立但未掛載,所以一些DOM操做應該放在mounted中。異步請求放在created或者mounted暫時沒發現什麼區別,如您知道有什麼區別,請評論指出。html
模板內的表達式不該該包含太多的邏輯,對於任何複雜邏輯,都應當使用計算屬性vue
computed屬性和methods不一樣的是計算屬性是基於它們的依賴進行緩存的。java
computed屬性和computed屬性,一般更好的想法是使用computed屬性而不是命令式的watch回調。雖然計算屬性在大多數狀況下更合適,但有時也須要一個自定義的watcher。當你想要在數據變化響應時,執行異步操做或開銷較大的操做,這是頗有用的。node
數組的變異方法(mutation method,會改變被這些方法調用的原始數組)會觸發視圖更新,有如下七個:vue-router
push() pop() shift() unshift() splice() sort() reverse()
當使用非變異方法時,能夠用新數組替換舊數組,或者使用Vue.set方法。vuex
能夠用新對象替換舊對象,或者使用Vue.set方法django
Vue.set(vm.someObject, 'foo', 'bar') this.someObject = Object.assign({}, this.someObject, { a:1, b:2 })
Vue.js爲v-on提供了事件修飾符和按鍵修飾符
能夠用v-model指令在表單控件元素上建立雙向數據綁定。常見修飾符有.lazy、.number、.trim。
也可使用自定義事件的表單輸入組件。
Vue組件的API來自三部分:props,events和slots:
1)組件的data屬性必須是函數
2)父子組件
在Vue.js中,父子組件的關係能夠總結爲 props down, events up 。父組件經過props向下傳遞數據給子組件,子組件經過events給父組件發送消息。
prop是單向綁定的:當父組件的屬性變化時,將傳導給子組件,可是不會反過來。這是爲了防止子組件無心修改了父組件的狀態——這會讓應用的數據流難以理解。
另外,每次父組件更新時,子組件的全部prop都會更新爲最新值。這意味着你不該該在子組件內部改變prop。若是你這麼作了,Vue會在控制檯給出警告。
爲何咱們會有修改prop中數據的衝動呢?一般是這兩種緣由:
1.prop做爲初始值傳入後,子組件想把它看成局部數據來用;
2.prop做爲初始值傳入,由子組件處理成其它數據輸出。
對這兩種緣由,正確的應對方式是:
1.定義一個局部變量,並用prop的值初始化它:
props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }
2.定義一個計算屬性,處理prop的值並返回。
props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
注意在JavaScript中對象和數組是引用類型,指向同一個內存空間,若是prop是一個對象或數組,在子組件內部改變它會影響父組件的狀態。
3)非父子組件
有時候兩個組件也須要通訊(非父子關係)。在簡單的場景下,可使用一個空的Vue實例做爲中央事件總線。在複雜的狀況下,咱們應該考慮使用專門的狀態管理模式。
4).sync修飾符
在一些狀況下,咱們可能會須要對一個prop進行『雙向綁定』。
2.0中移除了.sync,Vue2.3.0+又將其添加回來了,可是此次它只是做爲一個編譯時的語法糖存在,它會被擴展爲一個自動更新父組件屬性的v-on偵聽器。以下代碼
<comp :foo.sync="bar"></comp>
會被擴展爲:
<comp :foo="bar" @update:foo="val => bar = val"></comp>
當子組件須要更新foo的值時,它須要顯式地觸發一個更新事件:
this.$emit('update:foo', newValue)
5)使用slot進行內容分發
做用域插槽:接收從子組件中傳遞的prop對象。做用域插槽更具表明性的用例是列表組件,容許組件自定義應該如何渲染列表每一項
6)動態組件、is特性和keep-alive指令
7)子組件索引
儘管有props和events,可是有時仍然須要JavaScript中直接訪問子組件。爲此可使用ref爲子組件指定一個索引ID。
雖然 Vue.js 一般鼓勵開發人員沿着「數據驅動」的方式思考,避免直接接觸 DOM,可是有時咱們確實要這麼作。爲了在數據變化以後等待 Vue 完成更新 DOM ,能夠在數據變化以後當即使用 Vue.nextTick(callback) 。這樣回調函數在 DOM 更新完成後就會調用。
Vue在插入、更新或者移除DOM時,提供多種不一樣方式的應用過渡效果。包括如下工具:
1)單元素/組件的過渡
Vue提供了transition的封裝組件,在下列情形中,能夠給任何元素和組件添加過渡
2)多個元素的過渡
對於原生標籤可使用 v-if/v-else
3)多個組件的過渡
多個組件的過渡咱們可使用動態組件。
4)列表過渡
和Angular的指令相似,主要操做DOM,下面是一個滾動加載的指令,holder暫時沒想到什麼更好的處理方法:
let scrollCallback = function (callback) { let windowH = window.innerHeight let getDocumentHeight = function () { var body = document.body var html = document.documentElement return Math.max( body.offsetHeight, body.scrollHeight, html.clientHeight, html.offsetHeight, html.scrollHeight ) } let scrollH = document.documentElement.scrollTop || document.body.scrollTop if (windowH + scrollH >= getDocumentHeight() - (this.holder || 20)) { callback() } } let callBackWarpped export default { bind (el, binding, vnode) { let holder if (vnode.data && vnode.data.attrs && vnode.data.attrs['scroll-placeholder']) { holder = parseInt(vnode.data.attrs['scroll-placeholder']) } else { holder = 20 } callBackWarpped = scrollCallback.bind({el, holder}, binding.value) window.addEventListener('scroll', callBackWarpped, false) }, unbind: function () { window.removeEventListener('scroll', callBackWarpped, false) } }
混合是一種靈活的分佈式複用Vue組件的方式。混合對象能夠包含任意組件選項。以組件使用混合對象時,全部混合對象的選項將被混入該組件自己的選項。
1)建立插件
Vue.js的插件應當有一個公開方法install。這個方法的第一個參數是Vue構造器 , 第二個參數是一個可選的選項對象。
2)使用插件
經過全局方法Vue.use()使用插件:
// 調用 `MyPlugin.install(Vue)` Vue.use(MyPlugin)
也能夠傳入一個選項對象:
Vue.use(MyPlugin, { someOption: true })
1)router-link聲明式導航
<router-link to="/foo">Go to Foo</router-link>
router-link對應的路由匹配成功,將自動設置class屬性值.router-link-active。
2)編程式導航
// 字符串 router.push('home') // 對象 router.push({ path: 'home' }) // 命名的路由 router.push({ name: 'user', params: { userId: 123 }}) // 帶查詢參數,變成 /register?plan=private router.push({ path: 'register', query: { plan: 'private' }})
vue-router默認hash模式,也能夠設置爲路由的history模式。
vue-router提供的導航鉤子主要用來攔截導航,讓它完成跳轉或取消。有多種方式能夠在路由導航發生時執行鉤子:全局的, 單個路由獨享的, 或者組件級的。
一個路由匹配到的全部路由記錄會暴露爲$route對象(還有在導航鉤子中的route對象)的$route.matched數組。所以,咱們須要遍歷$route.matched來檢查路由記錄中的meta字段。
router-view是基本的動態組件,因此咱們能夠用transition組件給它添加一些過渡效果。
有時候,進入某個路由後,須要從服務器獲取數據。例如,在渲染用戶信息時,你須要從服務器獲取用戶的數據。咱們能夠經過兩種方式來實現:
導航完成以後獲取:先完成導航,而後在接下來的組件生命週期鉤子中獲取數據。在數據獲取期間顯示『加載中』之類的指示。
導航完成以前獲取:導航完成前,在路由的enter鉤子中獲取數據,在數據獲取成功後執行導航。
注意: 這個功能只在HTML5 history模式下可用。
當打包構建應用時,Javascript包會變得很是大,影響頁面加載。若是咱們能把不一樣路由對應的組件分割成不一樣的代碼塊,而後當路由被訪問的時候才加載對應組件,這樣就更加高效了。
結合Vue的異步組件和Webpack的code splitting功能,輕鬆實現路由組件的懶加載。
const Foo = resolve => require(['./Foo.vue'], resolve) const router = new VueRouter({ routes: [ { path: '/foo', component: Foo } ] })
能夠設置tag、append、active-class、exact等屬性
有時候咱們要讓 "激活時的CSS類名" 應用在外層元素,而不是a標籤自己,那麼能夠用router-link渲染外層元素,包裹着內層的原生a標籤:
<router-link tag="li" to="/foo"> <a>/foo</a> </router-link>
在這種狀況下,a將做爲真實的連接(它會得到正確的 href 的),而"激活時的CSS類名"則設置到外層的li。
routes、mode、base、linkActiveClass、scrollBehavior
1)注入的屬性
經過在Vue根實例的router配置傳入router實例,下面兩個屬性成員會被注入到每一個子組件。
$router:router實例
$route:當前激活的路由信息對象。這個屬性是隻讀的,裏面的屬性是immutable(不可變)的,不過你能夠watch(監測變化)它。
2)容許的額外配置:beforeRouteEnter、beforeRouteLeave
1)單一狀態樹
Vuex使用單一狀態樹--是的,用一個對象就包含了所有的應用層級狀態。至此它便做爲一個『惟一數據源(SSOT)』而存在。這也意味着,每一個應用將僅僅包含一個store實例。單一狀態樹讓咱們可以直接地定位任一特定的狀態片斷,在調試的過程當中也能輕易地取得整個當前應用狀態的快照。
2)在Vue組件中得到Vuex狀態
最好在根實例中註冊store選項,該store實例會注入到根組件下的全部子組件中,且子組件能經過this.$store訪問到。而不是在每一個須要使用state的組件中須要頻繁地導入。
3)mapState輔助函數
當一個組件須要獲取多個狀態時候,可使用mapState輔助函數幫助咱們生成計算屬性,這樣能夠簡化代碼書寫。mapState函數會返回一個對象,而後可使用對象展開運算符將它與局部計算屬性混合使用。
4)不要濫用vuex
使用Vuex並不意味着你須要將全部的狀態放入Vuex。雖然將全部的狀態放到Vuex會使狀態變化更顯式和易調試,但也會使代碼變得冗長和不直觀。若是有些狀態嚴格屬於單個組件,最好仍是做爲組件的局部狀態。你應該根據你的應用開發須要進行權衡和肯定。
getters用來從store中的state中派生出一些狀態,例如對列表進行過濾並計數:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length } }
getters能夠認爲是store的計算屬性。和state相似,有mapGetters輔助函數。
更改Vuex的store中的狀態的惟一方法是提交mutation。Vuex中的mutations很是相似於事件:每一個mutation都有一個字符串的事件類型(type)和一個回調函數(handler)。這個回調函數就是咱們實際進行狀態更改的地方,而且它會接受state做爲第一個參數
1)提交載荷(Payload)
你能夠向store.commit傳入額外的參數,即mutation的載荷(payload):
// ...
mutations: {
increment (state, n) { state.count += n } } store.commit('increment', 10)
2)Mutations需遵照Vue的響應規則
3)使用常量替代Mutation事件類型
4)mutation必須是同步函數
5)在組件中提交Mutations
你能夠在組件中使用this.$store.commit('xxx')提交mutation,或者使用mapMutations輔助函數將組件中的methods映射爲store.commit調用(須要在根節點注入store)。
actions相似於mutation,不一樣在於:
1)在組件中分發Action
你在組件中使用this.$store.dispatch('xxx')分發action,或者使用mapActions輔助函數將組件的methods映射爲store.dispatch調用(須要先在根節點注入store)
2)組合Actions
Action一般是異步的,那麼如何知道action何時結束呢?更重要的是,咱們如何才能組合多個action,以處理更加複雜的異步流程?
首先,你須要明白store.dispatch能夠處理被觸發的action的回調函數返回的Promise,而且store.dispatch仍舊返回Promise。
使用async/await會更加簡單:
// 假設 getData() 和 getOtherData() 返回的是 Promise actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { await dispatch('actionA') // 等待 actionA 完成 commit('gotOtherData', await getOtherData()) } }
因爲使用單一狀態樹,應用的全部狀態會集中到一個比較大的對象。當應用變得很是複雜時,store對象就有可能變得至關臃腫。
爲了解決以上問題,Vuex容許咱們將store分割成模塊(module)。每一個模塊擁有本身的state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行一樣方式的分割:
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的store接受plugins選項,這個選項暴露出每次mutation的鉤子。Vuex插件就是一個函數,它接收store做爲惟一參數。
開啓嚴格模式,僅需在建立store的時候傳入strict:true
在嚴格模式下,不管什麼時候發生了狀態變動且不是由mutation函數引發的,將會拋出錯誤。這能保證全部的狀態變動都能被調試工具跟蹤到。
不要在發佈環境下啓用嚴格模式!嚴格模式會深度監測狀態樹來檢測不合規的狀態變動--請確保在發佈環境下關閉嚴格模式,以免性能損失。