一、vue-cli的安装
1、npm install -g @vue/cli
2、vue create my-app
3、cd my-app
4、npm run serve
二、插槽应用
1、插槽:可以设置自定义样式
`
xxx.vue中书写
<template v-slot:item=itemProps>
<span style="{fontSize:20px;,color:itemProps.checked?'red':'blue'}">{{item}}</span>
</template>
应用:在相应的组建中书写
<li class="item">
<input type="checkbox" v-model="checked"/ >
<slot name="item" v-bind="{checked}"></slot>
</li>
`
三、vue组件的核心概念
1、属性:
自定义属性props:组件props中声明的属性
props:['name','type','list']
或者:
name:String,
type:{
validator:function(value){
return ['success','warning','danger'].includes(value)
}
},
list:{
type:Array,
default:() => []
}
原生属性attr: 没有声明的属性,默认自动挂载到组件根元素上,设置inheritAttrs为false可以关闭自动挂载
特殊属性class、style:挂载到组件根元素上,支持字符串、对象、数组等多种语法
2、事件:
普通事件:@click @input @change @xxx等事件,通过this.$emit('xxx',...)触发
<input :value="name" @click='handleChange' />
handleChange(e){
this.$emit('change',e.target.value)
}
修饰符事件:@input.trim @click.stop @submit.prevent等,一般用于原生HTML元素,自定义组件需要自行开发支持
3、插槽:
普通插槽:<template slot='xxx'>...</template> 或者 <template v-slot:xxx>...</template>
作用域插槽:<template slot='xxx' slot-scope='props'>...</template>
<template v-slot:xxx='prop'>...</template>
对应插槽组件应用:
<slot />
<slot name='title' />
<slot name='item' v-bind="{ value:'vue' }" />
大属性的应用:
<VNodes :vnodes="slotDefault" />
export default {
components:{
VNodes:{
function: true,
render:(h,ctx) => ctx.props.vnodes
}
},
}
四、双向绑定、单向数据流
Vue是单向数据流,不是双向绑定
Vue的双向绑定不过是语法糖
Object.defineProperty是用来做响应式更新的,和双向绑定没关系
v-model语法糖:
<PersonalInfo v-model='phoneInfo' :zip-code.sync='zipCode'/>
<PersonalInfo
:phone-info='phoneInfo'
@change='val => (phoneInfo = val)'
:zip-code='zipCode'
@updata:zipCode='val => (zipCode = val)'
/>
五、虚拟DOM及key属性作用:
1、数据驱动:操作虚拟DOM
2、数据来源(单向的)
来自父元素的属性
来自组件自身的状态 data
来自状态管理器,如vuex Vue.observable
3、数据响应式更新
必备条件:
(1)template模板中应用了此数据、
(2)data return中返回了相应的字段。
如template模板中应用了<div>{{msg.name}}</div>,
并且data return回来的数据中声明了 msg:{name:null,info:null},这样才能实现响应式更新
六、计算属性和侦听器
1、计算属性computed
减少模板中逻辑运算
数据缓存
依赖固定的数据类型(响应式数据)
2、侦听器 watch
更加灵活、通用
watch中可以执行任何逻辑,如函数节流,Ajax异步获取数据,甚至操作DOM
3、computed vs watch
computed能做的,watch都能做,反之则不行
能用computed的尽量用computed
七、生命周期的应用场景和函数式组件
1、生命周期:
创建阶段:
初始化事件和生命周期 ->
beforeCreate ->
数据观测、属性、侦听器配置等 ->
created ->
编译到render ->
beforeMount ->
render ->
mounted ->
异步请求、操作DOM、定时器等(以来this.$nextTick(()=>)事件对子组件进行监听、更新)
更新阶段:
依赖数据改变或者$forceUpdate强制刷新 ->
beforeUpdate ->
移除已经添加的事件监听器等 万万不可更改依赖数据 ->
render ->
updated ->
操作DOM添加事件监听器等 万万不可更改依赖数据等(以来this.$nextTick(()=>)事件对子组件进行监听、更新)
销毁阶段:
beforeDestroy -> 移除已经添加的事件监听器,计时器等 -> destroyed
2、函数式组件:
functional:true
无状态、无实例、没有this上下文、无生命周期
应用:
组建中tempvar.js文件中
export default {
functional: true,
render: (h,ctx) => {
return ctx.scopedSlots.default && ctx.scopedSlots.default(ctx.props || {})
}
}
index.vue应用函数式组件
<TempVar
:var1="`hello`${name}"
:var2 ="destroyClock?'hello vue':'hello world'"
>
<template v-slot="{ var1,var2 }">{{var1}} {{var2}}</template>
</TempVar>
八、指令的本质
1、内置指令:v-text v-html v-show v-model v-if 等等 语法糖、标志位
2、自定义指令:
生命周期钩子:
bind
inserted
update
componentUpdated
unbind
九、常用高级特性provide 、inject 组建通信
1、通过provide 和 inject 实现跨组件传值 可使用API Vue.observable优化响应式provide
例如:A B C之间,A直接传值给C,就可以采用provide和inject实现
A组件中:
export default {
provide(){
//监听整个this上绑定的属性,即可实现响应式更新,否则若是color值没有在组件中应用,就不能实现响应式更新
return {
theme:{
this
}
}
},
data(){
return {
color:'blue'
}
}
}
C组件中:
<h3 :style="{color: theme.color}">C节点</h3>
export default {
inject:{
theme:{
default:() => ({}) //默认使用传过来的theme的值
}
}
}
十、优雅的获取跨层级组件实例
1、ref 引用信息: this.$refs.name获取组件实例信息 获取当前页面的组件信息
2、递归查找 : 代码繁琐、性能低效
3、callback ref :主动通知(serXXXRef) 主动获取(getXXXRef)
例如:A节点中:绑定自定义的跨组件传值方法
<button @click="getEH3Ref"> 获取E H3 Ref</button>
export default {
provide(){
setChildrenRef:(name, ref) => {
this[name] = ref
},
getChildrenRef: name => {
return this[name]
},
getRef: () => {
return this
}
},
}
C节点中:insert中绑定相应的传值方法
<ChildrenH v-ant-ref="c => setChildrenRef('children",c)" />
export default {
inject: {
setChildRef:{
default:() => {}
}
}
}
十一、template和JSX的对比以及他们的本质
1、template:
模板语法(HTML的扩展)
数据绑定使用Mustache语法(双大括号)
<span>Message:{{msg}}</span>
特点:
学习成本低、大量内置指令简化开发、组件作用域css、but灵活性地
2、JSX:
JavaScript的语法扩展
数据绑定使用单引号
<sapn>Message:{msg}</span>
特点:灵活
3、更抽象一点来看,我们可以把组件区分成两类:一类是偏视图表现的,一类则是偏逻辑的。我们推荐在前者中使用模板,在后者中使用JSX或渲染函数。这两类组件的比例会根据应用类型的不同有所变化,但整体来说我们发现表现类的组件远远多于逻辑类组件 --Vue官方文档
十二、常见问题总结
1、子组件修改传入的值,为什么vue中有提示:
Object.defineProperty() 底层原理控制,若子组件直接修改父组件内容,会触发底层原理为true的事件,导致vue中警告,若是将改变让父组件触发,即通过$emit(‘change’,e.target.value)事件发从给父组件,从而改变绑定的值
2、this.$emit的返回值是什么:
是this,若需要传递参数,则使用callback函数将参数返回
this.$emit('change',e.target.value,val => {
console.log(val)
})
handleEventChang(val,callback){
this.name = val
callback('hello')
}
3、相同名称的插槽是合并还是替换:
目前2.6版本以上都是替换,之前是合并
4、为什么不能用index作为key
更新DOM性能问题以及会引入状态bug问题
5、数组有哪些方法支持响应式更新,如果不支持如何处理,底层原理如何实现的
支持:push() pop() shift() unshift() splice() sort() reverse()
不支持:filter() concat() slice()
原理同样是使用Object.defineProperty对数组方法进行改写