Vue学习笔记(三)

Vue
329
0
0
2023-03-12

Vue 学习笔记(三)

1. 插槽

插槽允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。

我们使用标签时,开始标签和结束标签之间之前都没有写东西。组件的标签和正常的双标签,如 div、p 等一样,可以在里面写东西。但是,直接在里面写,会发现,写的东西不会显示出来,也找不到了,被丢弃了。其实这个也挺好理解的,组件本来就有东西了,vue 又不知道你写的东西要插到哪里去。所以,vue 提供了插槽,可以在想要插的地方加上一个插槽,之后再把内容插过去。

用法例子:

img

效果:

img

没有预留插槽的话,用户提供的自定义内容都会被丢弃。

  • 封装组件时,可以为预留的插槽提供默认内容,如果组件的使用者没有为插槽提供内容,默认内容就会生效。

img

1.1 具名插槽

img

上面的例子中,有多个插槽,输入的文章头这段信息原本想插在第一个插槽里面的,但是会发现,它插到了所有的插槽中。

这个时候就需要使用具名插槽了

具名插槽:如果在封装组件时需要预留多个插槽,则需要为每个插槽指定具体的名称。这种带有具体名称的插槽就叫”具名插槽”。

img

如果没有给插槽起名字,则插槽默认叫”default”。要插入插槽的内容如果没有指定要插到哪里去,则会插到名为”default”的插槽中。

这就是为什么上面没有使用具名插槽时,内容会插到所有的插槽中去。

1.2 作用域插槽

在封装组件时,可以为预留的 slot 插槽绑定 props 数据,这个带有 props 数据的 slot 插槽叫做作用域插槽

img

解构插槽:因为得到的数据是对象形式的,所以可以解构,得到要用的数据

img

2. 自定义指令

2.1 私有自定义指令

在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令

img

为自定义指令动态绑定参数值

通过=的方式,为当前指令动态添加参数值,通过形参中的第二个参数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>

打印的结果:

img

可以知道 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"); }, } }

连续点击变色按钮。

img

简写:上面那张图,可以看到 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 项目时选择

img

img

img

故意在 main.js 中空两行结果:

img

复制上图红框框的字,到ESLint - 插件化的 JavaScript 代码检测工具查找错误原因

img

ctrl+F,把复制的内容粘贴上去

img

修改规则

可以自己修改规则

img

img

img

4. axios 优化

axios 用法可查看Vue 学习笔记(一)

用之前的方法每次新的组件需要使用 axios 时,都需要反复导入,通过 main.js 和原型链把 axios 挂载到 Vue 的原型上

img

用的时候不需要重新导入,而是直接通过 this.$http 调用即可

img

全局配置 axios 的请求根路径

img

较高效用法

  1. 通过 axios.create()设置好基址

img

  1. 其他要用到的地方导入使用即可

img

5. 路由

5.1 前端路由的概念

路由(router)是对应关系,前端路由则是 Hash 地址与组件之间的对应关系

SPA 和前端路由:SPA 指的是一个 web 网站只有唯一的一个 HTML 页面,通过组件的展示和切换来实现类似多个 HTML 页面的效果。不同组件之间的切换需要通过前端路由来实现。

前端路由的工作方式

  1. 用户点击了页面上的路由链接
  2. 导致 URL 地址栏中的 Hash 值发生变化
  3. 前端路由监听到 Hash 地址的变化
  4. 前端路由把当前 Hash 地址的组件渲染到浏览器中

例子:

img

5.2 vue-router

只能结合 vue 项目进行使用,可以轻松地管理 SPA 项目中组件的切换。

5.2.1 基本用法

  1. 安装 vue-router npm install vue-router -S
  2. 创建路由模块

img

  1. 导入并挂载路由模块 src/main.js 入口文件

img

  1. 声明路由链接占位符 用 vue-router 提供的router-link来声明路由链接, 用router-view来声明占位符,用来放路由链接对应的组件

img

  1. 声明路由的匹配规则 在 src/router/index.js 路由模块中,通过routes 数组声明路由的匹配规则。

img

  1. 路由重定向 经过上面五步后,会发现根路径不会出现首页,这个时候需要路由重定向路由重定向:用户在访问地址 A 时,强制用户跳转到特定的组件页面。通过路由规则的 redirect 属性,指定一个新的路由地址。

img

用 component 也指定 Home 可以实现类似结果。区别是,用重定向的方法相当于是没有根路径,进入根路径时会强制重定向地址。而用 component 也指定 Home 的方法则是有两个一样的页面。

5.2.2 嵌套路由

和路由的基本用法类似,不同的是用来声明路由的匹配规则不能直接写在 router/index.js 下的 routes 中,而应是在已经有的匹配规则中添加 chilaren 节点,再添加嵌套路由匹配规则。

声明路由链接和占位符和路由的基本用法一样

img

img

img

5.2.3 动态路由匹配

动态路由:把 Hash 地址中可变的部分定义为参数项,从而提高路由规则的复用性。使用:来定义路由的参数项。

img

img

经过上面的步骤后可以实现点击三部电影,都出现电影的组件。

可以在展示的组件中,通过**$route.params 参数对象**得到参数值

img

获取参数的另一个方法,开启 props 传参

img

img

img

5.2.4 编程式导航

  • 编程式导航:通过调用 API 方法实现导航的方式,如通过location.href跳转到新页面的方式
  • 声明式导航点击链接实现导航的方式,如点击a 链接和点击 vue 项目中的router-link

vue-router 中的编程式导航 API

  1. $router.push(‘hash 地址’):跳转到指定的 hash 地址,并增加一条历史记录
  2. $router.replace(‘hash 地址’):跳转到指定的 hash 地址,并替换当前历史记录
  3. **$router.go(‘数值’)**:实现导航历史的前进、后退

img

  1. **$router.back()**:回退到历史记录中的上一个界面
  2. **$router.forward()**:前进到历史记录中的下一个界面

5.2.5 导航守卫

导航守卫可以控制路由的访问权限

img

全局前置守卫:每次发生路由的导航跳转时,都会触发全局前置守卫。通过全局前置守卫可以对每个路由进行权限的控制。

通过 router.beforeEach(fn)可以实现声明全局前置守卫。

fn 接收 3 个形参(to, from, next),to是将要访问的路由的信息对象, from是将要离开的路由的信息对象,next 是一个函数,调用 next()表示可以前往。

img

导航守卫控制权限示例:

img