课程目标
- vue进阶用法
知识点
- 模板化
- 组件化
模板化
插槽 slot
- 默认插槽
- 组件外部维护参数以及结构,内部安排位置
//App.vue
<template>
<hello-world>
<p>{{ msg }}</p>
</hello-world>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
exprot default {
components: { HelloWorld },
name: 'App',
data() {
return {
msg: 'helloworld'
}
}
}
</script>
//HelloWorld.vue
<template>
<slot></slot>
</template>
如果有多个内容,需要放在不同地方怎么办?
- 具名插槽
- 以
name标识插槽的身份,从而在组件内部做到可区分
//App.vue
<template>
<hello-world>
<p>{{ msg }}</p>
<template v-slot:header></template>
<template v-slot:body></template>
</hello-world>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
exprot default {
components: { HelloWorld },
name: 'App',
data() {
return {
msg: 'helloworld',
header: 'header',
body: 'body'
}
}
}
</script>
//HelloWorld.vue
<template>
//默认插槽
<slot></slot>
//具名插槽
<slot name:header></slot>
<slot name:body></slot>
</template>
- 作用域插槽
- 外部做结构描述勾勒,内部做传参
slot-scope(vue2.6版本之前)
//App.vue
<template>
<hello-world>
<p>{{ msg }}</p>
<template v-slot:header></template>
<template v-slot:body></template>
<template slot="content" slot-scope="slotProps">{{ slotProps }}</template>
</hello-world>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
exprot default {
components: { HelloWorld },
name: 'App',
data() {
return {
msg: 'helloworld',
header: 'header',
body: 'body'
}
}
}
</script>
//HelloWorld.vue
<template>
//默认插槽
<slot></slot>
//具名插槽
<slot name:header></slot>
<slot name:body></slot>
//可传递参数的slot
<slot :slotProps = "slotProps">
</template>
<script>
exprot default {
data() {
return {
slotProps: 'start'
}
}
}
</script>
- v-slot(新版本2.6之后)
//App.vue
<template>
<hello-world>
//老版
<template slot="content" slot-scope="slotProps">{{ slotProps }}</template>
//新版
<template v-slot:slotProps="slotProps">{{ slotProps }}</template>
</hello-world>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
exprot default {
components: { HelloWorld },
name: 'App',
data() {
return {
msg: 'helloworld',
}
}
}
</script>
//HelloWorld.vue
<template>
//可传递参数的slot
<slot :slotProps = "slotProps">
</template>
<script>
exprot default {
data() {
return {
slotProps: 'start'
}
}
}
模板数据的二次加工
watch、computed-- 相应流过于复杂(computed赋值)
- 方案一:函数 - 独立、管道 / 缺点:无法响应式
- 方案二:v-html
//HelloWorld.vue
<template>
<h1 v-html="money > 99 ? 99 : money"></h1>
</template>
<script>
exprot default {
data() {
return {
money: 100
}
}
}
- 方案三:过滤器 过滤器没有上下文(没有
this)
time: 绑定的值format: 过滤器的名字
{{ time | format }}
//HelloWorld.vue
<template>
<h1 v-html="money > 99 ? 99 : money"></h1>
//也可以使用过滤器实现
<h1> {{ money | moneyFilter}} </h1>
</template>
<script>
exprot default {
data() {
return {
money: 100
}
},
filters: {
moneyFilter(money) {
//过滤器没有this,只能传参
return money > 99 ? 99 : money
}
}
}
jsx 更自由的基于js书写
- v-model 如何实现 -- 双向绑定。-- 外层bind:value,内层@input
- 写jsx的优缺点:
- vue的编译路径:
template -> render -> vm.render -> vm.render() diff =>可以使用性能优化方案
data() {
return {
money: 100,
options: [
{text:'1', value: '1'},
{text:'2', value: '2'},
{text:'3', value: '3'}
]
}
}
methods: {
handleClick() {}
},
render(h) {
const mondey = {
<p>{this.money > 99 ? 99 :this.money}</p>
}
return (
<ul>
{
this.options.map((item, index) => {
return (
<content
onClick = { this.handleClick }
item = { item }
value = { item.value }
key = { index }
>
{ moneyNode }
</content>
)
})
}
</ul>
)
}
组件化
传统模板化
Vue.component('component', {
template: '<h1>组件</h1>'
})
new Vue({
el:'#app'
})
//functional components 函数式组件
- 抽象复用
- 精简 &
聚合
混入minxin,逻辑混入,以数组的形式返回
//demoMixin.js
exprot default {
data() {
return {
msg: 'mixin',
obj: {
title: 'mixinTitle'
}
}
}
}
//HelloWorld.vue
<template>
<h1 v-html="money > 99 ? 99 : money"></h1>
//也可以使用过滤器实现
<h1> {{ money | moneyFilter}} </h1>
</template>
<script>
import demoMixin from './components/demoMixin'
exprot default {
mixins: [ demoMixin ]
data() {
return {
money: 100,
msg: 'welcome'
}
},
create() {
console.info(this.$data)
//输出结果 {money:100,msg: 'welcome',obj: {title: 'mixinTitle'}}
}
}
- 应用:抽离公共逻辑(逻辑相同,模板不同,可用
mixin) - 缺点:数据来源不明确
- 特点:合并策略
- 1)递归合并
- 2)
data合并冲突时,以组件优先 - 3) 生命周期回调函数不会覆盖,会先后执行,优先级先
mixin后组件
//demoMixin.js
exprot default {
data() {
return {
msg: 'mixin',
obj: {
title: 'mixinTitle',
header: 'mixinheader'
}
}
}
}
//HelloWorld.vue
<template>
<h1 v-html="money > 99 ? 99 : money"></h1>
//也可以使用过滤器实现
<h1> {{ money | moneyFilter}} </h1>
</template>
<script>
import demoMixin from './components/demoMixin'
exprot default {
mixins: [ demoMixin ],
data() {
return {
money: 100,
msg: 'welcome',
obj: {
number: 123,
header: 'header'
}
}
},
create() {
console.info(this.$data)
//输出结果 {money:100,msg: 'welcome',obj: {number: 123,header: 'header':'mixinheader'}}
}
}
</script>
继承拓展。extends
- 逻辑拓展
- 应用: 拓展独立逻辑
- 与
mixin的区别:传值mixin为数组,extends为对象 - 合并逻辑:
- 1)同
mixin,也是递归合并 - 2)合并优先级:
组件>mixin>extends - 3)回调优先级:
extends>mixin
//demoExtends.js
exprot default {
data() {
return {
msg: 'extends',
obj: {
title: 'extendsTitle',
header: 'extendsHeader'
}
}
}
}
//HelloWorld.vue
<template>
<h1 v-html="money > 99 ? 99 : money"></h1>
//也可以使用过滤器实现
<h1> {{ money | moneyFilter}} </h1>
</template>
<script>
import demoExtends from './components/demoExtends'
exprot default {
extends: demoExtends,
data() {
return {
money: 100,
msg: 'welcome',
obj: {
number: 123,
header: 'header'
}
}
},
create() {
console.info(this.$data)
//输出结果 {money:100,msg: 'welcome',obj: {number: 123,header: 'header',title: 'extendsTitle'}}
}
}
整体拓展类 extend
从预定义的配置中拓展出来一个独立的配置项,进行合并
//extend 不一定非要写在main.js文件里,可以写在其它文件里
//main.js
//拓展一个构造器
let _baseOptions = {
data: function() {
return {
course: 'text',
session: 'aa'
}
},
create() {
console.info('extend base');
}
}
const BaseComponent = Vue.extend( _baseOptions )
new BaseComponent({
created() {
console.info('extend created');
}
})
//输出结果
//extend base
//extend created
Vue.use 组件
- 注册外部插件,作为整体实例的补充。
- 以
map形式注册的,会除重,不会重复注册。 - 手写插件
- 外部使用
Vue.use(myPlugin, options), - 默认调用内部的
install方法
//myPlugin.js
export default {
install: (Vue, option) >= {
Vue.globalMethods = function() {
//主函数
}
Vue.directive('my-directive', {
bind(el, binding, vnode, oldNode){
//全局资源
}
})
Vue.mixin({
created: function() {
console.info(option.name + 'created');
}
})
Vue.prototype.$myMethod = funciton() {}
}
//main.js
import myPlugin from './plugin/myPlugin'
const _options = {
name: 'my plugin'
}
Vue.use(myPlugin, _options)
组件的高级引用
递归引用- 动态组件 -
<component :is='name'></component> - 异步组件 -
import demoExtends from './components/demoExtends'; component:{demoExtends}懒加载,比如router