一.自定义指令
自己定义的指令,可以封装一些dom操作,扩展额外功能
需求:当页面加载时,让元素将获得焦点(autofocus 在 safari浏览器有兼容性)
之前操作dom:dom元素.focus()
javascript
mounted(){
this.$refs.inp.focus()
}
1.全局注册:
javascript
//在main.js中进行注册
Vue.directive('指令名',{
//inserted会在指令所在的元素,被插入到页面中时触发
"inserted"(el){
//el就是指令所绑定的元素
el.focus()
}
})
2.局部注册:
javascript
//在.vue文件中进行注册
directives:{
"指令名":{
inserted(){
el.focus()
}
}
}
全局注册/局部注册使用:
javascript
<input v-指令名 type="text">
指令的值:
语法:在绑定指令时,可以通过"等号"的形式为指令绑定具体的参数值
javascript
<div v-color="color">哈哈哈</div>
通过binding.value 可以拿到指令值,指令值修改会触发update函数
javascript
directives: {
color:{
inserted (el, binding) {
el.style.color = binding.value
},
update (el, binding) {
el.style.color = binding.value
}
}
}
javascript
<template>
<div class="App">
<h1 v-color="color1">指令的值1</h1>
<h1 v-color="green1">指令的值2</h1>
</div>
</template>
<script>
export default {
data(){
return{
color1:'red',
green1:'green'
}
},
directives:{
color:{
inserted(el,binding){
el.style.color = binding.value
},
update(el,binding){
el.style.color = binding.value
}
}
}
}
</script>
<style lang="less" scoped>
.App{
width: 500px;
height: 500px;
border: 1px solid;
padding: 20px;
}
</style>

v-loading指令的封装:
实际开发过程中,发送请求需要时间,在请求的数据未回来时,页面会处于空白状态
封装一个v-loading指令,实现加载中的效果
1.本质loading效果就是一个蒙层,盖在了盒子上
2.数据请求中,开启loading状态,添加蒙层
3.数据请求完毕,关闭loading状态,移除蒙层
实现:
1.准备一个loading类,通过伪元素定位,设置宽高,实现蒙层
2.开启关闭loading状态(添加移除蒙层),本质只需要添加移除类即可
3.结合自定义指令的语法进行封装复用
javascript
<template>
<div class="App" v-loading="isLoading">
<h1>这是loading加载后的内容</h1>
</div>
</template>
<script>
export default {
data(){
return{
isLoading:true
}
},
directives:{
loading:{
inserted(el,binding){
binding.value ? el.classList.add('loading') : el.classList.remove('loading')
},
update(el,binding){
binding.value ? el.classList.add('loading') : el.classList.remove('loading')
}
}
},
mounted(){
this.timer = setTimeout(() => {
this.isLoading = false
}, 2000)
},
beforeDestroy(){
clearTimeout(this.timer)
}
}
</script>
<style lang="less" scoped>
.App{
width: 500px;
height: 500px;
border: 1px solid;
padding: 20px;
}
.loading:before{
content:"";
position:absolute;
top:0;
left:0;
width:28%;
height:80%;
background:#fff url("../public/images/loading.gif") no-repeat center;
background-size:100px 100px;
}
</style>


二.插槽
作用:让组件内部的一些结构支持自定义
语法:
1.组件内需要定制的结构部分,改用<slot></slot>占位
2.使用组件时,<MyDialog></MyDialog>标签内部,传入结构替换slot
javascript
<template>
<div class="dialog-mask">
<div class="dialog">
<div class="dialog-header">
<span class="title">温馨提示</span>
<span class="close">×</span>
</div>
<div class="dialog-body">
<!-- 1.需要使用的位置使用<slot>占位 -->
<slot></slot>
</div>
<div class="dialog-footer">
<button class="btn btn-cancel">取消</button>
<button class="btn btn-confirm">确认</button>
</div>
</div>
</div>
</template>
<script>
export default {
}
</script>
javascript
<template>
<div class="App">
<!-- 2.使用组件时组件标签内填入内容 -->
<MyDialog>
确定要退出本系统吗?
</MyDialog>
<MyDialog>
确定要删除吗?
</MyDialog>
</div>
</template>
<script>
import MyDialog from './components/MyDialog.vue'
export default {
components:{
MyDialog
}
}
</script>

