Vue的Key屬性,v-for和v-if,v-if/v-show,v-pre不渲染,v-once只渲染一次
- 2019 年 11 月 5 日
- 筆記
key屬性 為什麼要加
key — api 解釋
key的特殊屬性主要用在vue的虛擬dom演算法,如果不適用key,vue會使用一種最大限度減少動態元素並且儘可能的嘗試修復/再利用相同類型元素的演算法。使用Key,它會基於Key的變化重新排列元素順序,並且會移除Key不存在的元素。
v-for為什麼要加Key
<div id="app"> <div> <input type="text" v-model="name"> <button @click="add">添加</button> </div> <ul> <li v-for="(item, i) in list"> <input type="checkbox"> {{item.name}} </li> </ul> <script> // 創建vue實例,得到viewmodel var vm = new Vue({ el: '#app', data: { name: '', newId: 3, list: [ {id:1,name''} ] }, methods: { add() { this.list.unshift({ id: ++this.newId, name: this.name }) this.name="" } } }); </script> </div>
有key
<div id="app"> <div> <input type="text" v-model="name"> <button @click="add">添加</button> </div> <ul> <li v-for="(item, i) in list" :key="item.id"> <input type="checkbox"> {{item.name}} </li> </ul> <script> // 創建 Vue 實例,得到 ViewModel var vm = new Vue({ el: '#app', data: { name: '', newId: 3, list: [ { id: 1, name: '' }, { id: 2, name: '' }, { id: 3, name: '' } ] }, methods: { add() { //注意這裡是unshift this.list.unshift({ id: ++this.newId, name: this.name }) this.name = '' } } }); </script> </div>

file

file

file

file

file
為什麼使用v-for時必須添加唯一的key?
const list = [ { id: 1, name: 'test1', }, { id: 2, name: 'test2', }, { id: 3, name: 'test3', }, ]
<div v-for="(item, index) in list" :key="index" >{{item.name}}</div>
const list = [ { id: 1, name: 'test1', }, { id: 2, name: 'test2', }, { id: 3, name: 'test3', }, { id: 4, name: '我是在最後添加的一條數據', }, ]
const list = [ { id: 1, name: 'test1', }, { id: 4, name: '我是插隊的那條數據', } { id: 2, name: 'test2', }, { id: 3, name: 'test3', }, ]
兩個相同的組件產生類似的dom結構,不同的組件產生不同的dom結構。
同一層級的一組節點
特殊特性 key
預期:number | string
key的特殊屬性主要用在vue的虛擬dom演算法,在新舊nodes對比時辨識vnodes。
<ul> <li v-for="item in items" :key="item.id"></li> </ul>
它可以用於強制替換元素,組件而不是重複使用它。
完整地觸發組件的生命周期鉤子 觸發過渡
<transition> <span :key="text">{{text}}</span> </transition>
ref被用來給元素或子組件註冊引用資訊,引用資訊將會註冊在父組件的$refs對象上。如果在普通的dom元素上使用,引用指向就是dom元素,如果用在子組件上,引用就指向組件實例:
<p ref="p"> hello </p> <child-component ref="child"></child-component>
v-for用於元素或組件的時候,引用資訊將包含dom節點或組件實例的數組
is 用於動態組件且基於dom內模板的限制來工作
<component v-bind:is="currentView"></compoent> <table> <tr is="my-row"></tr> </table>
data: function () { return { todos: [ { id: 1, text: '學習使用 v-for' }, { id: 2, text: '學習使用 key' } ] } }
<ul> <li v-for="todo in todos"> {{ todo.text }} </li> </ul>
<ul> <li v-for="todo in todos" :key="todo.id" > {{ todo.text }} </li> </ul>
永遠不要把 v-if 和 v-for 同時用在同一個元素上。
為了過濾一個列表中的項目
v-for="user in users" v-if="user.isActive"
v-for="user in users" v-if="shouldShowUsers"
<ul> <li v-for="user in users" v-if="user.isActive" :key="user.id"> {{ user.name }} </li> </ul>
this.users.map(function (user) { if (user.isActive) { return user.name } })
computed: { activeUsers: function() { return this.user.filter(function (user) { return user.isActive }) } }
<ul> <li v-for="user in activeUsers" :key="user.id"> {{user.name}} </li> </ul>
<ul> <li v-for="user in users" v-if="shouldShowUsers" :key="use.id"> {{user.name}} </li> </ul>
<ul> <li v-for = "user in users" v-if="user.isActive" :key="user.id"> {{user.name}} </li> </ul> <ul> <li v-for="user in users" v-if="shouldShowUsers" :key="user.id"> {{user.name}} </li> </ul>
<ul> <li v-for="user in activeUsers" :key="user.id" > {{ user.name }} </li> </ul> <ul v-if="shouldShowUsers"> <li v-for="user in users" :key="user.id" > {{ user.name }} </li> </ul>
<ul> <li v-for="user in activeUsers" :key="user.id" > {{ user.name }} </li> </ul> <ul v-if="shouldShowUsers"> <li v-for="user in users" :key="user.id" > {{ user.name }} </li> </ul>
<template> <button class="btn btn-close">X</button> </template> <style> .btn-close { background-color: red; } </style>
<template> <button class="button button-close">X</button> </template> <!-- 使用 `scoped` 特性 --> <style scoped> .button { border: none; border-radius: 2px; } .button-close { background-color: red; } </style> <template> <button :class="[$style.button, $style.buttonClose]">X</button> </template> <!-- 使用 CSS Modules --> <style module> .button { border: none; border-radius: 2px; } .buttonClose { background-color: red; } </style>
<template> <button :class="[$style.button, $style.buttonClose]">X</button> </template> <!-- 使用 CSS Modules --> <style module> .button { border: none; border-radius: 2px; } .buttonClose { background-color: red; } </style>
<template> <button class="c-Button c-Button--close">X</button> </template> <!-- 使用 BEM 約定 --> <style> .c-Button { border: none; border-radius: 2px; } .c-Button--close { background-color: red; } </style>
虛擬Dom以及Key屬性的作用

