當前總結是本人在業餘學習與實踐過程後的總結與概括,旨在檢驗本身的積累,也方便忘記時查閱,同時也但願能幫助那些這方面知識匱乏的同行門,總結是基於vue2.x
,vue-cli3.x
,主要記錄些,vue
經常使用的指令、事件,監聽、數據綁定、過濾器、組件、動畫、vuex
,vue-router
等平常工做中時經常使用到的東西,也有些經常使用的插件
和開發工具
的介紹與使用,以及部分性能優化
的建議與實踐,若有不對,或不足的地方,也請各位大神,指出來,學習學習。javascript
mvvm
m
是vue
實例中的data
,自定義的數據或後端返回的數組不是後端mvc
裏的model
概念不一樣。php
vm
是vue
的實例 m
和v
之間的調度者 是mvvm
的核心思想v
是 html
要渲染的。v-cloak
解決{{}}插值閃爍問題v-text
會先執行 覆蓋 元素中本來的內容 可是插值表達式只會覆蓋本身的佔位符,默認不會閃爍v-html
渲染 html標籤 覆蓋元素中原有元素內容v-bind
: 簡寫爲: 用來綁定數據 能夠寫合法的js表達式v-on
: 簡寫爲 @
用來點擊事件stop
阻止冒泡 :外層和裏層都有方法 點擊裏層會產生冒泡,也會觸發外層的事件。順序 從裏到外產生事件prevent
阻止瀏覽器默認行爲 :a
標籤有瀏覽器默認行爲。capture
捕獲事件 :點擊裏層先觸發外層再觸發裏層 順序從外到裏產生事件self
只觸發本身自己的事件 不會產生冒泡和捕獲事件 相似於阻止冒泡 但只針對本身那一層 最外層仍是會被最裏層冒泡冒到 stop
是阻止全部層次once
事件只執行一次v-bind
: 數據的單向綁定v-modle
:數據的雙向綁定 這個只能用於表單元素中tips: 表單元素radio
text
address
select
checkbox
textarea
class
綁定<div :class="[classA,classB,{'classC':flag}]" > data(){ return{ flag:true } }
tips:能夠在類中的數組中寫三元表達式,但推薦使用對象來代替它控制是否渲染
<div :class="{classA:falg1,classB:flag2}" /> data(){ return{ falg1:true, falg2:true } }
<div :class="['ac','bd',falg?'active','']" / > data(){ return{ falg:true, } }
<div :class="classObj" /> data(){ return{ classObj:{classA:falg1,classB:flag2} } }
tips:直接使用一個對象數組來控制樣式
style
的對象來實現樣式的修改<div :class="styleObj" /> data(){ return{ styleObj:{color:red} } }
style
的數組帶對象來實現樣式的修改<div :class="[styleObj1,styleObj2]" /> data(){ return{ styleObj1:{color:red}, styleObj2:{color:red} } }
v-for
的使用能夠遍歷: 普通數組,對象數組,對象,還能夠是數字css
<div v-for='(item,key,index) in object' :key='index'> {{item}}--{{key}}--{{index}} </div> <div v-for='(count in 10)'> </div>
tips:在遍歷對象的時候有多個index
索引,遍歷數字時是從1開始的。綁定key
時屬性值必須是number
或者string
v-if
、v-show
v-if
有較高的切換性能 , 適合元素可能永遠不會被用戶看到。v-show
有較高的初始渲染消耗,適合元素頻繁切換。vue-devtools
插件,使用這個插件並設置插件,容許訪問文件網址。 會在調試中出現vue相關的東西html
debugger
直接寫能夠調試<div v-for='(item,key) in object' :key='index'> {{item | dateFormat}} </div> <div v-for='(count in 10)'> </div>
vue.filter('過濾器名稱',function(){ })
filters:{ dateFormat:function(data,param){ do some } }
tips:前端
data
就是|
第一個參數已經被定死了,永遠是, 管道左邊要被轉換的數據,param 是過濾方法傳進來的其餘參數,過濾器採用就近優先原則,若是私有和全局的名稱同樣就優先採用私有的。padstart
和padend
es6
的補0
方法- 第二個參數是字符串,第三個參數是表達式,若是本身定義參數值是動態的會報錯,還未找到緣由,後期會找時間再看看,目前就是
簡單的過濾用過濾器
,複雜點用方法
,能用計算屬性用計算屬性
,有緩存,能提升性能
<input @keyup.enter='方法名'></input>
tips:
enter
能夠換成鍵盤上的任何一個值,只要去找相關的鍵盤碼,就均可以使用,推薦設置個別名,放在沒有按鈕操做的模板。
Vue.config.keyCodes.f2=113
,就可以使用了vue
tips:f2
修飾符是vue
裏沒有定義的本身建立。
定義的指令都要按規定去建立 在bind
和inserted
還有 updated
中去建立java
Vue.directive('focus'{ //每當指令綁定到元素上的時候,會當即執行bind 函數,只執行一次, 注意:在元素剛綁定元素的時候,尚未插入到dom中去,這時候,調用focus方法沒有做用,即放在focus 放在bind中是不起做用 的 bind:function(el,binding){ el.style.color=binding.value }, //表示元素插入到dom中的時候,只執行一次 inserted:function(){ el.focus() js行爲放在這裏去建立 }, //當組件更新的時候,可能會觸發屢次 updated:function(){}, })
tips:node
參數1
指令名稱,在定義的時候,指令名稱前面不須要加v-前綴,可是調用的時候,必須在指令名稱前加v-前綴;參數2
:是一個對象,在這個對象身上,有一些指令相關的函數,這些函數能夠在特定的階段,執行相關的操做。webpack
- 在每一個函數中,的第一個參數,永遠是
el
,el
是表明被bind
綁定的元素,el
是個原生的js
對象。第二個參數能夠是用戶傳進來值
bingding.value
ios
directives:{ '指令名':{ bind:function( el,b){ } } }
'指令名':function(el,binding){ } //注意這個function 等同於 把代碼寫到bind和update中去
tips: 樣式相關的指令放在bind
中,js
行爲相關的放在inserted
中比較合適,防止指令不生效。使用場景 寫組件時能夠用這個去改樣式
beforeCreate()
:這是咱們遇到的第一個生命週期函數,表示實例徹底被建立出來以前,會執行它...created()
: 這是遇到的第二個生命週期函數...beforeMount()
:這是遇到的第3個生命週期函數,表示 模板已經在內存中編輯完成,可是還沒有把模板渲染(掛載)到頁面中。在 beforeMount
執行的時候,頁面中的元素,尚未被真正替換過來,只是以前寫的一些模板字符串。就像{{text}}這樣mounted()
:這是遇到的第四個生命週期函數,表示內存中的模板,已經真實的掛載到了頁面中,用戶已經能夠看到渲染好的頁面了。只要執行完這個生命週期,就表示整個vue
實例已經初始化完畢了,此時,組件已經脫離了建立階段,進入到了運行階段。beforeUpdate()
:這時候表示,咱們的界面尚未被更新[但數據已經被更新了頁面中顯示的數據,仍是舊的,此時data
數據是最新的。頁面還沒有和最新的數據保持同步update()
: 這一步執行的是 先根據data
中最新的數據,在內存中從新渲染出一份最新的內存dom
樹,當最新的內存dom
樹被更新後,會把最新的內存DOM
樹從新渲染到真實的頁面中去,這時候,就完成了數據data(model層)->view(視圖層)
的更新,頁面和data
數據已經保持同步了,都是最新的。beforeDestory
:當執行 beforeDestory
鉤子函數的時候,Vue
實例就已經從運行階段,進入到銷燬階段, 當執行beforeDestroy
的時候,實例身上全部的data
和全部的methods
以及過濾器、指令...
都處於可用狀態,此時,尚未真正執行銷燬的過程。destroyed
:當執行這個函數的時候,組件已經被徹底銷燬了,此時,組件中全部的數據,方法,指令,過濾器...
都已經不可用了
<style> .v-enter, .v-leave-to{ opacity:0; transform:translateX(150px) --這東西是位移 } .v-enter-active, .v-leave-active{ transition:all 0.4s ease; } </style>
<transition name='my'> <h3 v-if="flag"></h3> </transition>
<script> data(){ return { flag:false } } </script>
<transition enter-active-class="bounceIn" leave-avtive-class="bounceOut" duration='200' > <h3 v-if="flag" class="animated" ></h3> </transition>
<transition <div @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter" > </div> </transition>
<transition <div v-show="flag" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter" > </div> </transition>
<script> methods:{ beforeEnter(el){ //動畫入場以前,此時動畫還沒有開始, 能夠在beforeEnter中設置元素開始動畫以前的初始位置 el.style.transform= "translate(0,0)" }, enter(el,done){ /*這句話,沒有實際的做用,可是,若是不寫,出不來動畫效果,能夠認爲 這個會強制刷新動畫,ofset觸發了重繪重排致使動畫更新了*/ el.offsetWidth el.style.transform= "translate(150px,450px)" el.style.transition='all 1s ease' /*這裏的done 表明着 afterEnter的引用, 這個會當即執行afterEnter 不然會有延時 */ done() }, afterEnter(el){ /*動畫完成以後,會調用afterEnter */ this.flag=!this.flag } } </script>
v-for
循環渲染出來的,不能使用transition
包裹,須要使用transitionGroup
<transition-group appear tag='ul'> <li v-for > <li> </transition-group>
.v-enter, .v-leave-to{ opacity: 0; transform:translateY(80x); } .v-enter-active, .v-leave-active { transition: all 0.6s ease; } /*離開後下一個東西沒有動畫使用這個可使用動畫實現下一個東西漸漸地飄上來的效果,要和 v-leave-active的absolute 配合 固定寫法*/ .v-move { transition:all 0.6s ease } .v-leave-active{ /* absolute 有個特色元素默認寬度就是最小值,要在元素上添加width:100%*/ position:absolute; }
<transition mode="out-in"> <component :is="comName" > </component> </transition>
tips:
v-enter
[這是一個時間點] 是進入以前,元素的起始狀態,此時尚未開始進入v-leave-to
[這是一個時間點]是動畫離開以後,離開的終止狀態,此時,元素動畫已經結束了v-enter-active
[入場動畫的時間段]v-leave-active
[離場動畫的時間段]animated
是個動畫庫 新版本彷佛不須要加入- 使用:
duration=200
來表示動畫的時間 若是隻寫一個表示統一配置了開場和離場時間 用對象
可傳入c入場和離場duration="{enter:200,leave:400}"
- 添加
appear
屬性,實現頁面剛展現出來,入場時候的效果- 經過爲
transition-group
元素,設置tag
屬性指定transition-group
渲染爲指定元素,若是不指定tag
屬性,默認,渲染爲span
標籤mode="out-in" 先過渡再進來,防止有陰影,經過
mode`來設置過渡方式。注意:最外層必定要用
transition
包裹着,動畫彷佛升級了,能夠在transition
標籤中加入name
屬性,而且在css
樣式中把v
,替換爲你的name
屬性值。
1.使用Vue.extend
來建立全局的Vue
組件
var coml=Vue.extend({ template:'<h3>這是使用Vue.extend 建立的組件</h3>' })
//第一個參數組件名稱,第二個參數建立出來的組件模板對象 Vue.component('myComl',coml)
<my-coml><my-coml/>
2.使用 vue.component
來建立組件
Vue.component('mycom2',{ template:'<div> <h3> 這是直接使用Vue.component 建立出來的組件 </h3> </div>' })
3.使用 template
來建立組件
<template id='tmp1'> <div> <h1> 這裏經過template元素,在外部定義的組件結構,這個方式,有代碼的智能提示和高量 </h1> </div> </template> Vue.component('mycom3',{ template:'#tem1' })
4.私有組件 componment
<template id='temp2'> <h1>這是私有login組件</h1> </template> componment:{ login: { template:'tmpl2' } }
Vue.component
定義了全局組件的時候,組件名稱使用了駝峯命名,在引用的時候大寫的駝峯要改成小寫,同時兩個單詞之間 使用-連接Vue.component
第一個參數:組件的名稱,未來在引用組件的時候,就是一個標籤形式來引入的,第二個參數:Vue.extend
建立的組件,其中 template
就是組件未來要展現的內容
template
屬性指向的模板內容,必須有且只能有惟一的一個根元素。data
data
數據data
和實例中的data
有點不同,實例中的data
能夠爲一個對象,可是組件中的data
必須是一個方法。data
除了必須爲一個方法以外,這個方法內部,還必須返回一個對象才行。data
數據,使用方式,和實例中的data
使用方式徹底同樣!data
爲何必須是個方法返回個對象呢? 由於要確保每一個實例
裏的數據是惟一的,獨有的。若是data
裏的數據是放在實例外部
的,會被其餘實例
共享。v-if
和 v-else
進行切換即標籤頁切換<a href="" @click.prevent="flag=true" > 登陸 </a>
<a href="" @click.prevent="flag=flase" > 註冊 </a>
<login v-if="flag"> </login> <register v-else="flag"> </register>
2.vue
提供了 component
,來展現對應名稱的組件
//component 是一個佔位符 :is屬性,能夠用來指定要展現的組件的名稱 寫死的時候這個組件名要是個字符串,動態綁定時key普通寫法就好,但value必須是字符串。 <component :is="'componentId'"> </component> <component :is="oneName"> </component> data(){ return{ oneName:"login", } }
1.父子組件傳值,經過v-bind:(:)
來傳值,經過props
來接收值
2.父組件用事件綁定機制傳遞方法
給子組件—v-on
簡寫 @
//父組件中 <component-name :children='children' //傳值 @handle='show' //綁定方法 > </component-name> data(){ return(){ children:11 } } methods:{ show(data){ } }
3.emit
英文原意: 是觸發,調用,發射的意思。 @handle=show
父組件傳show
方法給子組件。
子組件接收父組件的方法,並用$emit
把子組件的值傳給父組件
//子組件中 methods:{ handle(){ this.$emit('func',{ age:1, name:'搞事' }) } }
4.在父組件中接收子組件全部參數的同時,添加自定義參數
1.子組件傳出單個參數時: // 子組件 this.$emit('test',this.param) // 父組件 @test='test($event,userDefined)' 2.子組件傳出多個參數時: // 子組件 this.$emit('test',this.param1,this.param2, this.param3) // 父組件 arguments 是以數組的形式傳入 @test='test(arguments,userDefined)'
tips:子組件中的data
數據,並非經過 父組件傳遞過來的,而是子組件自身私有的,好比子組件經過ajax
,請求回來的數據,均可以放到data
身上,data
上的數據都是可讀可寫的;
<h3 id='myh3' ref='myh3'> </h3> methods:{ getElement(){ console.log( this.$refs.myh3.innerText) } }
//組件也可使用ref,讓父組件調用子組件裏的方法和屬性值 <login ref='mylogin'> </login> methods:{ getElement(){ //父組件調用子組件裏的屬性值 console.log(this.$refs.mylogin.msg) } }
tips:
refs
;s
表明多個引用,會有多個dom
元素。ref
英文是reference
,值類型和引用類型。
1.這是vue-router
提供的元素,專門用來 看成佔位符的,
未來,路由規則,匹配到的組件,就會展現到這個router-view
中去,因此:咱們能夠把router-view認爲是一個佔位符
<router-view></router-view>
2.路由切換 模板寫法,默認渲染爲一個a
標籤,
使用tag
的span
能夠用來轉換模板的標籤名
<router-link to="/login" tag='span' > 登陸 </router-link>
3.路由配置
new VueRouter({ //路由匹配規則 routes:[ { path:'/', redirect:'/login' }, { path:'login', component:login }, { path:'/register', component:register } ] //路由高亮的類名 linkActiveClass:'myactive' }) var vm=new Vue({ el:'#app', data:{}, methods:{}, router //將路由規則對象註冊到vm實例上,用來監聽Url地址的變化,而後展現對應的組件。 })
4.路由傳參
1.query
//獲取id this.$route.query.id
2.在path
上設置參數
//參數要一一對應不可缺失,否則可能會 形成路由的不匹配 < router-link to="/login/12/ls" >
{ path:'/login/:id/:name',component:login }
3.params
新的方式可看文檔
5.子路由
<router-link to="/account/login" > </router-link>
routes:[ { path:'/account', component:account, children:{ { path:'login', component:login } } } ]
tips:
- 每一個路由規則,都是一個對象,這個規則對象,身上,有兩個必須的屬性。
- 屬性1 是
path
,表示監聽,哪一個路由連接地址;- 屬性2是
component
,表示,若是路由是前面匹配到的path,則展現component
屬性對應的那個組件。- 子路由不能加
/
, 加了/ 會以根目錄爲基準匹配,這樣不方便咱們用戶去理解url
地址- 超連接的
to
必定要加上父路由
==注意==:componen
屬性值,必須是一個組件的模板對象,不能是組件的引用名稱
根據name
來找組件
<router-view></router-view> <router-view name="left"></router-view> <router-view name="main"></router-view>
var header={ template:'<h1>header</h1>' } var leftBox={ template:'<h1>leftBox</h1>' } var mainBox={ template:'<h1>mainBox</h1>' }
{ path:'/',components:{ 'default':header, 'left':leftBox, 'main':mainBox } }
監聽非dom
元素
watch:{ 'obj.a'(newValue,oldValue){ }, immediate:false }
watch:{ 'obj':{ handler (newValue, oldValue) { } }, deep:true //深程度監聽 性能消耗大 }
watch:{ //監聽路由 '$route.path':{ handler (newValue, oldValue) { } }, //immediate:true表明若是在 wacth 裏聲明瞭以後,就會當即先去執行裏面的handler方法,若是爲 false就跟咱們之前的效果同樣,不會在綁定的時候就執行 immediate:true }
tips:
- 用了
obj.a
加上handle +immediate:true
,就能夠監聽 對象裏的值,若是是obj
加上handle+deep true
也是能夠監聽對象的屬性可是性能消耗大 通常是直接對象> > +屬性- 用
handle
方法可讓watch
初始化就執行,若是不用 handle它就先不執行,待數據改變再執行。- 不要在
watch
和computer
中去修改參與計算或者監聽的值 而是要生成新的值。
computed
計算屬性computed:{ 'fullname':(){ return } }
render
函數註冊組件(vm
[vue
實例]的屬性)render:function(createElements){ //createElements是一個方法,調用它,可以把指定的 組件模板 渲染爲html結構 return createElements(login) //注意 這裏 return 的結果,會替換頁面中el 指定的那個容器 }
tips:render
和components
區別render
會把整個app
裏組件所有覆蓋掉一個app
中只能放一個render
組件components
能夠多個,且不會覆蓋
slot
插槽1.寫插槽
<div v-if="layout === 'block'" class="layout-block" :class="scroll?'layout-scroll':''"> <slot></slot> //匿名插槽 </div> <!-- 左右塊 --> <div v-if="layout === 'both'" class="d-flex jc-between"> <div class="layout-both" :class="scrollLeft?'layout-scroll':''"> <slot name="left"></slot> //有名字的插槽 </div> <div class="layout-both" :class="scrollRight?'layout-scroll':''"> <slot name="right"></slot> </div> </div>
2.使用插槽
//有名字的插槽 # v-slot的縮寫是# <template #left></template> <template v-slot="left" > </template>
tips 區別對待v-slot="" 和v-slot:name; =和:的區別 一個是slot的name 一個是父組件獲取子組件的數據,插槽必定要用
template包裹着
<template> 插槽的內容 </template>
安裝 nrm
npm i nrm -g
全局安裝nrm ls
顯示列表nrm use npm
使用npm use
後有不少地址可選擇tips:nrm
只是單純的提供幾個經常使用的下載包url
地址,並可以讓咱們在這幾個地址以前,很方便的進行切換,可是,咱們每次裝包的時候,使用的裝包工具,都是npm
。和
npm i cnpm -g 不同
在網頁中會引用哪些常見的靜態資源
js
css
Image
字體文件(Fonts)
模板文件
webpack-dev-server
實現自動打包功能,瀏覽器不用刷新也能看到文件已經修改,打包的文件並無放在實際的物理磁盤上,而是直接託管到了,電腦的內存中,因此,咱們在項目根目錄中,根本找不到這個打包好的文件,這文件和src
、 dist
、 node_modules
平級,有一個看不見的文件
hot
網頁不重載 直接更新 加快打包速度 不生成新文件
"scripts":{ "dev":"webpack-dev-ser ver --open --prot 3000 --contentBase src --hot " }
配置文件中配置熱更新
devServer:{ hot:true 就熱更新了 }
tips:webpage
當中帶s
都是數組
webpack
引入vue
在 webpack
中 使用如下方式導入的Vue
構造函數,功能並不完善,只提供了 runtime-only
的方式,並無提供 像網頁中那樣的使用方式;
閹割版 import Vue from 'vue' 齊全版 1. import Vue from '../node_modules/vue/dist/vue.js' 2. module.exports={ resolve:{ //設置 Vue被導入的時候的包的路徑 alias:{ "vue$":"vue/dist/vue.js" } } }
tips: 包的查找規則:
- 找項目根目錄中有沒有
node_modules
的文件夾- 在
node_modules
中 根據包名,找對應的vue
文件夾- 在
vue
文件夾中,找一個叫作package.json
的包配置文件- 在
package.json
文件中,查找一個main
屬性[main
屬性指定了這個包在被加載時候的入口文件]- 改了
webpake
的包就須要從新運行項目
webpack
中經過render
展現組件若是想要經過vue
,把一個組件放到頁面中去展現,vm
實例中的render
函數能夠實現
render:function(createElement){ return createElement(login) } //就一行能夠省略{} 而且沒有花括號默認就有return, 簡寫: render: c => c(login)
tips:
webpack
中 如何使用Vue:
- 安裝
Vue
的包因爲在
webpack
中,推薦使用.vue
這個組件模板文件定義組件,因此須要安裝 能解析這種文件的loader
- 在
main.js
中,導入vue
模塊import Vue from 'vue'
- 定義一個
.vue
結尾的組件,其中,組件有三部分組成- 使用
import login from './login.vue'
導入這個組件- 建立
vm
的實例var vm = new Vue
({el:'app',render:c=>c(login)})
- 在頁面中建立一個
id
爲app
的div
元素,做爲咱們vm實例要控制的區域
export default
和 export
export default
向外暴露的成員,可使用任意的變量來接收export default
只容許向外暴露1次export default
和 export
向外暴露成員export
向外暴露的成員,只能使用{}的形式來接收,這種形式,叫作[按需導出]export
能夠向外暴露多個成員,同時,若是某些成員,咱們在import
的時候,不須要,則能夠不在 { }中定義export
導出的成員,必須嚴格按照導出時候的名稱,來使用{ } 按需接收使用 export
導出的成員,若是就想換個名稱來接收,可使用 as 來起別名
const arr={ a:'1', b:'2' } export default arr /* export default { 這個暴露是錯誤的因此當前註釋 一個js文件中只能暴露一次 address:'北京' } */ export title=1 import arr, {title as title1 } from '/xxx.js'
render
會把el
指定的容器中,全部的內容都清空覆蓋,全部不要把路由的router-view
和router-link
直接寫到el
所控制的元素中app
這個組件,是經過vm
實例的render
函數,渲染出來的,render
函數若是要渲染組件,渲染出來的組件,只能放到el: '#app'
所指定的元素中;Account
和GoodsList
組件,是經過路由匹配監聽到的,因此,這兩個組件,只能展現到屬於路由的
<router-view></router-view>中去
標籤頁
切換scoped
原理樣式的 scoped
是經過 css
的屬性選擇器來實現的 .aa[vsfp]{color:red}
tips:vsfp是哈希值
模擬 promise
getFution(aa,callback){ callback(aa) } getFution(aa,funtion(res){ console.log (aa) })
異步操做
/* 每當new一個Promise實例的時候,就會當即執行這個異步操做中的代碼。也就是說,new的時候,除了可以獲得一個promise實例以外,還會當即調用 咱們爲 Promise 構造函數傳遞的那個funtion,執行這個function中的異步操做代碼。
*/
var promise=new Promise(function(resolve,reject){
異步操做,ajax函數等,並且能夠自由輸出東西了 resolve(true) reject(false)
})
getFunction(){
var promise=new Promise(function(){ 異步操做,ajax函數等,並且能夠自由輸出東西了 })
}
getFunction().then(
function(data){
console.log(err)
},function(err){
console.log(err)
})
正確使用方式
getFunction(aa)
.then(function(data){
console.log(data) return getFunction() --返回後,可使用後續的then
})
.then(function(data){
console.log(data) return getFunction()
})
.then(funtion(data){
console.log(data)
})
//捕獲只放在最後面。前面有任何的異常都會終止
.catch(function(data){ console.log(data) }
> tips:在 `then`裏面多寫個返回錯誤的方法是不可取的。 #### 11. vuex + `vuex`是爲了保存組件之間共享數據而誕生的,若是組件之間 有要共享的數據,能夠直接掛載到`vuex`中,而沒必要經過父子組件之間傳值了,若是組件的數據不須要共享,此時,這些不須要共享的私有數據,沒有必要放到`vuex`中; + `vuex`,存放共享數據,`data` 存放組件私有的數據 `props`存放父組件傳過來的數據 + 操做`vuex`裏的`state` - 直接操做`store`裏的屬性值,不推薦這種作法
this.$store.state.屬性值 ```
推薦只經過mutations
提供的方法,才能操做對應的數據,
mutations:{ increment(state,payload){ state.count++ } } this.$store.commit('方法名')
vuex
裏的getters
若是`store`中`state`上的數據,在對外提供的時候,須要作一層包裝,那麼推薦使用`getters`。 ``` optCount:state=>state.count this.$store.getters.*** ```
tips:increment
方法裏的state
是屬於vuex
裏的state
;count
是state
裏的屬性 ;payload
外部傳進來的值,用來修改state
裏屬性的值.。最多支持只能傳兩個參數,能夠是數組和對象。
#### 12. ngrok
能夠映射本地80
端口,把本地的映射爲外網
npm地址
//npm下載 --感受下的有點慢 換個路徑下比較好 npm install ngrok -g //命令 ngrok http 80
tips: 須要開啓本地服務器,映射後只是映射www路徑,不是完整的程序路徑須要本身去補充完整
//第一種 圖片質量小的能夠自動轉換爲base64的 img: require("@/../public/img/home/user.jpg ") //第二種 這裏能夠把最前面的 / 看作是public /img/abnormal/Trash.png 即 public/img/abnormal/Trash.png
tips: @是指src目錄 .. @的上一級目錄,再進入public
1.watch
若是是obj 加上 handle+deep true
也是能夠監聽對象的屬性可是性能消耗大
2.computer
裏生成的值 會有緩存 不建議用函數去處理一些值得計算 而是用 computer
來計算值,這樣性能高。
3.:key ='id'
id是列表返回的id 若是沒有id 就寫item 通常不建議 寫 index (eslint會有警告錯誤信息) 寫上key 是爲了減小消耗 它會有個緩存。
4.v-once
和 v-model
的區別是 只會綁定一次 不會從新更新內容 能夠 減小開銷 應用場景:只讀場景,不進行修改頁面內容的時候
5.v-for
和 v-if
不適合在同個div連用
template
來解決<template v-for="(column, index) in btn"> <el-button size="small" :type='column.type' :plain='column.plain' :class='!isEmpty(column.style)&&[scope.$index + (currentPage - 1) * pageSize==column.style.index?column.style.className:""] ' @click="handle(id&&!column.isGetAll?scope.row[id]:scope.row,column.lable,scope.$index + (currentPage - 1) * pageSize)" :key='index'> {{column.lable}} </el-button> </template>
6.this.$parent
可修改父組件值,但不建議,只讀就好
7.gzip
優化
vue
配置 在前端生成帶有gz
的文件compression-webpack-plugin
const CompressionWebpackPlugin = require('compression-webpack-plugin') const productionGzipExtensions = ['js', 'css'] const isProduction = process.env.NODE_ENV === 'production' configureWebpack: config => { if (isProduction) { config.plugins.push( new CompressionWebpackPlugin({ algorithm: 'gzip', test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), threshold: 10240, minRatio: 0.8 }) ) } },
ngnix服務端配置
//配合前端的gzip 在站點配置添加以下代碼: location ~* \.(css|js)$ { gzip_static on; } 這是 nginx 的靜態 gzip功能,會自動查找對應擴展名的文件,若是存在 gzip 文件,就使用,若是沒有就用原文件 //後端返回gzip gzip on; gzip_static on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.1; gzip_comp_level 2; gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml; gzip_vary on; gzip_proxied expired no-cache no-store private auth; gzip_disable "MSIE [1-6]\.";
8.cdn
加速
<script src="https://unpkg.com/vue@2.6.10/dist/vue.runtime.min.js"></script> <script src="https://unpkg.com/vuex@3.0.1/dist/vuex.min.js"></script> <script src="https://unpkg.com/vue-router@3.0.3/dist/vue-router.min.js"></script> <script src="https://unpkg.com/axios@0.19.0/dist/axios.min.js"></script> <script src="https://unpkg.com/element-ui@2.9.2/lib/index.js"></script>
//有了config就按如下配置 configureWebpack: config => { //cdn config.externals = { vue: 'Vue', vuex: 'Vuex', 'vue-router': 'VueRouter', axios: 'axios' } if (isProduction) { config.plugins.push( new CompressionWebpackPlugin({ algorithm: 'gzip', test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), threshold: 10240, minRatio: 0.8 }) ) } }
9.網頁中引入的靜態資源多了之後有什麼問題?
二次
請求;要處理錯綜複雜的依賴關係
解決方案:
- 合併、壓縮、精靈圖、圖片的
base64
編碼 、cdn
- 可使用以前學過的
requireJs
、也可使用webpage
10.創建不一樣的環境變量(開發、測試、正式)
1、創建環境配置文件 在package.json 同級的目錄下 創建3個文件 1 .env.development --開發環境 (本地環境) 2 .env.production --正式環境 (正式線服務器--打包) 3 .env.test --測試環境 (測試線服務器--打包) 2、在每一個文件中寫入具體的配置內容 /*****.env.development文件的內容*****/ NODE_ENV = 'development' VUE_APP_CURRENT_MODE = 'development' /*****.env.production文件的內容*****/ NODE_ENV = 'production' VUE_APP_CURRENT_MODE = 'production' /*****.env.test*****/ NODE_ENV = 'production' VUE_APP_CURRENT_MODE = 'test' 3、在package.json 中寫入 1.在純粹的vue_cli3.x配置以下 "scripts": { "serve": "vue-cli-service serve --mode development", "build": "vue-cli-service build --mode production", "build:test": "vue-cli-service build --mode test", }, 2.在uni-app下的vue_cli3.x的配置 "scripts": { "serve": "npm run dev:h5 -- development", //修改點 "build": "npm run build:h5 -- production", //修改點 "build:test": "npm run build:h5 -- test", //修改點 "build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build --mode", //修改點 "build:mp-alipay": "cross-env NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build", "build:mp-baidu": "cross-env NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build", "build:mp-toutiao": "cross-env NODE_ENV=production UNI_PLATFORM=mp-toutiao vue-cli-service uni-build", "build:mp-weixin": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build", "dev:h5": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve --mode", //修改點 "dev:mp-alipay": "cross-env NODE_ENV=development UNI_PLATFORM=mp-alipay vue-cli-service uni-build --watch", "dev:mp-baidu": "cross-env NODE_ENV=development UNI_PLATFORM=mp-baidu vue-cli-service uni-build --watch", "dev:mp-toutiao": "cross-env NODE_ENV=development UNI_PLATFORM=mp-toutiao vue-cli-service uni-build --watch", "dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch", "info": "node node_modules/@dcloudio/vue-cli-plugin-uni/commands/info.js" },
tips:以上不一樣環境的切換,修改點主要就是mode -- '環境變量'
1.postcss-plugin-px2rem
配置文件名postcss.config.js
vue-cli3.x
腳手架自帶的px
轉rem
等單位的配置,創建腳手架的時候選擇分離 否則配置在josn
文件中很差配置
module.exports = { plugins: [ require('autoprefixer')(), require('postcss-plugin-px2rem')({ rootValue: 192, //設計圖的寬度/10 unitPrecision: 10, //換算的rem保留幾位小數點 mediaQuery: true, minPixelValue: 3 // exclude:/node_modules|folder_name/i,把第三方的框架排除掉 }) ] }
2.babel-plugin-transform-remove-console
刪除console
,在根目錄中新建個.babelrc
的文件,在如下文件中配置
//第一種 { "env": { "production": { "plugins": [ ["transform-remove-console", { "exclude": ["error", "warn"] }] ] } } } //第二種 1、創建環境配置文件 在package.json 同級的目錄下 創建3個文件 1 .env.development --開發環境 (本地環境) 2 .env.production --正式環境 (正式線服務器--打包) 3 .env.test --測試環境 (測試線服務器--打包) 2、在每一個文件中寫入具體的配置內容 /*****.env.development文件的內容*****/ NODE_ENV = 'development' VUE_APP_CURRENT_MODE = 'development' /*****.env.production文件的內容*****/ NODE_ENV = 'production' VUE_APP_CURRENT_MODE = 'production' /*****.env.test*****/ NODE_ENV = 'production' VUE_APP_CURRENT_MODE = 'test' 3、在package.json 中寫入 "scripts": { "serve": "vue-cli-service serve --mode development", "build": "vue-cli-service build --mode production", "build:test": "vue-cli-service build --mode test", }, 4、在babel.config.js 中寫 let transformRemoveConsolePlugin = []; if (process.env.VUE_APP_CURRENT_MODE === "production") { transformRemoveConsolePlugin = [ ["transform-remove-console", { exclude: ["error", "warn"] }] ]; } module.exports = { presets: ["@vue/app"], plugins: [...transformRemoveConsolePlugin] };
3.html-webpack-plugin
當使用 html-webpack-plugin
以後,咱們再也不須要手動處理bundle.js
的引用路徑了,由於這個插件,已經幫咱們自動建立了一個合適的script,而且,引用了正確的路徑
/*導入在內存中生成html頁面的插件,只要是插件,都必定要放到plugins節點中去 */ const htmlWebpackPlugin=require("html-webpack-plugin") //建立一個 內存中 生成html 頁面的插件 new htmlWebpackPlugin({ template:path.join(__dirname,'./src/index.html') filename:'index.html' })
//這個節點,用於配置 全部 第三方模塊 加載器 module:{ rules:[ {test:/\.css$,use:[]} ] }
4.prerender-spa-plugin
構建階段生成匹配預渲染路徑的 html 文件
npm install prerender-spa-plugin --save vue.config.js const PrerenderSPAPlugin = require('prerender-spa-plugin') const Renderer = PrerenderSPAPlugin.PuppeteerRenderer configureWebpack: config => { if (isProduction) { config.plugins.push( new CompressionWebpackPlugin({ algorithm: 'gzip', test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), threshold: 10240, minRatio: 0.8 }) ), config.plugins.push( new PrerenderSPAPlugin({ staticDir: path.join(__dirname, 'dist'), routes: [ // '/' '/login' // '/show', // '/websocket', // 'websocket2', // '/websocket3', // '/home', // 'abnormal/AbnormalStatis', // 'abnormal/FocusCrowd', // 'abnormal/FocusDetail', // 'abnormal/ScaleDetail', // 'abnormal/WarnSetup', // 'abnormal/WarnDetail', // 'abnormal/WarnLists', // 'abnormal/PsychMonth', // 'abnormal/PsychTeacher', // 'abnormal/PsychList', // 'laboratory/sports/MoveClock', // 'laboratory/sports/ClockDetail', // 'activity/ActList', // 'activity/ActForm' ], minify: { minifyCSS: true, // css壓縮 removeComments: true // 移除註釋 }, server: { port: 8080 }, //忽略打包錯誤 ignoreJSErrors: true, phantomOptions: '--web-security=false', maxAttempts: 10, renderer: new Renderer({ injectProperty: '__PRERENDER_INJECTED', inject: { foo: 'bar' }, headless: false, renderAfterTime: 5000, renderAfterDocumentEvent: 'render-event' }) }) ) } }, main.js new Vue({ mounted() { document.dispatchEvent(new Event('render-event')) } }).$mount('#app')
tips:main.js
中的render-event
,要和renderAfterDocumentEvent:'render-event'
一一對應 ,publicPath
目前驗證必須是/ 不能自定義文件夾