动态组件
动态组件指 动态切换组件的显示与隐藏
vue 提供内置 <component> 组件,专门用于实现动态组件渲染。<component :is="comName">
注:<component> 切换时,组件会重新创建。可用<keep-alive> 缓存组件
<keep-alive> 生命周期函数
- 被缓存时。自动触发 deactivated 生命周期函数
- 被激活时。自动触发 activated 生命周期函数 (第一次创建也会被激活)
<keep-alive> include,exculde属性
- include 属性指定:只有名称匹配的组件才会被缓存,多个组件由 ',' 分割
- exculde 属性指定:排除项不会被缓存
<template>
<div class="app-container">
<h1>App 根组件</h1>
<hr />
<button @click="comName = 'Left'">Left</button>
<button @click="comName = 'Right'">Right</button>
<div class="box">
<!--keep-alive 可以把内部组件进行缓存,而不是销毁-->
<keep-alive include="Left">
<!-- component 组件占位符 :is 表示渲染组件名称 -->
<component :is="comName"></component>
</keep-alive>
</div>
</div>
</template>
<script>
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue'
export default {
data(){
return{
comName:'Left'
}
},
components:{
Left,
Right
}
}
</script>
<style lang="less">
.app-container {
padding: 1px 20px 20px;
background-color: #efefef;
}
.box {
display: flex;
}
</style>
插槽
插槽(slot) 时vue为组件封装着提供的功能。允许开发这在封装组件时,把不确定,希望由用户指定的部分定义为插槽。
############### Left.vue #################
<template>
<div class="left-container">
<h3>Left 组件</h3>
<hr />
<!--声明插槽区域-->
<!--官方规定solt需要有name 名称,默认为defalut-->
<!--后备内容,无定义内容时使用-->
<!--具名插槽:为<slot> 提供名称-->
<!--作用域插槽:为<slot> 提供属性对应的值-->
<slot name="myslot" msg="message" :user="user">default text</slot>
</div>
</template>
############### App.vue ###########
<template>
<div class="app-container">
<h1>App 根组件</h1>
<hr />
<div class="box">
<!--插槽使用-->
<left>
<!--v-slot: 简写 #-->
<!--scope 解构赋值成 {msg,user}-->
<template #myslot="{msg,user}"> <!--<template #myslot="scope">-->
<p>Left插槽调用</p>
<p>{{msg}}</p>
<p>{{user.name}}</p>
</template>
</left>
</div>
</div>
</template>
自定义指令
私有自定义指令
在每个vue组件中,可以在 directives 节点下声明 私有自定义指令。
- bind(el,binding) 只在绑定第一次才触发
- update(el,binding) 在DOM 更新时触发
- color(el,binding) 自定义指令 简写
-
<!--<h5 v-color>自定义指令</h5>--> <h5 v-color="'red'">自定义指令</h5> directives:{ /*color:{ //为绑定到 html 元素设置红色文字 bind(el){ //形参中的 el 是绑定了次指令的,原生的DOM 对象 el.style.color='red'; }, //bind(el) 固定写法,只在绑定第一次才触发 bind(el,binding){ el.style.color=binding.value; }, //bind(el) 固定写法,在DOM 更新时触发 update(el,binding){ el.style.color=binding.value; } }*/ //自定义指令 简写 color(el,binding){ el.style.color=binding.value; } }
全局自定义指令
在main.js 通过 Vue.directive('color',function(el,binding) 方式声明。
-
######## main.js ########## import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false //全局自定义指令 Vue.directive('color',function(el,binding){ el.style.color=binding.value; }) new Vue({ render: h => h(App), }).$mount('#app')
axios 优化
全局axios
①定义全局axios,避免组件多次创建
②定义全局根路径,避免重复书写更路径
缺点:API接口无法在组件间复用
######## main.js ##########
import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'
Vue.config.productionTip = false
// 全局配置 axios 的请求根路径
axios.defaults.baseURL = 'http://www.myAxios.top:3006'
// 把axios挂载到 vue.prototype 上,供每个.vue组件实例直接调用
Vue.prototype.$http = axios
new Vue({
render: h => h(App)
}).$mount('#app')
######## .vue ##########
methods: {
async postInffo () {
const { data: res } = await this.$http.post('/api/post', { name: zs, age: 22 })
console.log(res)
}
}
③ 解决全局axios 无法重用问题
封装 request.js 模块
// request.js //
import axios from 'axios'
const request = axios.create({
// 指定请求的根路径
baseURL: 'https://www.escook.cn'
})
export default request
④ API接口封装
// 文章相关接口 返回Promise实例对象 提供代码复用性
import request from '@/utils/request.js'
// 按需导出
export const getArticleList = function (page, limit) {
return request.get('/articles', {
// 请求参数
params: { _page: page, _limit: limit }
})
}
// 按需导入API接口
import { getArticleList } from '@/api/articleAPI.js'
export default {
methods: {
// 封装获取文章数据
async initArticleList (refreshFlag) {
const { data: res } = await getArticleList(this.page, this.limit)
console.log(res)
},
},
created () {
this.initArticleList()
},
}
axios 拦截器
概念:每次发起 ajax 请求和响应 时候自动被触发。
作用:Token 身份认证,Loading效果
// main.js //
import axios from 'axios'
//Loading 效果
import {Loading} from 'element-ui'
let loadingInstance = null
//请求拦截器
axios.interceptors.request.use(config=>{
//获取Token
config.headers.Authorzation = 'Barer xxxx'
//Loading 开启
loadingInstance = Loading.servive({fullscreen:true})
// config 必须返回
return config;
})
//响应拦截器
axios.interceptors.response.use(function(response){
//成功
//Loading 关闭
loadingInstance.close();
return response;
},function(error){
//失败
loadingInstance.close();
return Promise.reject(error);
})
proxy 跨域代理
vue-cli 项目通过代理解决接口跨域问题
① 把 axios 的请求根路径 设置为 vue 项目的运行地址(接口请求不再跨域)
② vue项目 发现请求接口不存在,把请求转交给proxy代理
③ 代理把请求根路径替换为 devServer.proxy 属性的值,发起真正的数据请求
④ 代理把请求到的数据,转交到axios
// request.js //
import axios from 'axios'
const request = axios.create({
// 指定请求的根路径(项目运行地址)
//baseURL: 'https://www.escook.cn'
baseURL: 'https://localhost:8080'
})
export default request
/vue.config.js
module.exports = {
devServer:{
//当项目在调试阶段
//会将任何未知请求(未匹配到静态文件的请求)代理到 'https://www.escook.cn'
proxy: 'https://www.escook.cn'
}
}
注意:
① devServer.proxy 提供的代理功能,仅在开发阶段生效
② 项目上线发布时,仍然需要API接口服务器开启CORS跨域资源共享