file

file

file

file

file
<template> <div id="app"> <input v-model="message" > <input :value="message" @input="handleChange"> {{message}} {{message * message}} <div :id="message"></div> <todo-list> <todo-item @delete="handleDelete" v-for="(item, index) in list" :key="index" :title="item.title" :del=""> <template v-slot:pre-icon="{value}"> <span>{{value}}</span> </template> </todo-item> </todo-list>
vue是如果觸發組件更新的

file

file

file
<script> export default{ name: " ", props: { info: Object, name: String, list: Array }, data(){ return { a: ' ', b: ' ' }; }, updated() { console.log(' '); }, methods: { handleBChange() { this.b = "vue" +Date.now(); } } };

file
合理應用計算屬性和偵聽器
減少模板中計算邏輯 數據快取 依賴固定的數據類型(響應式數據)
計算屬性:computed
<p>{{ reversedMessage1 }}</p> <p>{{ reversedMessage2() }}</p> <p> {{ now }} </p> <button @click="() => $forceUpdate()">forceUpdate</button> <br/> <input v-model="message"/> export default { data() { return { message: 'hello' }; }, computed: { // 計算屬性的getter reversedMessage1: function() { return this.message .split("") .reverse() .join(""); }, now: function() { return Date.now(); } }, methods: { reversedMessage2: function() { return this.message .split("") .reverse() .join(""); }
偵聽器watch 更加靈活,通用 watch中可以執行任何邏輯,如函數節流,ajax非同步獲取數據
<div> {{$data}} <br/> <button @click="() => (a += 1)"><button> </div> wxport default { data: function() { return { a: 1, b: {c:2,d:3}, e: { f: { g: 4 } }, h: [] }; }, watch: { a: function(val, oldVal) { this.b.c += 1; }, "b.c": function(val, oldVal) { this.b.d += 1; }, "b.d": function(val, oldVal) { this.e.f.g += 1; }
computed vs watch
computed能做的,watch都能做,反之不行 能computed的盡量用computed
<div> {{ fullName }} <div> firstName: <input v-model="firstName"/></div> <div> lastName: <input v-model="lastName"/></div> </div> export default { data: function() { return { firstName: 'foo', lastName: 'bar' }; }, computed: { fullName: function() { return this.firstName + " " + this.lastName; } }, watch: { fullName: function(val, oldVal) { console.log("new",val,oldVal); } }
vue的生命周期的應用場景和函數式組件
生命周期:
創建階段,更新階段,銷毀階段

file
創建階段: beforeCreate created beforeMount render mounted
更新階段 beforeUpdate render updated
銷毀階段 beforeDestory destoryed

file
創建階段: beforeCreate created beforeMount render mounted
初始化事件和生命周期 beforeCreate 數據觀測,屬性,偵聽器配置 created 模板編譯到render beforeMount render mounted 非同步請求,操作dom,定時器等

file
更新階段多次更新的階段
更新階段
beforeUpdate render updated
依賴數據改變或$forceUpdate強制刷新 beforeUpdate 移除已經添加的事件監聽器等萬萬不可更改 render updated 操作dom添加事件監聽器等萬萬不更改依賴數據

file
銷毀階段: beforedestory destoryed

file
watch: { start() { this.startClock(); } },

file
函數式組件: functional:true 無狀態,無實例,沒有this上下文,無生命周期
函數式組件:

file
vue指令的本質
v-text v-html v-show v-if v-else v-else-if v-for v-on v-bind v-model v-slot v-pre v-cloak v-once
自定義指令: bind inserted update componentUpdated unbind
生命周期鉤子
常用的高級特性provide/inject
解決的問題為組件的通訊問題

file
屬性,通訊 事件,通訊
如何優雅地獲取跨層級組件實例: 拒絕遞歸
引用資訊
<p ref="p">hello</p> <child-component ref="child"></child-component>

file

file
自動通知setXXXref 主動獲取getxxxref
<button @click="getEH3Ref"></button export default { components: { ChildrenB, ChildrenC, ChildrenD }, provide() { return { setChildrenRef: (name, ref) => { this[name] = ref; }, getChildrenRef: name => { return this[name]; }, getRef: () => { return this; } }; },
<ChildrenH v-ant-ref="c => setChildrenRef("childrenH", c)"/> export default { components: { ChildrenG, ChildrenH, ChildrenI }, inject: { setChildRef: { default: () = {} } } };
template和jsx之間的區別

file

file

file
如何在vue中使用vuex

file

file
import Vue from 'vue' import Vuex from 'vuex' import App from './App.vue' Vue.use(Vuex) Vue.config.productionTip = false const store = Vue.Store({ state: { count: 0, } }) new Vue({ store, render: h => h(App), }).$mount('#app')
increment({commit}) { setTimeout(()=>{ commit('increment') }, 3000) }
<template> <div id="app"> {{count}} </div> </template> <script> export default { name: 'app', computed: { count() { return this.$store.state.count } } } </script>
<button @click="$store.commit('increment', 2)">count++</button>
mutations: { increment(state, n) { state.count += n } }

file
vuex核心概念以及底層原理
核心概念 state->this.
store.getters.xxx取值
mutation->this.
store.dispatch("xxx")賦值
module
底層原理: State:提供一個響應式數據 Getter:藉助Vue的計算屬性computed來實現快取
mutation:更改state方法 action:觸發mutaion方法 module:Vue.set動態添加state到響應式數據中

file

file
vuex最佳實戰

file
使用常量替代mutation事件類型
// mutation-type.js export const SOME_MUTATION="SOME_MUTATION「 // store.js import Vuex from 'vues' import { SOME_MUTATION } from '' const store = new Vuex.Store({ state: { ... }, mutations { [SOME_MUTATION] (state) { } } })
傳統開發模式
www.xxx.com - index.html www.xxx.com/about -about.html

file
vue touter的使用場景
監聽url的變化,並在變化前後執行相應的邏輯
不同的url對應不同的不同的組件
提供多種方式改變Url的api
使用方式: 提供一個路由配置表,不同url對應不同組件的配置 初始化路由實例new VueRouter()
掛載到vue實例上 提供一個路由佔位,用來掛載Url匹配到的組件

file
選擇何種模式的路由以及底層原理
hash模式:丑,無法使用錨點定位

file
Nuxt解決了哪些問題?

file

file
Nuxt核心原理,SSR的核心原理

file

file
Ui組件對比 Element UI,ANT design vue,iview

file
提升開發效率
Vetur,ESLint,Prettier,Vue DevTools

file

file
Vuex是通過什麼方式提供響應式數據的?

file
擴展簡化版的min-vuex,實現getters,並實現Vuex的方式注入$store
計算屬性computed實現getters快取
beforeCreate中混入$store的獲取方式

file

file