# 动态组件

# 动态组件定义

动态组件指的是动态切换组件的显示与隐藏

# 实现动态组件渲染

<template>
	<div>
        <button @click="comName = 'Left'">展示 Left</button>
        <button @click="comName = 'Right'">展示 Right</button>
        <component :is="comName"></component>
    </div>
</template>
<script>
export default {
    data () {
        return {
            comName: 'Left'
        }
    }
}
</script>

# 使用 keep-alive 保持状态

默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 <keep-alive> 组件保持动态组件的状态

<template>
	<div>
        <keep-alive>
    		<component :is="comName"></component>
    	</keep-alive>
    </div>
</template>

# keep-alive 生命周期函数

当组件被缓存时,会自动触发组件的 deactivated 生命周期函数

当组件被激活时,会自动触发组件的 activated 生命周期函数

<script>
export default {
    activated () {
        console.log('Left 组件被激活了');
    },
    deactivated () {
        console.log('Left 组件被缓存了');
    }
}
</script>

# keep-alive 的 include 属性

include 属性用来指定:只有名称匹配的组件会被缓存。多个组件名之间使用英文的逗号分隔,也可以使用 exclude 属性,不能同时使用

<template>
	<div>
        <keep-alive include="Left,Right">
    		<component :is="comName"></component>
    	</keep-alive>
    </div>
</template>

# 插槽

# 插槽定义

插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽

image-20230116121918426

# 体验插槽的基础用法

在封装组件时,可以通过 <slot> 元素定义插槽,从而为用户预留内容占位符

<template>
	<p>这是 MyCom1 组件的第一个标签</p>
	<solt></solt>
	<p>这是 MyCom1 组件的最后一个标签</p>
</template>
<MyCom1>
	<p>---用户自定义内容---</p>
</MyCom1>

# 没有预留插槽的内容会被丢弃

如果在封装组件时没有预留任何 <slot> 插槽,则用户提供的任何自定义内容都会被丢弃

<template>
	<p>这是 MyCom1 组件的第一个标签</p>
	<p>这是 MyCom1 组件的最后一个标签</p>
</template>
<MyCom1>
	<p>---用户自定义内容---</p>
</MyCom1>

# 后备内容

封装组件时,可以为预留的 <slot> 插槽提供后备内容(默认内容)如果组件的使用者没有为插槽提供任何内容,则后备内容会生效

<template>
	<p>这是 MyCom1 组件的第一个标签</p>
	<solt>这是插槽后备内容</solt>
	<p>这是 MyCom1 组件的最后一个标签</p>
</template>

# 具名插槽

如果在封装组件时需要预留多个插槽节点,则需要为每个 <slot> 插槽指定具体的 name 名称

<template>
	<solt name="default">默认名字就是default</solt>
</template>

# 为具名插槽提供内容

在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称

<template v-solt:header>
	<h1>header---</h1>
</template>
<!-- 简写方法 -->
<template #header>
	<h1>header---</h1>
</template>

# 作用域插槽

在封装组件的过程中,可以为预留的 <slot> 插槽绑定 props 数据,这种带有 props 数据的 <slot> 叫做 “作用域插槽”

<template>
	<div>
        <tbody>
    		<solt v-for="item in list" :user='item'></solt>
    	</tbody>
    </div>
</template>

# 使用作用域插槽

可以使用 v-slot: 的形式,接收作用域插槽对外提供的数据

<template>
	<div id="app">
        <MyCom>
    		<template v-solt:default="scope">
				<p></p>
			</template>
    	</MyCom>
    </div>
</template>

# 解沟插槽 Prop

作用域插槽对外提供的数据对象,可以使用解构赋值简化数据的接收过程

<template>
	<div id="app">
        <MyCom>
    		<template v-solt:default="{user}">
				<p></p>
			</template>
    	</MyCom>
    </div>
</template>

# 自定义指令

# 自定义指令定义

vue 官方提供了 v-text、v-for、v-model、v-if 等常用的指令,除此之外 vue 还允许开发者自定义指令

# 自定义指令分类

  • 私有自定义指令
  • 全局自定义指令

# 私有自定义指令

在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令

<script>
export default {
    directive: {
        color: {
            bind (el) {
		       el.style.color = 'red'	
            }
        }
    }
}
</script>

# 使用自定义指令

<template>
	<div>
        <h1 v-color>App组件</h1>
    </div>
</template>

# 为自定义指令动态绑定数值

在 template 结构中使用自定义指令时,可以通过等号(=)的方式,为当前指令动态绑定参数值

<template>
	<div>
        <h1 v-color="color">App组件</h1>
    </div>
</template>
<script>
export default {
    data () {
        return {
            color: 'red'
        }
    }
}
</script>

# 通过 binding 获取指令的参数值

在声明自定义指令时,可以通过形参中的第二个参数,来接收指令的参数值

<script>
export default {
    directives: {
        color: {
            bind (el, binding) {
                el.style.color = binding.value
            }
        }
    }
}
</script>

# update 函数

bind 函数只调用 1 次:当指令第一次绑定到元素时调用,当 DOM 更新时 bind 函数不会被触发,update 函数会在每次 DOM 更新时被调用

<script>
export default {
    directives: {
        color: {
            bind (el, binding) {
                el.style.color = binding.value
            },
            update (el, binding) {
                el.style.color = binding.value
            }
        }
    }
}
</script>

# 函数简写

如果 insert 和 update 函数中的逻辑完全相同,则对象格式的自定义指令可以简写成函数格式

<script>
export default {
    directives: {
        color (el, binding) {
            el.style.color = binding.value
        }
    }
}
</script>

# 全局自定义指令

在 main.js 中定义

Vue.directive('color', function (el, binding) {
    el.style.color = bingding.value
})

# axios

# 定义全局 axios

在 main.js 中导入

import axios from 'axios'
Vue.prototype.$axios = axios // $axios 这是后面调用使用的名称

# 调用全局 axios

<script>
export default {
    methods: {
        async getInfo () {
            const {data: res} = await this.$axios.get('http://www.baozi.com:3006/api/get')
        }
    }
}
</script>

# 配置统一根路径

import axios from 'axios'
axios.defaults.baseURL = 'http://www.baozi.com:3006'
Vue.prototype.$axios = axios // $axios 这是后面调用使用的名称
<script>
export default {
    methods: {
        async getInfo () {
            const {data: res} = await this.$axios.get('/api/get')
        }
    }
}
</script>

# 配置统一的根路径缺点

不利于接口路径的复用