前端面試題—vue部分詳解

NO IMAGE

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-cloak

需要配合css使用:解決小鬍子顯示問題

v-pre

跳過有這個指令的標籤及其子元素的編譯,按照原生代碼編譯

vue對象

data中的屬性最終都添加到了實例上
屬性需要有get set,才能觸發視圖更新

     let vm = new Vue({
el: '#app',
data: {
name: 'liu',
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:'liu'
},
methods: {
fn: function (val,e) {
console.log(val,e,this)
}
}
})
//@kryup.13='fn'在按下回車的時候才會觸發該函數
</script>

vue過濾器

全局用filter,實例局部使用filters
全局過濾器要放在需要使用的實例的前面

前端面試題—vue部分詳解

vue計算屬性computed

  • 於data同級別
  • 語法同methods一樣
  • 計算屬性的名字 不能跟 data 或 methods 中的名字重複
  • 完全依賴於函數體中出現的屬性名,只在最初加載時和其中屬性名改變時運行,並不是像methods中的函數只要頁面更新就運行一次
  • 不能傳參
  • 異步的無法處理
  • 為了提高性能而存在
前端面試題—vue部分詳解

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自定義指令

前端面試題—vue部分詳解

一個指令定義對象可以提供如下幾個鉤子函數 (均為可選):

  • bind:只調用一次,指令第一次綁定到元素時調用。在這裡可以進行一次性的初始化設置。
  • inserted:被綁定元素插入父節點時調用 (僅保證父節點存在,但不一定已被插入文檔中)。
  • update:所在組件的 VNode 更新時調用,但是可能發生在其子 VNode 更新之前。指令的值可能發生了改變,也可能沒有。但是你可以通過比較更新前後的值來忽略不必要的模板更新 (詳細的鉤子函數參數見下)。
  • componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新後調用。
  • unbind:只調用一次,指令與元素解綁時調用。

vue動畫

transition
  • 把需要實現動畫的標籤用transition標籤包起來
  • 只能對根元素有動效
前端面試題—vue部分詳解

transition-group
  • tag指定外層包裹元素的tag類型;不寫,默認span
  • duration控制vue設置的類名存在的時間
前端面試題—vue部分詳解

事件修飾符

  • .self只點元素本身時才觸發事件
  • .stop阻止冒泡事件
  • .prevent阻止默認事件
  • .once對應函數只觸發一次
  • .capture在捕獲階段觸發二級綁定事件
  • .passive優先執行默認事件(滾動行為)

表單修飾符

  • .number轉化為數字,類似parse轉化
  • .trim去字符串前後空格

生命週期

前端面試題—vue部分詳解

    let vm = new Vue({
el:'#app',
// template:'<h1>哈哈哈</h1>',
data:{
name:"liu"
},
// 生命週期鉤子函數 就是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: 'liu'
}
},
created() {
console.log(this.name)
}
})
Vue.component('myName', {
template: `<h2>My name is </h2>`,
data() {
return {
}
},
})
let vm = new Vue({
el: '#app',
data: {
name: "liu"
}
})
</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: "liu"
},
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: "liu"
},
components: {
son,
}
})
</script>
子傳父

本質上是父組件使用子組件的數據

官方過程

  1. 通過自定義事件觸發父組件中的方法
  2. 再由子組件方法的執行通過this.$emit('自定義事件名',this.qqq)傳遞子組件的數據

也可以在父組件中通過this.$children[i]調用子組件的數據及方法
也可以在父組件中通過this.$refs.son調用子組件的方法

插槽

在template模板中寫入<slot></slot>,可顯示在使用組件時組件名標籤內部內容

具名插槽

在slot標籤中的name屬性是控制要去顯示哪一部分的一個功能
不寫時,默認default,全部顯示
name對應的的是slot='qqq'的部分

前端面試題—vue部分詳解

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

子父組件的mounted

執行順序

前端面試題—vue部分詳解

動態組件component

前端面試題—vue部分詳解

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: "liu"
},
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: "liu"
},
components: {
son1,
son2
},
created() {
console.log(this)
},
})

==========================================================

前端小白,第一次發文,歡迎評論指正!

相關文章

android圖片裁剪拼接實現(一):Matrix基本使用

關於我對於寫博客寫文章的理解

藉助系統自帶圖片裁剪集成圖片選擇以及7.0適配

面試題整理—CSS部分