1.插槽后备内容
封装组件时,可以为预留的**`<slot>`**插槽提供后备内容(默认内容)
语法:在<slot>标签内,放置内容,作为默认显示内容
效果:
1.外部使用组件时,不传东西,则slot会显示后备内容
2.外部使用组件时,传东西了,则slot整体会被换掉
2.具名插槽
默认插槽:一个的定制位置
具名插槽:一个组件内有多处结构,需要外部传入标签,进行定制
具名插槽语法:
1.多个slot使用name属性区分名字
2.template配合v-slot:名字来分发对应标签
3.v-slot:插槽名 可以简化成**#插槽名**
javascript
<template>
<div class="App">
<MyDialog>
<template #head>
<div>温馨提示</div>
</template>
<template #body>
<div>确认删除吗?</div>
</template>
<template #footer>
<button class="btn btn-cancel">取消</button>
<button class="btn btn-confirm">确认</button>
</template>
</MyDialog>
<MyDialog>
<template #head>
<div>友情提示</div>
</template>
<template #body>
<div>确认退出本系统吗?</div>
</template>
<template #footer>
<button class="btn btn-confirm">确认</button>
</template>
</MyDialog>
</div>
</template>
<script>
import MyDialog from './components/MyDialog.vue';
export default {
components:{
MyDialog
}
}
</script>
javascript
<template>
<div class="dialog-mask">
<div class="dialog">
<div class="dialog-header">
<span class="title">
<slot name="head"></slot>
</span>
<span class="close">×</span>
</div>
<div class="dialog-body">
<slot name="body"></slot>
</div>
<div class="dialog-footer">
<slot name="footer"></slot>
</div>
</div>
</div>
</template>
<script>
export default {
}
</script>

3.作用域插槽
是插槽的一个传参语法,并不属于插槽的分类(默认插槽、具名插槽)当中
定义slot插槽的同时是可以传值的,给插槽上可以绑定数据,将来使用组件时可以用
场景:封装表格组件
1.父传子,动态渲染表格内容
2.利用默认插槽,定制操作列
3.删除或查看都需要用到当前项的id,属于组件内部的数据,通过作用域插槽传值绑定使用
基本步骤:
1.给slot标签,以添加属性的方式传值
javascript
<slot :id="item.id" msg="哈哈哈"></slot>
2.所有添加的属性,都会被收集到一个对象中
javascript
{ id:1 , msg:'哈哈哈' }
3.在template中,通过**#插槽名="obj"**接收,默认插槽名为default
javascript
<MyTable :list="list">
<template #default="obj">
<button @click="del(obj.id)">删除</button>
</template>
</MyTable>
三.单页应用程序
单页面应用(SPA):所有功能在一个html页面上实现
单页面开发:
一个html页面,按需更新性能高,开发效率高,用户体验好,学习成本高,首屏加载慢,SEO差
应用:系统类网站/内部网站/文档类网站/移动端站点
多页面开发:
多个html页面,整页更新性能低,开发效率中等,用户体验一般,学习成本中等,首屏加载快,
SEO优(SEO:搜索引擎优化)
javascript
import VueRouter from'vue-router'
应用:公司官网/电商类网站
四.路由使用
Vue中路由:路径和组件的映射关系
根据路由就能知道不同路径的,应该匹配渲染哪个组件
1.VueRouter插件:
Vue官方的一个路由插件,是一个第三方包
作用:修改地址栏路径时,切换显示匹配的组件
2.VueRouter的使用:
1.下载:下载VueRouter模块到当前工程,版本3.6.5
javascript
npm add vue-router@3.6.5
2.引入
javascript
import VueRouter from'vue-router'
3.安装注册
javascript
Vue.use(VueRouter)
4.创建路由对象
javascript
const router = new VueRouter()
5.注入,将路由对象注入到newVue实例中,建立关联
javascript
new Vue({
render:h => h(App),
router
}).$mount('#app')
6.创建需要的组件(views目录),配置路由规则
7.配置导航,配置路由出口(路径匹配的组件显示的位置)







组件目录存放问题:
组件分类:页面组件、复用组件
src/views文件夹:页面组件---页面展示---配合路由用
src/components文件夹:复用组件---展示数据---常用于复用