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