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实例,得到viewmodelvar 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>

为什么使用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属性的作用

<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是如果触发组件更新的

<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(); }}};

合理应用计算属性和侦听器

减少模板中计算逻辑
数据缓存
依赖固定的数据类型(响应式数据)

计算属性: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: {// 计算属性的getterreversedMessage1: 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的生命周期的应用场景和函数式组件

生命周期:

创建阶段,更新阶段,销毁阶段

创建阶段:
beforeCreate
created
beforeMount
render
mounted

更新阶段
beforeUpdate
render
updated

销毁阶段
beforeDestory
destoryed

创建阶段:
beforeCreate
created
beforeMount
render
mounted

初始化事件和生命周期
beforeCreate
数据观测,属性,侦听器配置
created
模板编译到render
beforeMount
render
mounted
异步请求,操作dom,定时器等

更新阶段多次更新的阶段

更新阶段

beforeUpdate
render
updated

依赖数据改变或$forceUpdate强制刷新
beforeUpdate
移除已经添加的事件监听器等万万不可更改
render
updated
操作dom添加事件监听器等万万不更改依赖数据

销毁阶段:
beforedestory
destoryed

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

函数式组件:
functional:true
无状态,无实例,没有this上下文,无生命周期

函数式组件:

vue指令的本质

v-textv-htmlv-showv-ifv-elsev-else-ifv-forv-onv-bindv-modelv-slotv-prev-cloakv-once

自定义指令:
bind
inserted
update
componentUpdated
unbind

生命周期钩子

常用的高级特性provide/inject

解决的问题为组件的通信问题

属性,通信
事件,通信

如何优雅地获取跨层级组件实例:
拒绝递归

引用信息
<p ref="p">hello</p><child-component ref="child"></child-component>

自动通知setXXXref
主动获取getxxxref

<button @click="getEH3Ref"></buttonexport 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之间的区别

如何在vue中使用vuex

import Vue from 'vue'import Vuex from 'vuex'import App from './App.vue'Vue.use(Vuex)Vue.config.productionTip = falseconst 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 }}

vuex核心概念以及底层原理

核心概念
state->this.$store.state.xxx取值
getter->this.$store.getters.xxx取值

mutation->this.$store.commit("xxx")赋值
action->this.$store.dispatch("xxx")赋值

module

底层原理:
State:提供一个响应式数据
Getter:借助Vue的计算属性computed来实现缓存

mutation:更改state方法
action:触发mutaion方法
module:Vue.set动态添加state到响应式数据中

vuex最佳实战

使用常量替代mutation事件类型

// mutation-type.jsexport const SOME_MUTATION="SOME_MUTATION“// store.jsimport Vuex from 'vues'import { SOME_MUTATION } from ''const store = new Vuex.Store({state: { ... },mutations {[SOME_MUTATION] (state) {}}})

传统开发模式

www.xxx.com - index.htmlwww.xxx.com/about -about.html


vue touter的使用场景

监听url的变化,并在变化前后执行相应的逻辑

不同的url对应不同的不同的组件

提供多种方式改变Url的api

使用方式:
提供一个路由配置表,不同url对应不同组件的配置
初始化路由实例new VueRouter()

挂载到vue实例上
提供一个路由占位,用来挂载Url匹配到的组件

选择何种模式的路由以及底层原理

hash模式:丑,无法使用锚点定位

Nuxt解决了哪些问题?

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

Ui组件对比
Element UI,ANT design vue,iview

提升开发效率

Vetur,ESLint,Prettier,Vue DevTools

Vuex是通过什么方式提供响应式数据的?

扩展简化版的min-vuex,实现getters,并实现Vuex的方式注入$store

计算属性computed实现getters缓存

beforeCreate中混入$store的获取方式


若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。


请点赞!因为你们的赞同/鼓励是我写作的最大动力!

欢迎关注达达的简书!

这是一个有质量,有态度的博客