属性
自定义属性:组件props中声明的属性原生属性:没有声明的属性,默认自动挂载到组件根元素上,设置inheritAttrs为false可关闭自动挂载特殊属性:挂载到组件根元素上,支持字符串、对象、数组等多种语法
事件
普通事件
@click @input @change @xxx等事件
this.$emit('eventName'...)出发
修饰符事件
@input.trim @click.stop @submit.prevent 等
一般用于原生HTML元素,自定义组件需要自行开发支持
插槽
普通插槽
slot="xxx">...
v-slot:xxx>...
作用域插槽
slot="xxx" slot-scope="props">...
v-slot:xxx="props">...
属性、事件、插槽完全都可以通过属性解决,大属性的概念
双向绑定与单项数据流
双向绑定:model与view互相更新 单项数据流:model更新view
Vue是单项数据流,非双向绑定
Vue的双向绑定不过是语法糖
Object.defineProperty是用来做响应式更新的,和双向绑定没关系
如何实现双向绑定(语法糖)
v-model="phoneInfo"
:zip-code.sync="zipCode"
/>
:phone-info="phoneInfo"
@change="val=>(phoneInfo = val)"
:zip-code.sync="zipCode"
@update:zipCode="val=>(zipCode = val)"
/>
虚拟Dom与Key属性
JQuery:Event ===> Element Vue:Event ====> State ====> Element
Virtual DOM
Virtual DOM Diff(对比同层节点比较):
如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。
如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。
场景1:移动
场景2:删除后新建
场景3:删除后新建
场景4:更新删除新建(无Key)
场景5:移动(有Key)
场景6:插入(有Key)
组件的数据来源分类
来自父元素的属性
来自组件自身的状态
来自状态管理器,如vuex,Vue.observable
计算属性及侦听器
计算属性 computed
减少模版中计算逻辑
数据缓存
依赖固定的数据类型(响应式)
侦听器 watch
更加灵活,通用
watch中可以执行任何逻辑,如函数节流、Ajax异步获取数据,甚至操作DOM
computed VS watch
computed能做的,watch都能做,反之则不行
能用computed的尽量用computed
函数式组件
functional:true
无状态、无实例、没有this上下文、无生命周期
export default {
name: 'functional-button',
functional: true,
render(createElement, context) {
return createElement('button', 'click me')
}
}
<template>
<FunctionalButton>
click me
FunctionButton>
template>
Vue自定义指令
生命周期
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
案例
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
<input v-focus>
template和JSX的对比以及它们的本质
template
模版语法(HTML的扩展)
数据绑定使用Mustache语法(双大括号)
优点:学习成本低、大量内置指令简化开发、组件作用域CSS
缺点:灵活性低
Message:{{ msg }}
JSX
Javascript 的语法扩展
数据绑定使用单引号
灵活灵活灵活
Message:{ this.msg }
template & JSX都是语法糖
Q&A
子组件为何不可以修改父组件传递的Prop,如果修改了,Vue是如何监控到属性的修改并给出警告的?
Vue是单项数据流的。Object.defineProperty()
this.$emit的返回值是什么?
返回值是 this
如果需要需要返回值可以使用回调参数
相同名称的插槽是合并还是替换
替换。
为什么不能用index作为key?
更新DOM性能问题
会引入状态bug问题(因为array改变后,index会动态的相应改变)
数组有哪些方式支持响应式更新,如不支持如何处理,底层原理如何实现的?
- 支持:push、pop、shift、unshift、splice、sort、reverse
- 不支持:filter、concat、slice
- 原理同样使用Object.defineProperty对数组方法进行改写
进行节流改造,即直到用户停止输入超过500毫秒后才更新 fullName
watch:{
firstName:function(val){
clearTimeout(this.firstTimeout);
this.firstTimeout = setTimeout(()=>{
this.fullName = val + '"" + this.lastName
},500)
}
}
只能用watch,无法使用computed
进阶生态
在Vue中使用vuex
//main.js
const store = new Vuex.Store({
state:{
count:0
},
mutations:{
INCREMENT(state){
state.count++
}
},
actions:{
increment(commit){
setTimeout(() => {
commit('INCREMENT')
}, 1000)
}
},
getters:{
doubleCount(state){
return state.count+2
}
}
})
//App.vue
<template>
<div id="app">
{{count}}
<br />
{{$store.getters.doubleCount}
<button @click="$store.commit('INCREMENT')">count++button>
<button @click="$store.dispatch('increment')">count++button>
div>
template>
...
computed:{
count(){
return this.$store.state.count
}
}
...
vuex核心概念及底层原理
State:state类似与组件中的data数据,而data只仅局部使用于该组件中,state数据是全局的可以再任何一个组件使用,并且我们可以在单个组件中修改state的数据。
Mutations:mutations 类似于组件里面的methods在mutations里面可以对state的数据进行修改。mutations必须是同步的。同步的意义在于这样每一个 mutation 执行完成后都可以对应到一个新的状态(和 reducer 一样),这样 devtools 就可以打个 snapshot 存下来。
Actions:actions 只是一个架构性的概念,并不是必须的,说到底只是一个函数。区分 actions 和 mutations 并不是为了解决竞态问题,而是为了能用 devtools 追踪状态变化。actions可以包含任意异步操作。
Getters: getters存放公共函数供组件调用,类似于组件中的过滤函数computed或者filters,缓存state的数据。
Module:Vue.set动态添加state到响应式数据中
实现原理(响应式数据)
import Vue from 'vue'
const Store = function Store (options={}){
const {state={},mutations={}} = options;
this._vm = new Vue({ // 将state放在Vue的data下,就变成了响应式的数据
data:{
$$state: state
}
})
this._mutations = mutations
}
Store.prototype.commit = function(type,payload){
if(this._mutations[type]){
this._mutations[type](this.state,payload)
}
}
Object.defineProperties(Store.prototype,{ // 将state的get重写,每次get值的时其实是访问_vm实例下state 的值
state:{
get:function(){
return this._vm._data.$$state
}
}
})
vuex辅助函数
State ---- this.$store.state.xxx ---- mapState 取值
Getter ---- this.$store.getters.xxx ---- mapGetters 取值
Mutation ---- this.$store.commit('xxx') ---- mapMutations 取值
Action ---- this.$store.dispatch('xxx') ---- mapActions 取值
computed: mapState({
products: state => state.products
})
// 等价于
computed: {
products(){
return this.$store.state.products
}
}
methods:mapAction('cart',{
'addProductToCart'
})
// 等价于
methods;{
addProductToCart(product){
this.$store.dispatch('cart/addProductToCart',product)
}
}
Vue-Router的使用场景
解决的问题
监听URL的变化,并在变化前后执行相应的逻辑
不同的URL对应不同的组件
提供多种方式改变URL的API(URL的改变不能导致浏览器刷新)
路由类型以及底层原理
类型
hash模式:丑,无法使用锚点定位
history模式:需要后端配合,IE9不兼容(可使用强制刷新处理)
底层原理
Nuxt
SPA模式缺点
不利于SEO 服务端渲染 SSR
首屏渲染时间长 预渲染 Prerendering
Nuxt的作用
静态站点
动态渲染
简化配置
SSR流程图
单元测试的使用
使用方式
jest or mocha
@vue/test-utils
sinon
*该笔记基于 Vue开发实战课程 整理
来自Jerry的blog
欢迎扫码看看这个 Flutter 课程