自定义指令
- 之前所学的比如v-model、v-for、v-html...这些都属于内置指令
- 而像v-focus、v-loading、v-lazy...则属于自定义指令
定义
自定义指令: 自己定义的指令,可以 封装一些dom操作,扩展额外功能
需求: 当页面加载时,让元素获得焦点
之前的话,我们会直接这样写
<input ref="inp" type="text">
mounted () {
this.$refs.inp.focus()
}
但是这样写的话,只能在当前页面使用,如果你再跳转到别的页面,就需要再重新写
所以这时候就需要自定义指令了(自定义指令又分为全局和局部)
- 全局
- 全局注册指令,需要在main.js文件里写
<input v-focus type="text">
// 1. 全局注册指令
Vue.directive('focus'指令名, {
// inserted 会在 指令所在的元素,被添加到页面中时自动调用
"inserted" (el) {
// el 就是指令所绑定的元素,可以对el标签扩展额外功能
// console.log(el);
el.focus()
}
})
- 局部
- 在当前组件里定义
// 2. 局部注册指令
directives: {
// 指令名:指令的配置项
focus指令名: {
inserted (el) {
// el 就是指令所绑定的元素,可以对el标签扩展额外功能
el.focus()
}
}
}
}
上面是定义指令的操作,然后你要使用的时候,直接在页面对应部分 v-指令名 即可
指令的值
需求:实现一个color指令——传入不同的颜色,给标签设置文字颜色
语法:在绑定指令时,可以通过“等号”的形式为指令绑定具体的不同的参数值
而通过binding.value就可以拿到指令值,指令值修改会触发update函数
<template>
<div>
<h1 v-color="color1">指令的值1测试</h1>
<h1 v-color="color2">指令的值2测试</h1>
</div>
</template>
<script>
export default {
data () {
return {
color1: 'red',
color2: 'orange'
}
},
directives: {
color: {
// 1. inserted 提供的是元素被添加到页面中时的逻辑
inserted (el, binding) {
// console.log(el, binding.value);
// binding.value 就是指令的值
el.style.color = binding.value
},
// 2. update 指令的值修改的时候触发,提供值变化后,dom更新的逻辑
//不写这个的话,当指令的值被修改时,视图没有响应!!!!!!!!!!!!!
update (el, binding) {
console.log('指令的值修改了');
el.style.color = binding.value
}
}
}
}
</script>
v-loading指令封装
实际开发中,发送请求需要时间,在请求的数据未回来时,页面会处于空白状态 => 用户体验不好
分析:
- 本质loading效果就是一个蒙层,盖在了盒子上
- 数据请求中,开启loading状态,添加蒙层
- 数据请求完毕,关闭loading状态,移除蒙层
插槽
TIP:插槽只有两个分类:默认插槽和具名插槽
默认插槽(一个定制位置)
作用:让组件内部的一些 结构 支持 自定义
需求:要在页面中显示一个对话框,封装成一个组件
问题:组件的内容部分,不希望写死,希望能使用的时候自定义
基本语法:
- 组件内需要定制的结构部分,改用
<slot></slot> - 使用组件时,
<MyDialog></MyDialog>标签内部,传入结构替换slot
后备内容(默认值)
通过插槽完成了内容的定制,传什么显示什么,但如果不传,则是空白
插槽后备内容: 封装组件时,可以为预留的<slot>插槽提供后备内容(默认内容)
语法:在<slot>我是默认内容</slot>标签内,放置内容,作为默认显示内容(当<MyDialog></MyDialog>里无内容时)
具名插槽
需求:一个组件内有多处结构,需要外部传入标签,进行定制
- 与刚刚默认插槽不同的是,默认插槽只有一个定制位置,具名插槽有多个
- 一旦插槽起了名字,它就是具名插槽,只支持定向分发
语法:
-
- 多个
slot使用name属性区分名字
- 多个
-
template配合v-slot:名字来分发对应标签
- 多个template外是用
<MyDialog></MyDialog>包起来的 - 需要通过template标签包裹需要分发的结构,包成一个整体,才能更好的进行分发
-
v-slot:插槽名可以简化成#插槽名
作用域插槽(插槽的一个传参语法)
作用域插槽:定义slot插槽的同时,是可以传值的。给插槽上可以绑定数据,将来使用组件时可以使用
基本使用步骤:
- 给slot标签,以 添加属性的方式 传值(传递数据)
<slot id="item.id" msg="测试文本"></slot>
- 所有添加的属性,都会被收集到一个对象中
{id:3,msg:'测试文本'}
- 在template中,具名通过
#插槽名="obj"接收,默认插槽用#default="obj",然后在template里就可以通过obj.id使用了
<template #default="obj">
//也可以这样写,直接对obj结构,比如row就是obj里面的一个对象
<template #default="{ row }">
组件封装案例——商品列表
单独写在外面了
单页应用程序 & 路由介绍
单页应用程序:SPA-Single Page Application
- 单页面应用(SPA):所有功能在一个html页面上实现
- 开发效率高,性能好,用户体验高
- 而有这些优点是因为:页面按需更新
要按需更新,首先就要明确:访问路径和组件的对应关系👇
路由: 可以确定访问路径和组件的对应关系
- Vue中的路由:是路径和组件的映射关系
- VueRouter插件
- 修改地址栏路径时,切换显示匹配的组件
VueRouter的使用(5+2)
五个基础步骤(固定),在main.js里写
- 下载VueRouter模块到当前工程,版本3.6.5
yarn add vue-router@3.6.5
npm install vue-router@3.6.5
- 引入
import VueRouter from 'vue-router'
- 安装注册
Vue.use(VueRouter)
- 创建路由对象(这里面之后会写路由规则)
const router = new VueRouter()
- 注入,将路由对象注入到new Vue实例中,建立关联
new Vue({
render:h => h(App),
router
}).$mount('#app')
两个核心步骤
- 创建需要的组件(views目录),配置
路由规则routes- route 一条路由规则 { path: 地址栏路径, component: 组件 }
import Find from './views/Find'
import My from './views/My'
import Friend from './views/Friend'
import VueRouter from 'vue-router'
const router = new VueRouter({
// routes 路由规则们
// route 一条路由规则 { path: 路径, component: 组件 }
//数组包对象
routes: [
{ path: '/find', component: Find },
{ path: '/my', component: My },
{ path: '/friend', component: Friend },
]
})
- 配置导航,配置路由出口(路径匹配的组件显示的位置
<router-view>)
<div class="footer_wrap">
<a href="#/find">发现音乐</a>
<a href="#/my">我的音乐</a>
<a href="#/friend">朋友</a>
</div>
<div class="top">
<!-- 路由出口 → 匹配的组件所展示的位置 -->
<router-view></router-view>
</div>