­

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