自定义指令
自定义指令
需求:当页面加载时,让元素获取焦点(一进页面,输入框就获取焦点)
常规操作:操作dom “dom元素.focus()”
获取dom元素还要用ref 和 $refs
<input ref="inp" type="text">
mounted(){
this.$refs.inp.focus()
}
处在mounted这个钩子时,模板已经渲染完了
全局注册指令
所有组件内均可使用
语法:
Vue.directive('指令名',{
"inserted" (el) {
el.focus()
}
})
inserted:指令的生命周期钩子;指令所绑定的元素被添加到页面时会自动调用
el是指令所绑定的元素
局部注册指令
只能在所在组件内使用
语法:
directives:{
"指令名":{
inserted() {
el.focus()
}
}
}
使用:<input v-指令名 type="text">
指令的值
需求:实现一个color指令 —— 当传入不同颜色的时候,标签的文字颜色也跟着变成对应的颜色
语法:
- v-指令名 = "指令值" (通过等号绑定指令的值)
<div v-color = "color">我是内容</div>
- binging.value 拿指令值
- 通过update钩子,监听指令值的变化,进行dom更新操作 (数据变化,视图自动更新)
directives:{
color:{
inserted (el,binding) {
el.style.color = binding.value
},
update (el,binding) {
el.style.color = binding.value
}
}
}
el:指令所绑定的元素
update:指令值修改时会触发update函数
v-loading 指令封装
场景:在开发过程中,发送请求需要时间,在请求的数据未回来时,页面会处于空白状态;这个时候我们就需要实现一个加载中的效果。
这个加载中的效果,我们通常封装一个v-loading指令来实现
先来介绍一下伪类和伪元素
伪类:已有元素在处于某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的;例如::hover、:focus
伪元素:创建一些不在DOM树中的元素,并为其添加样式;例如:::before
::before 向指定元素之前插入内容
语法:
元素::before{content: "要插入的内容";/* 其他属性 */ }
CSS3 规范中有一部分要求,为了区分伪类和伪元素,伪元素使用两个冒号 (::), 伪类使用一个冒号 (:)
实现:
- 先准备一个loading类,通过伪元素定位(::before),设置宽高,实现蒙层
这里使用的是子绝父相
- 添加移除蒙层 => 钩子里添加移除loading类
- 设置定时器,时间一到关闭加载
- 使用指令
完整代码:
App.vue
<template><div class="main"><div class="box" v-loading="isLoading"><ul><li v-for="item in list" :key="item.id" class="news"><div class="left"><div class="title">{{ item.title }}</div><div class="info"><span>{{ item.source }}</span><span>{{ item.time }}</span></div></div><div class="right"><img :src="item.img" alt=""></div></li></ul></div></div>
</template><script>
const axios = require('axios')//加载模块
// // 安装axios => yarn add axios / npm install -g axios
// import axios from 'axios' //默认导入// 接口地址:http://hmajax.itheima.net/api/news
// 请求方式:get
export default {data () {return {list: [],isLoading: true,}},async created () {// 1. 发送请求获取数据const res = await axios.get('http://hmajax.itheima.net/api/news')setTimeout(() => {// 2. 更新到 list 中,用于页面渲染 v-forthis.list = res.data.datathis.isLoading = false//关闭加载}, 2000)},directives: {//局部注册loading: {inserted (el, binding) {//指令所在的元素,被插入到页面中时触发binding.value ? el.classList.add('loading') : el.classList.remove('loading')},update (el, binding) {//监听指令值的变化,进行dom更新操作binding.value ? el.classList.add('loading') : el.classList.remove('loading')}}}}
</script><style>
.loading::before {content: '';position: absolute;left: 0;top: 0;width: 100%;height: 100%;background: #fff url('./loading.gif') no-repeat center;
}.box {width: 800px;min-height: 500px;border: 3px solid orange;border-radius: 5px;position: relative;
}.news {display: flex;height: 120px;width: 600px;margin: 0 auto;padding: 20px 0;cursor: pointer;
}
.news .left {flex: 1;display: flex;flex-direction: column;justify-content: space-between;padding-right: 10px;
}
.news .left .title {font-size: 20px;
}
.news .left .info {color: #999999;
}
.news .left .info span {margin-right: 20px;
}
.news .right {width: 160px;height: 120px;
}
.news .right img {width: 100%;height: 100%;object-fit: cover;
}
</style>
插槽
默认插槽
场景:组件的内容部分,不希望写死,希望能使用的时候自定义 —— 使用插槽
作用:让组件内部结构自定义
插槽基本语法:
- 组件内需要定制的结构部分,改用<slot></slot>占位
- 使用组件时,<MyDialog></MyDialog>标签内部,传入结构替换slot
默认值
语法:在<slot>标签内,放置内容,作为默认显示内容
为什么引入默认值:当使用组件未给我们传入具体标签或内容时,显示空白,用户体验不好
具名插槽
具有名字的插槽
使用场景:一个组件出现 需要多处内容进行定制(组件内定制多处结构)
默认插槽:组件内定制一处结构
区别:不加名字的就是默认插槽
语法:
- 给多个slot插槽起名,将来通过name属性区分名字
- template配合v-slot:插槽名来分发对应标签
v-slot:插槽名 可以简化为 #插槽名
为什么用<template></template>包起来:不包的话vue无法区分到底哪块儿是一个整体
作用域插槽
是插槽的一个传参语法