前端面試題—vue部分詳解
- 單頁面應用:在一個頁面跳來跳去,不重新載入頁面
- vue 特點:漸進式 框架 雙向資料繫結
- 雙向資料繫結:檢視改變 資料自動更新;資料更新 檢視自動改變
- 漸進式:vue vue-router路由 vuex axios
- 框架:自己寫的程式碼被框架呼叫(庫:自己呼叫庫的程式碼)
- 宣告式
安裝vue
cmd命令
npm i vue
yarn add vue
vue核心實現方法
var obj={} Object.defineProperty(obj,'name',{ value:'xhufeng', configurable:true,//是否可刪 writable:true,//是否可寫 enumerable:true,//是否可列舉(迴圈) set(val){ //只要外界給name賦值,就會觸發該函式 //形參val就是外界賦予的值 }, get(){ return 123 } }) 複製程式碼
vue指令
指令都是行內屬性 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標籤,就不會出現多餘標籤
<body> <div id="app"> <h1>{{name}}</h1> <button @click='flag=!flag'>按鈕</button> <h2 v-show='flag'>hello</h2> <h2 v-show='!flag'>world</h2> <button @click='n=1'>1</button> <button @click='n=2'>2</button> <button @click='n=3'>3</button> <h3 v-if='n===1'>hello</h3> <h3 v-else-if="n===2">hahaha</h3> <h3 v-else>world</h3> </div> </body> </html> <script src="./node/node_modules/vue/dist/vue.js"></script> <script> let vm = new Vue({ el: '#app', data: { name: "珠峰", flag:true, n:1 }, methods: { fn() { } } }) </script> 複製程式碼
v-clock
需要配合css使用:解決小鬍子顯示問題
v-pre
跳過有這個指令的標籤及其子元素的編譯,按照原生程式碼編譯
vue物件
data中的屬性最終都新增到了例項上 屬性需要有get set,才能觸發檢視更新
let vm = new Vue({ el: '#app', data: { name: '劉琪', age:21, q:'<h1>haha</h1>', obj:{ a:123,//對於物件來說,新增一個屬性不會觸發檢視更新,只有改變屬性時才會觸發檢視更新 b:undefined, } } }).$mount('#app') //處理方式 //1.正常寫全要用到的屬性;先預留要用到的屬性 //2.整個物件的重新賦值 //3.$set()方法 vm.$set(vm.obj,'c','456') //4.增加一個無關變數t,每次修改完資料之後;重置t就可以了 複製程式碼
vue陣列
let vm = new Vue({ el: '#app', data: { ary: [1, 2, 3, 4] } }) vm.ary.length--; //能改變原有陣列,但不能觸發檢視更新,只有陣列原型上的變異方法可以觸發更新 //陣列變異方法:pop shift unshift push reverse splice sort 複製程式碼
vue 事件
<body> <div id="app"> {{ary}} <button @click='fn'>按鈕1</button> <button @click='fn(name,$event)'>按鈕2</button> <!-- $event是固定寫法,代表傳參事件物件 --> </div> </body> </html> <script src="./node/node_modules/vue/dist/vue.js"></script> <script> //事件繫結,用v-on:事件型別=‘函式’或者@事件型別=‘函式’ //函式一般是在methods中定義的 //對應的函式一般不帶小括號,預設傳參事件物件e //當我們需要傳參時,需要加小括號,小括號裡寫需要傳的引數;當只有小括號沒有傳參時,為undefined //el data methods 都是VUE規定死的屬性名 let vm = new Vue({ el: '#app', data: { ary: [1, 2, 3, 4], name:'zhufeng' }, methods: { fn: function (val,e) { console.log(val,e,this) } } }) //@kryup.13='fn'在按下回車的時候才會觸發該函式 </script> 複製程式碼
vue過濾器
全域性用filter,例項區域性使用filters 全域性過濾器要放在需要使用的例項的前面

vue計算屬性computed
- 於data同級別
- 語法同methods一樣
- 計算屬性的名字 不能跟 data 或 methods 中的名字重複
- 完全依賴於函式體中出現的屬性名,只在最初載入時和其中屬性名改變時執行,並不是像methods中的函式只要頁面更新就執行一次
- 不能傳參
- 非同步的無法處理
- 為了提高效能而存在

vue監聽屬性
- 當且僅當監聽的屬性(例如:name)發生變化時會執行函式
- 可以處理非同步
- 下面這種寫法不能監聽引用資料型別的內部變化
watch:{ name(newV,oldV){ clearTimeout(this.timer) this.timer=setTimeout(() => { if (newV.length > 5) { this.msg2 = '名字太長' }else{ this.msg2 = '' } }, 500) } } 複製程式碼
- 深度監聽需要用下面這種語法
- 這種深度監聽在有get和set屬性時才會觸發監聽
watch:{ obj:{ handler(){ console.log(1111) }, deep:true } } 複製程式碼
directives自定義指令

一個指令定義物件可以提供如下幾個鉤子函式 (均為可選):
- bind:只調用一次,指令第一次繫結到元素時呼叫。在這裡可以進行一次性的初始化設定。
- inserted:被繫結元素插入父節點時呼叫 (僅保證父節點存在,但不一定已被插入文件中)。
- update:所在元件的 VNode 更新時呼叫,但是可能發生在其子 VNode 更新之前。指令的值可能發生了改變,也可能沒有。但是你可以通過比較更新前後的值來忽略不必要的模板更新 (詳細的鉤子函式引數見下)。
- componentUpdated:指令所在元件的 VNode 及其子 VNode 全部更新後呼叫。
- unbind:只調用一次,指令與元素解綁時呼叫。
vue動畫
transition
- 把需要實現動畫的標籤用transition標籤包起來
- 只能對根元素有動效

transition-group
- tag指定外層包裹元素的tag型別;不寫,預設span
- duration控制vue設定的類名存在的時間

事件修飾符
.self .stop .prevent .once .capture .passive
表單修飾符
.number .trim
生命週期

let vm = new Vue({ el:'#app', // template:'<h1>哈哈哈</h1>', data:{ name:"珠峰" }, // 生命週期鉤子函式 就是VUE規定的一些在固定階段執行的函式 // 語法上 跟 data和el、methods等 同級 beforeCreate(){ // 創造之前 // 不能獲取data和methods裡的資料 console.log('beforeCreate'); debugger; }, created(){ // 能獲取data和methods裡的資料 // 一般把ajax請求的傳送寫到這裡 }, beforeMount() {}, mounted(){ // 在此時DOM已經渲染完成 }, beforeUpdate(){ // 在檢視更新時會觸發其中函式 // 函式在檢視更新前執行 }, updated(){ // 在檢視更新時會觸發其中函式 // 函式在檢視更新後執行 // 不要寫會觸發檢視更新的程式碼 }, beforeDestroy(){}, destroyed(){} }) vm.$destory();//手動銷燬該例項,雙向資料繫結沒了 複製程式碼
元件
- 劃分比較明細,複用率比較高
- 功能性元件 頁面級元件
- 全域性元件 區域性元件
- template模板中只能有一個根元素
全域性元件的註冊
- 必須寫到根元件(根例項)的前面
//全域性元件的定義 Vue.component('qqq',{ template:'<i>hello 小聰子</i>' }) 複製程式碼
<body> <div id="app"> <h1>{{name}}</h1> <aaa></aaa> <aaa></aaa> <my-name></my-name> <!-- 不支援駝峰式命名 --> </div> </body> <template id='qqq'> <div> <input type="text" v-model='name'> <h1><i>{{name}}</i></h1> </div> </template> <script> //全域性元件的定義 //使用時只要把元件名當作標籤使用即可 Vue.component('aaa', { //沒有el屬性,有template屬性,data是個函式,並且返回一個物件 //template就是qqq標籤要去展示的內容 //template有且只能有一個根元素 template: '#qqq', data() { return { name: 'zhufeng' } }, created() { console.log(this.name) } }) Vue.component('myName', { template: `<h2>My name is </h2>`, data() { return { } }, }) let vm = new Vue({ el: '#app', data: { name: "珠峰" } }) </script> 複製程式碼
區域性元件的註冊
- 區域性元件只能使用在此之前宣告的區域性元件作為子元件
<body> <div id="app"> <h1>{{name}}</h1> <son></son> <parent></parent> </div> </body> <template id="opp"> <h2>ninininini</h2> </template> <template id="o"> <h2>小聰子<son></son></h2> </template> <script> let son = { template: '#opp', data() { return { } } } let parent = { template: '#o', data() { return { } }, components: { son } } let vm = new Vue({ el: '#app', data: { name: "珠峰" }, components: { son, parent: parent } }) </script> 複製程式碼
元件的資料傳輸
父傳子
過程
- 1.通過v-bind繫結屬性,把相應的資料傳遞給子元件
- 2.子元件通過props接收傳進來的資料
注意事項
- 父傳子是單向資料流,不能從子元件修改父元件的資料
- 但如果是引用資料型別,不修改地址,只改變內容,可以改變
- props可以是陣列,也可以物件
- props中自定義屬性的引數
-
- 1.default:預設值 複製程式碼
-
- 2.type:規定此屬性的資料型別 複製程式碼
- 可以通過例項
this.$parent
呼叫父元件的資料和方法(不推薦)
<body> <div id="app"> <h1>{{name}}</h1> <input type="text" v-model='name'> <son :name='name'></son> </div> </body> <template id="o"> <div> <h3>{{name}}</h3> <button @click='fn'> 這個按鈕點選了{{n}}次</button> </div> </template> <script> let son = { template: '#o', data() { return { n: 0 } }, methods: { fn() { this.n++ } }, props:['name'] } let vm = new Vue({ el: '#app', data: { name: "珠峰" }, components: { son, } }) </script> 複製程式碼
子傳父
本質上是父元件使用子元件的資料
官方過程
this.$emit('自定義事件名',this.qqq)
也可以在父元件中通過 this.$children[i]
呼叫子元件的資料及方法 也可以在父元件中通過 this.$refs.son
呼叫子元件的方法
插槽
在template模板中寫入 <slot></slot>
,可顯示在使用元件時元件名標籤內部內容
具名插槽
在slot標籤中的name屬性是控制要去顯示哪一部分的一個功能 不寫時,預設default,全部顯示 name對應的的是 slot='qqq'
的部分

模板中若有與name值對應的元素,則slot標籤包含的內容不會顯示出來;反之,可以顯示
子父元件的mounted
執行順序

動態元件component

keep-alive
-在沒有keep-alive時,component元件是銷燬舊的,重新渲染新的 -加上keep-alive後,動態元件有快取機制,不會銷燬舊的
<keep-alive> <component :is='son'></component> </keep-alive> 複製程式碼
vue-router
vue-router是vue的路由外掛
基本用法
- 步驟
- 1、宣告元件
- 2、編寫路由對映表
- 3、把編輯好的對映表注入到router例項中
- 4、把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: "珠峰" }, router, }) </script> 複製程式碼
傳參
- 提供了兩種傳參方式
- 1、query傳參(問號傳參)
- 路由對映表不用改動
:to={path:'',query:{}}
或者:to={name:'',query:{}}
- 2、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' } ] 複製程式碼
vuex
是一個能方便vue例項及其元件傳輸資料的外掛 方便傳輸資料,作為公共儲存資料的一個庫
基本用法
- 步驟
- 1、建立一個vuex例項
- 2、在根元件中註冊一下
- 3、註冊後,根元件及其一下的區域性或全域性元件可使用vuex例項中的資料方法,多個元件使用同一套規則時,我們可以把這套規則單獨拎出來寫在vuex例項中通用
方法彙總
state
類似vue例項中的data,儲存資料 在vue例項中用 this.$store.state
呼叫state裡的資料 使用 ...Vuex.mapStore(['count'])
將其資料放入computed中
mutations
官方提供的唯一改資料的方法 其中必須是同步函式 通過 commit
來呼叫mutations中的函式 其中函式最少有一個引數 state
,最多兩個引數另加 val
(呼叫時的傳參) 使用 ...Vuex.mapMutations(['mu_add'])
將其函式放入methods中
actions
可以寫非同步函式,一般多用於觸發ajax請求 不能直接用於修改state中的資料,需要通過其中函式預設的第一個實參obj,用 obj.commit('mu_')
來呼叫mutations中的函式來修改資料 使用 ...Vuex.mapActions(['ac_add'])
將其函式放入methods中
getters
類似vue例項中的計算屬性,儲存資料 使用 ...Vuex.mapGetters(['remove'])
將其函式放入computed中
//1、創造一個vuex例項 //2、把創造的例項放到根例項中 //使用this.$store.state let son1 = { template: `<div> <button @click='add'>增加</button> <button @click='mu_add(100)'>增加</button> <button @click='add2(100)'>2增加</button> <h2>{{count}}</h2> <h2>{{qqq}}</h2> </div>`, data() { return { } }, computed: { //兩種監聽vuex資料的寫法 // myCount(){ //return this.$store.state.count // } ...Vuex.mapState(['count', 'qqq']) }, methods: { add() { // this.$store.state.count++ // this.$store.commit('mu_add', 1) this.mu_add(10) }, ...Vuex.mapMutations(['mu_add']), add2() { this.$store.dispatch('ac_add', 22) //dispatch 觸發的是actions裡的函式 //commit觸發的是mutations裡的函式 } } } let son2 = { template: `<div> <button @click='remove'>減少</button> <h2>{{$store.state.count}}</h2> </div>`, methods: { remove() { this.$store.commit('mu_remove', 1) } }, } let store = new Vuex.Store({ state: { count: 0, qqq: 12 }, mutations: { mu_add(state, val = 1) { console.log(arguments) //第一個實參是預設傳的state //第二個實參是自己傳的引數 //一共只有一個或兩個實參 state.count += val }, mu_remove(state, val = 1) { console.log(arguments) //第一個實參是預設傳的state //第二個實參是自己傳的引數 //一共只有一個或兩個實參 state.count -= val } }, actions: { ac_add(obj,n) { //obj是vuex封裝好的一個物件,裡邊提供了commit方法 obj.commit('mu_add',n) console.log(arguments) } } //mutations中必須是同步函式,actions同步非同步都行 //想要修改state裡的資料只能用commit來呼叫mutations裡的函式 }) let vm = new Vue({ el: '#app', store, data: { name: "珠峰" }, components: { son1, son2 }, created() { console.log(this) }, }) 複製程式碼
==========================================================
前端小白,第一次發文,歡迎評論指正!