(三)Vue使用
Vue使用
- 概述
- 面試題
- Vue基本使用
- 模板(指令、插值)
- computed和watch
- class和style
- 條件渲染
- 循環(列表)渲染
- 事件
- 表單
- 組件
- props和$emit
- 組件間通訊-自定義事件
- 生命周期
- 單個組件
- 父子組件
- 高級特性
- 自定義v-model
- refs與$nextTick
- slot
- 基本使用
- 作用域插槽
- 具名插槽
- 動態組件
- 異步組件
- keep-alive
- mixin
- mixin問題
- Vuex使用
- Vuex基本概念
- 用于Vue組件
- Vue-router使用
- Vue-router路由模式
- Vue-router路由配置
概述
基本使用,組件使用—常用,必須會
高級特性—不常用,但體現深度
Vuex和Vue-router的使用
面試題
v-show和v-if的區別
為何v-for中要用key
描述Vue組件生命周期(有父子組件的情況)
Vue組件如何通訊
描述組件渲染和更新的過程
雙向數據綁定v-model的實現原理
Vue基本使用
日常使用,必須掌握,面試必考(不一定會考)
梳理知識點,從冗長的文檔中摘出考點和重點
考察形式不限(參考后面的面試真題),但都在范圍之內
模板(指令、插值)
插值、表達式
指令、動態屬性
v-html:會有XSS風險,會覆蓋子組件
computed和watch
computed有緩存,data不變則不會重新計算
watch如何深度監聽
watch監聽引用類型,拿不到oldVal
class和style
使用動態屬性
使用駝峰式寫法
條件渲染
v-if v-else的用法,可使用變量,也可以使用===表達式
v-if和v-show的區別
v-if和v-show的使用場景:切換頻繁使用v-show
v-show和v-if都能控制元素的顯示和隱藏。
v-show本質就是通過設置css中的display設置為none,控制隱藏,無論true或者false初始都會進行渲染,因此切換開銷比較小,初始開銷較大
v-if是動態的向DOM樹內添加或者刪除DOM元素,因為懶加載,初始為false時,不會渲染,因此初始渲染開銷較小,切換開銷比較大,要不停的銷毀和創建)
切換頻繁使用v-show
循環(列表)渲染
如何遍歷對象?—也可以用v-for
key的重要性。key不能亂寫(如random或者index)
v-for和v-if不能一起使用
因為v-for的優先級比v-if高,意味著v-if 將分別重復運行于每個 v-for 循環中,造成不必要的計算,影響性能
解決方法:將 v-if 置于外層元素 或在計算屬性中進行條件過濾
事件
event參數,自定義參數
事件修飾符,按鍵修飾符
【觀察】事件被綁定到哪里
表單
v-model
常見表單項textarea checkbox radio select
修飾符lazy number trim
當添加.lazy修飾符之后,相當于 雙向數據綁定不起作用了,主要用于控制數據同步的時機,改變input框中的內容并不會使數據發生變化,當輸入框失去焦點后觸發change事件,數據才更新
<template><div><p>輸入框: {{name}}</p><input type="text" v-model.trim="name"/><input type="text" v-model.lazy="name"/><input type="text" v-model.number="age"/><p>多行文本: {{desc}}</p><textarea v-model="desc"></textarea><!-- 注意,<textarea>{{desc}}</textarea> 是不允許的!!! --><p>復選框 {{checked}}</p><input type="checkbox" v-model="checked"/><p>多個復選框 {{checkedNames}}</p><input type="checkbox" id="jack" value="Jack" v-model="checkedNames"><label for="jack">Jack</label><input type="checkbox" id="john" value="John" v-model="checkedNames"><label for="john">John</label><input type="checkbox" id="mike" value="Mike" v-model="checkedNames"><label for="mike">Mike</label><p>單選 {{gender}}</p><input type="radio" id="male" value="male" v-model="gender"/><label for="male">男</label><input type="radio" id="female" value="female" v-model="gender"/><label for="female">女</label><p>下拉列表選擇 {{selected}}</p><select v-model="selected"><option disabled value="">請選擇</option><option>A</option><option>B</option><option>C</option></select><p>下拉列表選擇(多選) {{selectedList}}</p><select v-model="selectedList" multiple><option disabled value="">請選擇</option><option>A</option><option>B</option><option>C</option></select></div> </template><script> export default {data() {return {name: '雙越',age: 18,desc: '自我介紹',checked: true,checkedNames: [],gender: 'male',selected: '',selectedList: []}} } </script>組件
props和$emit
組件間通訊-自定義事件
//index.vue <template><div><Input @add="addHandler"/><List :list="list" @delete="deleteHandler"/></div> </template><script> import Input from './Input' import List from './List'export default {components: {Input,List},data() {return {list: [{id: 'id-1',title: '標題1'},{id: 'id-2',title: '標題2'}]}},methods: {addHandler(title) {this.list.push({id: `id-${Date.now()}`,title})},deleteHandler(id) {this.list = this.list.filter(item => item.id !== id)}},created() {// eslint-disable-next-lineconsole.log('index created')},mounted() {// eslint-disable-next-lineconsole.log('index mounted')},beforeUpdate() {// eslint-disable-next-lineconsole.log('index before update')},updated() {// eslint-disable-next-lineconsole.log('index updated')}, } </script> //Input.vue <template><div><input type="text" v-model="title"/><button @click="addTitle">add</button></div> </template><script> import event from './event'export default {data() {return {title: ''}},methods: {addTitle() {// 調用父組件的事件this.$emit('add', this.title)// 調用自定義事件event.$emit('onAddTitle', this.title)this.title = ''}} } </script> //event.js import Vue from 'vue'export default new Vue() //List.vue <template><div><ul><li v-for="item in list" :key="item.id">{{item.title}}<button @click="deleteItem(item.id)">刪除</button></li></ul></div> </template><script> import event from './event'export default {// props: ['list']props: {// prop 類型和默認值list: {type: Array,default() {return []}}},data() {return {}},methods: {deleteItem(id) {this.$emit('delete', id)},addTitleHandler(title) {// eslint-disable-next-lineconsole.log('on add title', title)}},created() {// eslint-disable-next-lineconsole.log('list created')},mounted() {// eslint-disable-next-lineconsole.log('list mounted')// 綁定自定義事件event.$on('onAddTitle', this.addTitleHandler)},beforeUpdate() {// eslint-disable-next-lineconsole.log('list before update')},updated() {// eslint-disable-next-lineconsole.log('list updated')},beforeDestroy() {// 及時銷毀,否則可能造成內存泄露event.$off('onAddTitle', this.addTitleHandler)} } </script>生命周期
單個組件
- 掛載階段(beforeCreate、created、beforeMount、mounted)
- 更新階段(beforeUpdate、updated)
- 銷毀階段(beforeDestory、destroyed )
created和mounted區別
created把vue示例給初始化,只是存在js內存模型的內存變量而已,并沒有開始渲染;
mounted組件真正在網頁上匯聚完成了,頁面渲染完成了
beforeDestory上可以做什么
解除綁定,銷毀子組件以及事件監聽器
父子組件
創建初始化vue實例是從外到內,只有父組件初始化完才能初始化子組件
渲染是從內到外,只有把子組件渲染完父組件才能渲染完
beforeUpdate:更新的時候父組件的data首先被修改,首先執行beforeUpdate
updated:只有子組件更新完了父組件才能更新完
渲染過程:父組件掛載完成一定是等子組件都掛載完成后,才算是父組件掛載完,所以父組件的mounted在子組件mouted之后。父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
子組件更新過程:
影響到父組件: 父beforeUpdate -> 子beforeUpdate->子updated -> 父updated
不影響父組件: 子beforeUpdate -> 子updated
父組件更新過程:
影響到子組件: 父beforeUpdate -> 子beforeUpdate->子updated -> 父updated
不影響子組件: 父beforeUpdate -> 父updated
銷毀過程:父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed
不管是哪種情況,都一定是父組件等待子組件完成后,才會執行自己對應完成的鉤子
高級特性
//index.vue <template><div><p>vue 高級特性</p><hr><!-- 自定義 v-model --><!-- <p>{{name}}</p><CustomVModel v-model="name"/> --><!-- nextTick --><!-- <NextTick/> --><!-- slot --><!-- <SlotDemo :url="website.url">{{website.title}}</SlotDemo> --><!-- <ScopedSlotDemo :url="website.url"><template v-slot="slotProps">{{slotProps.slotData.title}}</template></ScopedSlotDemo> --><!-- 動態組件 --><!-- <component :is="NextTickName"/> --><!-- 異步組件 --><!-- <FormDemo v-if="showFormDemo"/><button @click="showFormDemo = true">show form demo</button> --><!-- keep-alive --><!-- <KeepAlive/> --><!-- mixin --><MixinDemo/></div> </template><script> // import CustomVModel from './CustomVModel' // import NextTick from './NextTick' // import SlotDemo from './SlotDemo' // import ScopedSlotDemo from './ScopedSlotDemo' // import KeepAlive from './KeepAlive' import MixinDemo from './MixinDemo'export default {components: {// CustomVModel// NextTick// SlotDemo,// ScopedSlotDemo,// FormDemo: () => import('../BaseUse/FormDemo'),// KeepAliveMixinDemo},data() {return {name: '雙越',website: {url: 'http://imooc.com/',title: 'imooc',subTitle: '程序員的夢工廠'},// NextTickName: "NextTick",showFormDemo: false}} } </script>自定義v-model
//index.vue <template><div><!-- 自定義 v-model --><p>{{name}}</p><CustomVModel v-model="name"/></div> </template><script> import CustomVModel from './CustomVModel'export default {components: {CustomVModel},data() {return {name: '雙越',}} } </script> //CustomVModel.vue <template><!-- 例如:vue 顏色選擇 --><input type="text":value="text1"@input="$emit('change1', $event.target.value)"><!--1. 上面的 input 使用了 :value 而不是 v-model2. 上面的 change1 和 model.event 要對應起來3. text1 屬性對應起來--> </template><script> export default {model: {prop: 'text1', // 對應 props text1event: 'change1'},props: {text1: String,default() {return ''}} } </script>refs與$nextTick
Vue是異步渲染(原理部分會詳細講解)
data改變之后,DOM不會立刻渲染
$nextTick會在DOM渲染之后被處罰,以獲取最新DOM節點
slot
基本使用
//index.vue <template><div><!-- slot --><SlotDemo :url="website.url">{{website.title}}</SlotDemo></div> </template><script> import SlotDemo from './SlotDemo'export default {components: {SlotDemo},data() {return {website: {url: 'http://imooc.com/',title: 'imooc',subTitle: '程序員的夢工廠'},}} } </script> //SlotDemo.vue <template><a :href="url"><slot>默認內容,即父組件沒設置內容時,這里顯示</slot></a> </template><script> export default {props: ['url'],data() {return {}} } </script>作用域插槽
//index.vue <template><div><ScopedSlotDemo :url="website.url"><template v-slot="slotProps">{{slotProps.slotData.title}}</template></ScopedSlotDemo></div> </template><script> import ScopedSlotDemo from './ScopedSlotDemo'export default {components: {ScopedSlotDemo},data() {return {website: {url: 'http://imooc.com/',title: 'imooc',subTitle: '程序員的夢工廠'},}} } </script> //ScopedSlotDemo.vue <template><a :href="url"><slot :slotData="website">{{website.subTitle}} <!-- 默認值顯示 subTitle ,即父組件不傳內容時 --></slot></a> </template><script> export default {props: ['url'],data() {return {website: {url: 'http://wangEditor.com/',title: 'wangEditor',subTitle: '輕量級富文本編輯器'}}} } </script>具名插槽
動態組件
:is="component-name"用法
需要根據數據,動態渲染的場景,即組件類型不確定
比如一個新聞詳情頁,可能包含text、image、video組件,而且排序展示可能不一致
異步組件
import()函數
按需加載,異步加載大組件
keep-alive
緩存組件
頻繁切換,不需要重復渲染
Vue常見性能優化
點擊A-B-C-A-B-C
未加keep-alive前
加keep-alive后,離開不會destroyed,再次加載不會mounted
mixin
多個組件有相同的邏輯,抽離出來
mixin并不是完美的解決方案,會有一些問題
Vue 3 提出的Composition API旨在解決這些問題
mixin問題
變量來源不明確,不利于閱讀
多mixin可能會造成命名沖突
mixin和組件可能出現多對多的關系,復雜度較高
Vuex使用
面試考點并不多(因為熟悉Vue之后,vuex沒有難度)
但基本概念,基本使用和API必須掌握
可能會考察state的數據結構設計(后面會講)
Vuex基本概念
state
getters
action
mutation
異步操作在Actions里進行
用于Vue組件
dispatch
commit
mapState
mapGetters
mapActions
mapMutations
Vuex 是專門為 Vue.js 設計的狀態管理庫,簡單地說就是采用全局單例模式,將組件的共享狀態抽離出來管理,使組件樹中的每一個位置都可以獲取共享的狀態(變量)或者觸發行為。實現響應式的全局變量
state–狀態,在store實例中注冊state;在組件中使用store.state訪問
getters–類似計算屬性,對store中某個屬性相同的處理操作抽出出來,做了一個公共的處理,組件中通過store.getters調用
action–異步更改狀態,參數有context和payload,context.state獲取store變量,context.commit觸發mutation,提交mutation去修改state,組件中使用this.store.dispatch調用
mutation–更改store中狀態的唯一方法,參數有state和payload,不能包含異步操作,組件中使用this.$store.commit調用
輔助函數:mapState、mapMutations、mapGetters、mapActions,它們的使用我們可以配合ES6的展開運算符將其與局部計算屬性或方法混合使用
import {mapState、mapMutations、mapGetters、mapActions} from ‘vuex’ compoted:{ ...mapState({}) } compoted:{ ...mapGetters({}) } methods:{ ...mapActions({}) } methods:{ ...mapMutations({}) }Vue-router使用
面試考點并不多(前提是熟悉Vue)
路由模式(hash、H5 history)
路由配置(動態路由、懶加載)
Vue-router路由模式
hash模式(默認),如http://abc.com/#/user/10
H5 history模式,如http://abc.com/user/20
后者需要server端支持,因此無特殊需求可選擇前者
H5 history模式404不會跳轉,需要配置404情況
Vue-router路由配置
總結
- 上一篇: Input placeholder属性样
- 下一篇: (四)Vue原理