文章目录
一、组件
A. Vue.componet注册方式
一种通用解决方案的复用抽象
// 组件定义
Vue.component('component_name', {
props: {
field1: {
type: String,
default: ''
}
},
template: `
<div>{{ field1 }}</div>
`,
data: function() {
return {};
}
})
// 对于复用组件不允许直接将data设置为一个对象,而需要时用一个方法来返回(引用类型导致多复用场景公用同一个data对象);
// 对于未声明的变量或class属性,默认挂载在组件的根节点上;
// 'component_name'必须是全局唯一的;
缺陷:
- 全局component必须唯一;
- 字符串模板不支持语法高亮;
- 不支持css模块化;
- 没有构建步骤
B. *.vue文件的单文件组件
npm install -g @vue/cli
vue --version
<template></template>
<script>
export default {
data() {
return {}
}
}
</script>
<style scoped></style>
C、组件的数据驱动
数据必须是响应式的设置,即方法返回;同时需要响应变化的字段必须进行申明;
如果模板中未使用字段,则该字段不会进行响应式更新;
二、事件
使用
v-on:event
进行事件监听,可简写为@event
自定义事件:删除 ->@delete="xxxx"
自定义实践调用方法: this.$emit('event_name', ...args)
三、插槽
<slot>
通过占位的方式,在指定位置插入一段字符串或html; 类似为返回复杂内容函数;
// 示例:
// 组件:MainContent
<div id="content">
<slot/>
</div>
// 调用时:
<main-content>Hello World!!</main-content> // 1
<main-content> // 2
<h1>Hello World!!</h1>
</main-content>
// 会替代模板中的slot标签
// slot图标可以设置‘name’属性,替换指定slot:<slot name="xxx"/>
// 2.5版本之前直接使用,之后版本需要设置为:
<template v-slot:name>
xxxx
</template>
// 自定义html中获取slot模板组件中的值:
模板组件中: <slot name="xxx", :value="val">, (val是模板组件中的变量)
自定义html组件中:
<template v-slot:xxx="{value}">
<div>
{{ value }}
</div>
</template>
// <slot>aaa</slot>: aaa为默认值
四、数据绑定
v-model
可实现数据的双向绑定
// 方式1
<input v-model="data" />
// 方式2
<input :value="data" @input="handleChange" />
自定义双向绑定:
<custom-item v-bind:title.sync="data.title" />
<custom-item v-bind:title="data.title" v-on:update:title="data.title = $event"/>
自定义组件中:
this.$emit('update:title', args)
// 该方法不可用于表达式
五、计算属性computed及监听watch
计算属性仅在数据发生变化时才会进行计算;而通过响应事件去做时,需要每次计算;
作用:
- 减少模板中计算逻辑
- 数据缓存
- 依赖固定的数据类型(响应式数据)
watch:
数据结构:
data: functuon() {
return {
a: 'aaa',
b: {b1: '', b2: ''},
c: {c1: '', c2: ''}
}
},
watch: {
a: functuin(val, oldVal) {
// 监听a的变化
},
'b.b1': functuin(val, oldVal) {
// 监听b.b1的变化
},
c: functuin(val, oldVal) {
// 监听c的变化
}
}
computed和watch的区别:
- 计算属性computed能做到的,watch都可以做到;
- 能用computed时尽量使用computed, watch的写法更复杂,更底层;
六、生命周期
vue的生命周期及各个周期做的事情
A. 创建阶段
B. 更新阶段
C. 销毁阶段
七、组件通信
组件通信,可通过 属性变量 的方式进行状态的传递;但必须经过两个节点的共用节点来进行中转,因此会涉及到dom树多层级的处理,每一级之间均需要进行属性的双向绑定,导致层次结构复杂;
vue提供provide
和inject
的方式来进行组件通信,降低通信成本;
// 组件1
...
<script>
export default {
provide() {
return {
field: {
color: this.color // color属性必须是响应式的
}
}
}
}
</script>
...
// 组件2
...
<script>
export default {
inject: {
return {
field1: {
from: 'field', // 实现字段映射
default: () => {{}}
},
field: {
default: () => {{}}
}
}
}
}
</script>
...
// 注:如果一个属性存在多个provider,那么inject找到的为路径最短的provider;
// 若要支持响应式变化,那么传递的属性必须是响应式的属性;
八、组件跨层级获取vue实例
ref
: 可直接获取组件实例,但无法获取到跨层级的vue实例;
callback ref
通过provide
以及inject
的方式可以优雅的实现多组件通信,
因此可以考虑对虚拟dom中的各级组件实例进行缓存;
然后提供一种机制,在组件实例进行变更时进行变化通知;
最终在inject注入中就可以获取到当前最新的实例状态;
实现方案:通过自定义指令(例如:v-ant-ref),通过bind,更新等事件来进行实例的更新。
九、jsx和template对比及本质
template
<span> nessage: {{ msg }}</span>
// html语法扩展, 双大括号(Mustache)数据绑定
// 学习成本低,大量内资指令,组件作用于css,灵活性较低
jsx
<span>message: { this.msg }</span>
// js语法扩展, 单大括号数据绑定
// 灵活性高
使用对比
// template
<template>
<h1 v-if="level === 1"> <slot/> </h1>
<h2 v-if="level === 2"> <slot/> </h2>
<h3 v-if="level === 3"> <slot/> </h3>
<h4 v-if="level === 4"> <slot/> </h4>
</template>
<script>
export default {
props: {
level: {
type: Number,
default: 1
}
}
}
</script>
// jsx
export default {
props: {
level: {
type: Number,
default: 1
}
},
render: function(h) {
const Tag = `h${this.level}`;
return <Tag>{this.$slots.default}</Tag>;
}
}
// js
export default {
props: {
level: {
type: Number,
default: 1
}
},
render: function(createElement) {
// 多级标签时需要多级创建嵌套
return createElement(
`h${this.level}`,
{this.$slots.default}
);
}
}
十、vuex
前后端分离后,也随着前端的发在,前端也需要维护自己的状态量;实现状态管理;
A. vuex的使用
// main.js中定义
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state, n) {
state.count += n;
}
},
actions: { // 异步处理, 通过dispatch调用
increment({state}) {
// do some async event
}
},
getters: { // 计算属性
doubleCount(state) {
return state.count * 2;
}
}
})
...
// 使用
<template>
<div> {{ count }} </div>
<button @click="$store.commit('increment', 2)"> +2 </button>
</template>
<script>
export default {
// mapState, mapGetters批量的获取属性状态
computed: {
count: function() {
return this.$store.state.count
},
...mapState({
count1: state => state.count
}),
...mapGetters({
doubleCount: 'doubleCount'
})
}, // mapActions批量引入方法
methods: {
...mapActions(`${nameSpace}`, [
'increment',
])
},
created() {
this.$store.dispatch(`${nameSpace}/${method}`)
}
}
</script>
十一、vue router
Vue.use(VueRouter);
const routes = [];
const router = new VueRouter({
routes: routes
})
export default router;