Vue 学习笔记(三)
1. 插槽
插槽允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。
我们使用标签时,开始标签和结束标签之间之前都没有写东西。组件的标签和正常的双标签,如 div、p 等一样,可以在里面写东西。但是,直接在里面写,会发现,写的东西不会显示出来,也找不到了,被丢弃了。其实这个也挺好理解的,组件本来就有东西了,vue 又不知道你写的东西要插到哪里去。所以,vue 提供了插槽,可以在想要插的地方加上一个插槽,之后再把内容插过去。
用法例子:
效果:
没有预留插槽的话,用户提供的自定义内容都会被丢弃。
- 封装组件时,可以为预留的插槽提供默认内容,如果组件的使用者没有为插槽提供内容,默认内容就会生效。
1.1 具名插槽
上面的例子中,有多个插槽,输入的文章头这段信息原本想插在第一个插槽里面的,但是会发现,它插到了所有的插槽中。
这个时候就需要使用具名插槽了。
具名插槽:如果在封装组件时需要预留多个插槽,则需要为每个插槽指定具体的名称。这种带有具体名称的插槽就叫”具名插槽”。
如果没有给插槽起名字,则插槽默认叫”default”。要插入插槽的内容如果没有指定要插到哪里去,则会插到名为”default”的插槽中。
这就是为什么上面没有使用具名插槽时,内容会插到所有的插槽中去。
1.2 作用域插槽
在封装组件时,可以为预留的 slot 插槽绑定 props 数据,这个带有 props 数据的 slot 插槽叫做作用域插槽
解构插槽:因为得到的数据是对象形式的,所以可以解构,得到要用的数据
2. 自定义指令
2.1 私有自定义指令
在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令。
为自定义指令动态绑定参数值
通过=的方式,为当前指令动态添加参数值,通过形参中的第二个参数binding来接收指令的参数值。
<template>
<div class="app-container">
<h1 v-color="color">App根组件</h1>
<hr />
</div>
</template>
<script>
export default {
data() {
return {
color: "blue",
};
},
directives: {
color: {
//自定义指令名字
bind(el, binding) {
//el是绑定了这个指令的DOM对象
// el.style.color = 'red';
console.log(binding);
},
},
},
};
</script>
<style lang="less">
.app-container {
padding: 1px 20px 20px;
background-color: #efefef;
}
.box {
display: flex;
}
</style>
打印的结果:
可以知道 binding.value 就是参数值。
所以上面的 bind()改为
bind(el, binding) { //el是绑定了这个指令的DOM对象
el.style.color = binding.value;
},
就可以实现为自定义指令动态绑定参数值
update 函数:bind 函数只会调用一次,当指令第一次绑定到元素时调用,当 DOM 更新时 bind 函数不会触发。update()函数则是每当 DOM 更新时,都会触发。
<template>
<div class="app-container">
<h1 v-color="color">App根组件</h1>
<button @click="color = color=='red' ? 'blue' : 'red'">变色</button>
<hr />
</div>
</template>
<script>
export default {
data() {
return {
color: "blue",
};
},
directives: {
color: {
//自定义指令名字
bind(el, binding) {
//el是绑定了这个指令的DOM对象
el.style.color = binding.value;
},
},
},
};
</script>
<style lang="less">
.app-container {
padding: 1px 20px 20px;
background-color: #efefef;
}
.box {
display: flex;
}
</style>
上面的示例中,无论怎么点击变色按钮,颜色都不会变,这就是因为 bind()方法只在当指令第一次绑定到元素时调用,且只调用一次,所以此时需要用 update()方法。不能只有 update(),没有 bind()。每当 DOM 更新时,都会触发,但是指令第一次绑定到元素时,update()不会调用。
directives 节点改为以下代码
directives: { color:{ //自定义指令名字 bind(el, binding) {
//el是绑定了这个指令的DOM对象 el.style.color = binding.value;
console.log("bind"); }, update(el, binding) { //el是绑定了这个指令的DOM对象
el.style.color = binding.value; console.log("update"); }, } }
连续点击变色按钮。
简写:上面那张图,可以看到 bind()和 update()方法的业务逻辑一样,此时,可以使用简写形式。
color(el, binding) { //el是绑定了这个指令的DOM对象 el.style.color =
binding.value; },
2.2 公有自定义指令
所有组件都能使用。
在 main.js 中通过**Vue.directive()**进行声明
Vue.directive("color", (el, binding) => {
el.style.color = binding.value;
});
3. ESlint 使用
ESLint 最初是由Nicholas C. Zakas 于 2013 年 6 月创建的开源项目。它的目标是提供一个插件化的 javascript 代码检测工具。(用来团队协作时,不会因为代码规范问题酿成大错,事先规定好代码的规范,不符合规范会报错或警告)
新建 vue 项目时选择
故意在 main.js 中空两行结果:
复制上图红框框的字,到ESLint - 插件化的 JavaScript 代码检测工具查找错误原因
ctrl+F,把复制的内容粘贴上去
修改规则:
可以自己修改规则
4. axios 优化
axios 用法可查看Vue 学习笔记(一)
用之前的方法每次新的组件需要使用 axios 时,都需要反复导入,通过 main.js 和原型链把 axios 挂载到 Vue 的原型上
用的时候不需要重新导入,而是直接通过 this.$http 调用即可
全局配置 axios 的请求根路径:
较高效用法:
- 通过 axios.create()设置好基址
- 其他要用到的地方导入使用即可
5. 路由
5.1 前端路由的概念
路由(router)是对应关系,前端路由则是 Hash 地址与组件之间的对应关系
SPA 和前端路由:SPA 指的是一个 web 网站只有唯一的一个 HTML 页面,通过组件的展示和切换来实现类似多个 HTML 页面的效果。不同组件之间的切换需要通过前端路由来实现。
前端路由的工作方式:
- 用户点击了页面上的路由链接
- 导致 URL 地址栏中的 Hash 值发生变化
- 前端路由监听到 Hash 地址的变化
- 前端路由把当前 Hash 地址的组件渲染到浏览器中
例子:
5.2 vue-router
只能结合 vue 项目进行使用,可以轻松地管理 SPA 项目中组件的切换。
5.2.1 基本用法
- 安装 vue-router
npm install vue-router -S
- 创建路由模块
- 导入并挂载路由模块 src/main.js 入口文件
- 声明路由链接和占位符 用 vue-router 提供的router-link来声明路由链接, 用router-view来声明占位符,用来放路由链接对应的组件
- 声明路由的匹配规则 在 src/router/index.js 路由模块中,通过routes 数组声明路由的匹配规则。
- 路由重定向 经过上面五步后,会发现根路径不会出现首页,这个时候需要路由重定向。 路由重定向:用户在访问地址 A 时,强制用户跳转到特定的组件页面。通过路由规则的 redirect 属性,指定一个新的路由地址。
用 component 也指定 Home 可以实现类似结果。区别是,用重定向的方法相当于是没有根路径,进入根路径时会强制重定向地址。而用 component 也指定 Home 的方法则是有两个一样的页面。
5.2.2 嵌套路由
和路由的基本用法类似,不同的是用来声明路由的匹配规则不能直接写在 router/index.js 下的 routes 中,而应是在已经有的匹配规则中添加 chilaren 节点,再添加嵌套路由匹配规则。
声明路由链接和占位符和路由的基本用法一样
5.2.3 动态路由匹配
动态路由:把 Hash 地址中可变的部分定义为参数项,从而提高路由规则的复用性。使用:
来定义路由的参数项。
经过上面的步骤后可以实现点击三部电影,都出现电影的组件。
可以在展示的组件中,通过**$route.params 参数对象**得到参数值
获取参数的另一个方法,开启 props 传参
5.2.4 编程式导航
- 编程式导航:通过调用 API 方法实现导航的方式,如通过location.href跳转到新页面的方式
- 声明式导航:点击链接实现导航的方式,如点击a 链接和点击 vue 项目中的router-link
vue-router 中的编程式导航 API:
- $router.push(‘hash 地址’):跳转到指定的 hash 地址,并增加一条历史记录
- $router.replace(‘hash 地址’):跳转到指定的 hash 地址,并替换当前历史记录
- **$router.go(‘数值’)**:实现导航历史的前进、后退
- **$router.back()**:回退到历史记录中的上一个界面
- **$router.forward()**:前进到历史记录中的下一个界面
5.2.5 导航守卫
导航守卫可以控制路由的访问权限。
全局前置守卫:每次发生路由的导航跳转时,都会触发全局前置守卫。通过全局前置守卫可以对每个路由进行权限的控制。
通过 router.beforeEach(fn)可以实现声明全局前置守卫。
fn 接收 3 个形参(to, from, next),to是将要访问的路由的信息对象, from是将要离开的路由的信息对象,next 是一个函数,调用 next()表示可以前往。
导航守卫控制权限示例: