key属性
为何要加html
key -- api 解释vue
key的特殊属性主要用在vue的虚拟dom算法,若是不适用key,vue会使用一种最大限度减小动态元素而且尽量的尝试修复/再利用相同类型元素的算法。使用Key,它会基于Key的变化从新排列元素顺序,而且会移除Key不存在的元素。node
v-for为何要加Keyajax
<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>
为何使用v-for时必须添加惟一的key?vuex
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结构。api
同一层级的一组节点数组
特殊特性
key缓存
预期:number | stringapp
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>
<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: { // 计算属性的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的生命周期的应用场景和函数式组件
生命周期:
建立阶段,更新阶段,销毁阶段
建立阶段:
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-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
解决的问题为组件的通讯问题
属性,通讯
事件,通讯
如何优雅地获取跨层级组件实例:
拒绝递归
引用信息
<p ref="p">hello</p> <child-component ref="child"></child-component>
自动通知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之间的区别
如何在vue中使用vuex
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 } }
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.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
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的获取方式
若本号内容有作得不到位的地方(好比:涉及版权或其余问题),请及时联系咱们进行整改便可,会在第一时间进行处理。
这是一个有质量,有态度的博客