day06
day06
- day06- 声明式导航 — 导航链接
- 声明式导航 — 两个类名
- 声明式导航 — 自定义类名(了解)
- 声明式导航 — 查询参数传参
- 声明式导航 — 动态路由传参
- 动态路由参数的可选符(了解)
- Vue 路由 — 重定向
- Vue 路由 — 404
- Vue 路由 — 模式设置
- 编程式导航 — 两种路由跳转方式
- 编程式导航 — path 路径跳转传参
- 编程式导航 — name 命名路由传参
- 面经基础版 — 案例效果分析
- 面经基础版 — 一级路由配置
- 面经基础版 — 二级路由配置
- 面经基础版 — 二级导航高亮
- 面经基础版 — 首页请求渲染、获取数据
- 面经基础版 — 查询参数传参
- 面经基础版 — 缓存组件
- VueCli 自定义创建项目
- ESlint 代码规范及手动修复
- 通过 eslint 插件来实现自动修正
 
声明式导航 — 导航链接
需求
- 实现导航高亮效果
- 如果使用 a 标签进行跳转的话,需要给当前跳转的导航加样式,同时要移除上一个 a 标签的样式,太麻烦
解决方案
- 
vue-router提供了一个全局组件router-link(取代 a 标签)
- 
能跳转,配置 to属性指定路径(必须指定),本质还是 a 标签,写法 to 无需加 #
- 
相比 a 标签的好处就是:能高亮,默认就会提供高亮类名,可以直接设置高亮样式 
- 
语法: <router-link to="path的值">xxx</router-link><div> <div class="footer_wrap"> <router-link to="/find">发现音乐</router-link> <router-link to="/my">我的音乐</router-link> <router-link to="/friend">朋友</router-link> </div> <div class="top"> <!-- 路由出口 → 匹配的组件所展示的位置 --> <router-view></router-view> </div> </div>
通过 router-link 自带的两个样式进行高亮
- 
使用 router-link 跳转后,我们 F12 发现。当前点击的实际代码就是 a 标签默认加了两个 class 的值 router-link-exact-active和router-link-active(用于高亮的类,会自行加删)
- 
我们可以给任意一个 class 属性添加高亮样式即可实现功能 - 
如: .footer_wrap a.router-link-active { background-color: red; }
 
- 
声明式导航 — 两个类名
- 当我们使用 <router-link></router-link>跳转时,自动给当前导航加了两个类名:

router-link-active
- 
模糊匹配(用的多) - to="/my"可以匹配- /my、- /my/a、- /my/b......
 
- 
只要是以 /my 开头的路径 都可以和 to="/my"匹配到
- 
使用场景:在主导航栏点击高亮后,次级导航栏再点击高亮时,主导航栏的高亮不会取消 
router-link-exact-active
- 精确匹配
- to="/my"仅可以匹配到- /my
 
声明式导航 — 自定义类名(了解)
问题
- router-link 的两个高亮类名太长了,能否定制
解决方案
- 在创建路由对象时,额外配置两个配置项即可: linkActiveClass和linkExactActiveClass
const router = new VueRouter({
  routes: [...],
  linkActiveClass: "类名1",
  linkExactActiveClass: "类名2"
})

代码演示
// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    ...
  ], 
  linkActiveClass: 'active', // 配置模糊匹配的类名 active
  linkExactActiveClass: 'exact-active' // 配置精确匹配的类名 exact-active
})
- 
这样再 F12 打开时就会发现是 - 
class="exact-active active"了
- 
css 就是自定义的: .footer_wrap a.active { background-color: red; }- 即可
 
 
- 
声明式导航 — 查询参数传参
- 在跳转路由时,进行传参
- 例如:点击了按钮,需要把点击的内容带到详情页
 
跳转传参
- 
可以通过两种方式,在跳转的时候把所需要的参数传到其他页面中 - 
查询参数传参 
- 
动态路由传参 
 
- 
查询参数传参
- 
传参: - <router-link to="/path?参数名=值"></router-link>
 
- 
接受参数固定用法: - $route.query.参数名
 
代码演示
- Home.vue
<div class="hot-link">
  热门搜索:
  <router-link to="/search?key=xxx">xxx</router-link>
  <router-link to="/search?key=yyy">yyy</router-link>
  <router-link to="/search?key=xyx">xyx</router-link>
</div>
- Search.vue
<template>
  <div class="search">
    <p>搜索关键字: {{ $router.query.key }}</p>
    <p>搜索结果: </p>
    <ul>
      <li>.............</li>
    </ul>
  </div>
</template>
<script>
export default {
  created () {
    // 在created中,获取路由参数: this.$route.query.参数名
    console.log(this.$route.query.key);
  }
}
</script>
声明式导航 — 动态路由传参
动态路由传参方式
- 
配置动态路由 - 
动态路由后面的参数可以随便起名,但要有语义(如下述的 words) const router = new VueRouter({ routes: [ ..., { path: '/search/:words', component: Search } ] })
 
- 
- 
配置导航链接 - to="/path/参数值"
- 即:<router-link to="/search/xxx">xxx为想传的参数</router-link>
 
- 
对应页面组件接受参数 - $route.params.参数名
- params 后面的参数名要和动态路由配置的参数保持一致(即上述的 words)
- 即:console.log(this.$route.params.words);
 
查询参数传参 VS 动态路由传参
- 查询参数传参(比较适合传多个参数)
- 跳转:to="/path?参数名=值&参数名2=值"(键值对方式)
- 获取:$route.query.参数名
 
- 跳转:
- 动态路由传参(优雅简洁,传单个参数比较方便)
- 配置动态路由:path: "/path/:参数名"
- 跳转:to="/path/参数值"
- 获取:$route.params.参数名
 
- 配置动态路由:
- 注意:动态路由也可以传多个参数,但一般只传一个
动态路由参数的可选符(了解)
- 
/search/:words表示,必须要传参数,即进入不到#/search地址的页面了
- 
如果不传参数,也希望匹配到某页面(即可选的),可以加个可选符 " ?" const router = new VueRouter({ routes: [ ... { path: '/search/:words?', component: Search } ] })
Vue 路由 — 重定向
问题
- 网页打开时, url 默认是 / 路径,未匹配到组件会出现空白(组件不存在就会出现空白)
解决方案
- 重定向:匹配 / 后, 强制跳转 /home路径(也就是显示/home所指向的组件)
语法
{ path: 匹配路径, redirect: 重定向到的路径 },
比如:
{ path:'/' ,redirect:'/home' }
代码演示
const router = new VueRouter({
  routes: [
    { path: '/', redirect: '/home'},
 	 ...
  ]
})
Vue 路由 — 404
作用
- 当路径找不到匹配时,给个提示页面
位置
- 404 的路由,虽然配置在任何一个位置都可以,但一般都配置在其他路由规则的最后面
语法
- path: "*"(任意路径)— 前面不匹配就命中最后这个
import NotFind from '@/views/NotFind'
const router = new VueRouter({
  routes: [
    ...
    { path: '*', component: NotFound } //最后一个,*就表示任意,匹配NotFound组件
  ]
})
代码示例
- NotFound.vue
<template>
  <div>
    <h1>404 Not Found</h1>
  </div>
</template>
- router/index.js
...
import NotFound from '@/views/NotFound'
...
// 创建了一个路由对象
const router = new VueRouter({
  routes: [
     ...
    { path: '*', component: NotFound }
  ]
})
export default router
Vue 路由 — 模式设置
问题
- 路由的路径看起来不自然,有 #,想办法切成真正路径形式
- hash 路由(默认),例如:http://localhost:8080/#/home
- history 路由(常用),例如:http://localhost:8080/home(以后上线需要服务器端支持,开发环境 webpack 给规避掉了 history 模式的问题)
 
语法
const router = new VueRouter({
    mode:'histroy', //默认是 hash
    routes:[]
})
编程式导航 — 两种路由跳转方式
- 
点击按钮跳转的实现,就像是点击登录到登录页面一样,这里通常就不会用导航链接了 
- 
而是用编程式导航:用 JS 代码来进行跳转 - 原来都是用 location.href=新链接来实现,但 vue 这里是跳路由,本质上是在单页中,所以不能在这样用了,有专门的跳转方式
 
- 原来都是用 
语法
- 
两种语法: - 
path 路径跳转(简易方便) 
- 
name 命名路由跳转(适合 path 路径长的场景) 
 
- 
path 路径跳转语法
- 特点:简易方便(直接往路由上跳)
- 写在按钮之类的方法事件上:
//简单写法:
this.$router.push('路由路径')
// 如:this.$router.push('/search')
//完整写法:
this.$router.push({
  path: '路由路径'
})
- 完整的写法在之后传参的时候会更适用
name 命名路由跳转语法
- 
特点:适合 path 路径长、层级深的场景 
- 
前提: - 
必须在路由规则中配置 name 配置项 { name: '路由名', path: '/path/xxx/yyy/zzz', component: XXX },
- 
通过 name 来进行跳转 this.$router.push({ name: '路由名' })
 
- 
编程式导航 — path 路径跳转传参
问题
- 点击搜索按钮,跳转需要把文本框中输入的内容传到下一个页面
两种传参方式
- 查询参数
- 动态路由传参
传参
- 两种跳转方式,对于两种传参方式都支持:
- path 路径跳转传参
- name 命名路由跳转传参
 
path 路径跳转传参(query 传参)
// 简单写法(参数值可以是${双向绑定的参数值})
this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
// 完整写法(更适合传参 —— 尤其是多个参数的时候,参数值可以是this.xxx动态)
this.$router.push({
  path: '/路径',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})
- 不管哪种,接受参数的方式依然是:$route.query.参数名
path 路径跳转传参(动态路由传参)
- 注意:前提是路由规则已经配置成动态路由的格式 /xx/:yy?
//简单写法(参数值可以是${双向绑定的参数值})
this.$router.push('/路径/参数值')
//完整写法(参数值可以是${双向绑定的参数值})
this.$router.push({
  path: '/路径/参数值'
})
- 接受参数的方式依然是:$route.params.动态路由的冒号后的命名yy
编程式导航 — name 命名路由传参
name 命名路由跳转传参(query 传参)
this.$router.push({
  name: '路由名字',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})
- 还是 $route.query.参数名
name 命名路由跳转传参(动态路由传参)
- 注意:前提是路由规则已经配置成动态路由的格式 /xx/:yy?
this.$router.push({
  name: '路由名字',
  params: { // params传params接收
    参数名: '参数值',
  }
})
- 依旧是 $route.params.动态路由的冒号后的命名yy
总结
- 
编程式导航,如何跳转传参: 
- 
path路径跳转 - 
query传参 this.$router.push('/路径?参数名1=参数值1&参数2=参数值2') this.$router.push({ path: '/路径', query: { 参数名1: '参数值1', 参数名2: '参数值2' } })
- 
动态路由传参 this.$router.push('/路径/参数值') this.$router.push({ path: '/路径/参数值' })
 
- 
- 
name 命名路由跳转 - 
query传参 this.$router.push({ name: '路由名字', query: { 参数名1: '参数值1', 参数名2: '参数值2' } })
- 
动态路由传参 (需要配动态路由) this.$router.push({ name: '路由名字', params: { 参数名: '参数值', } })
 
- 
面经基础版 — 案例效果分析
功能分析
- 通过演示效果发现,主要的功能页面有两个,一个是列表页,一个是详情页,并且在列表页点击时可以跳转到详情页
- 底部导航可以来回切换,并且切换时,只有上面的主题内容在动态渲染
实现思路分析:配置路由 + 功能实现
- 
配置路由 - 
首页和面经详情页两个大页面,两个一级路由 
- 
首页内嵌套四个可切换的小页面(嵌套二级路由) 
- 
面经详情是单独的一个大页面 
 
- 
- 
实现功能 - 
首页请求渲染 
- 
跳转传参到详情页,详情页动态渲染 
- 
组件缓存,性能优化 
 
- 
面经基础版 — 一级路由配置
- 针对 router/index.js 文件进行一级路由配置
...
import newFirst from '@/views/newFirst.vue'
import info from '@/views/info.vue'
...
const router = new VueRouter({
  routes: [
    {
      path: '/',
      component: newFirst
    },
    {
      path: '/info',
      component: info
    }
  ]
})
面经基础版 — 二级路由配置
- 二级路由也叫嵌套路由,当然也可以嵌套三级、四级 ...
使用场景
- 当在页面中点击链接跳转,只是部分内容切换时,我们可以使用嵌套路由
语法
- 在一级路由下,配置 children 属性即可
- 配置二级路由的出口
举例
- 
在一级路由下,配置 children 属性 - 
注意:一级的路由 path 需要加 /二级路由的 path 不需要加/... import xxxx from '@/views/xxxx.vue' import yyyy from '@/views/yyyy.vue' ... const router = new VueRouter({ routes: [ { path: '/', component: newFirst, // 别光记得二级路由,把主的显示忘了(加个重定向 —— 初进默认显示页面) redirect: '/xxxx' children:[ //children中的配置项 跟一级路由中的配置项一模一样 {path:'/xxxx',component:Xxxx}, {path:'/yyyy',component:Yyyy}, ] } ] })
 
- 
- 
注意配置了二级路由后不要忘了 /时的显示,否则就是空白 —— 重定向
- 
配置二级路由的出口 <router-view></router-view>- 
当然此处的 <router-view></router-view>和对应的<a href>写在一起
- 
注意: 配置了嵌套路由,一定配置对应的路由出口,否则不会渲染出对应的组件 
 
- 
- 
newFirst.vue 
<template>
  <div class="wsad">
    <div class="content">
      <!-- 内容部分 -->
      <router-view></router-view>
    </div>
    <nav class="asdfg">
      <a href="#/xxxx">xxxx显示</a>
      <a href="#/yyyy">yyyy显示</a>
    </nav>
  </div>
</template>
面经基础版 — 二级导航高亮
- 将 a 标签替换成 <router-link></router-link>组件,配置 to 属性,不用加 #
- 结合高亮类名实现高亮效果(推荐模糊匹配:router-link-active)
<nav class="tabbar">
  <router-link to="/article">面经</router-link>
  <router-link to="/collect">收藏</router-link>
  <router-link to="/like">喜欢</router-link>
  <router-link to="/user">我的</router-link>
</nav>
<style>
  // F12 可见渲染后真正样式,和内在真正作用的class
   a.router-link-active { 
      color: orange;
    }
</style>
面经基础版 — 首页请求渲染、获取数据
- 
安装 axios 用来发请求 
- 
看接口文档,确认请求方式,请求地址,请求参数 
- 
created 中发送请求,获取数据,存储到 data 中 
- 
页面动态渲染 
代码实现
- 
安装 axios - yarn add axios或- npm i axios
- i就是- install
 
- 
接口文档 
请求地址: https://......
请求方式: get
- created 中发送请求,获取数据,存储到 data 中
 data() {
    return {
      articelList: [],
    }
 },
 async created() {
		const res = await axios.get('https://......')
		this.articelList = res.data.result.rows
 },
- 需要的时候调用 articelList即可
面经基础版 — 查询参数传参
- 
跳转详情页需要把当前点击的文章 id 传给详情页,获取数据(两种方式:) - 
查询参数传参: this.$router.push('/detail?参数1=参数值&参数2=参数值')
- 
动态路由传参:先改造路由再传参 this.$router.push('/detail/参数值')
 
- 
查询参数传参实现
- xxxx.vue
<template>
  ... 
      v-for="item in List" :key="item.id" 
      @click="$router.push(`/detail?id=${item.id}`)">
  ...
</template>
- xxxxDetail.vue
  created(){
    console.log(this.$route.query.id)
  }
动态路由传参
- 改造路由
- 动态传参
- 在详情页获取参数
代码实现
- 改造路由
- router/index.js
...
  {
      path: '/detail/:id',
      component: ArticleDetail
  }
- Article.vue 发送
<div class="article-item" 
     v-for="item in articelList" :key="item.id" 
     @click="$router.push(`/detail/${item.id}`)">
       ....
 </div>
- ArticleDetail.vue 接收
  created(){
    console.log(this.$route.params.id)
  }
额外优化功能点 — 点击回退跳转到上一页
- ArticleDetail.vue
<template>
  <div class="article-detail-page">
    <nav class="nav"><span class="back" @click="$router.back()"><</span> 面经详情</nav>
     ....
  </div>
</template>
- 用 back()返回即可
面经基础版 — 缓存组件
问题
- 从面经列表点到详情页,又点返回,数据重新加载了
- 现在想要试着、希望回到原来的位置
- 不再重新加载
 
原因
- 当路由被跳转后,原来所看到的组件就被销毁了(会执行组件内的 beforeDestroy 和 destroyed 生命周期钩子),重新返回后组件又被重新创建了(会执行组件内的 beforeCreate,created,beforeMount,Mounted 生命周期钩子),所以数据被重又加载了
解决方案
- 利用 keep-alive 把原来的组件给缓存下来
关于 keep-alive
- 
keep-alive 是 Vue 的内置组件,当它包裹动态组件(也就是这里的 <router-view></router-view>)时,会缓存不活动的组件实例,而不是销毁它们
- 
keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件中 
- 
优点: - 在组件切换过程中把切换出去的组件保留在内存中,防止重复渲染 DOM
- 减少加载时间及性能消耗,提高用户体验性
 
- 
App.vue 
<template>
  <div class="">
    <keep-alive>
      <router-view></router-view>
    </keep-alive>
  </div>
</template>
- 存在问题:
- 上述缓存了所有被切换的组件,很可能会出现错乱
 
keep-alive 的三个属性(按需所配)
- 
include : 组件名数组,只有匹配的组件会被缓存 
- 
exclude : 组件名数组,任何匹配的组件都不会被缓存 - 只写了不缓存的,所有一般都配合 max 使用
 
- 
max : 最多可以缓存多少组件实例 
- 
结合上述属性,App.vue: 
<template>
  <div class="h5-wrapper">
    <keep-alive :include="['LayoutPage']">
<!--  或者是写数组:<keep-alive :include="keepArr">  -->
      <router-view></router-view>
    </keep-alive>
  </div>
</template>
额外的两个生命周期钩子
- keep-alive 的使用会触发两个生命周期函数
- activated 当组件被激活(使用)的时候触发 —— 进入这个页面的时候触发
- deactivated 当组件失活(不被使用)的时候触发 —— 离开这个页面的时候触发
- 组件缓存后就不会执行组件的 created,mounted,destroyed 等钩子了
 
- 所以其提供了 actived 和 deactived 钩子,帮我们实现一些业务需求
VueCli 自定义创建项目
- 
注意,这里的前提是 npm -v正确显示版本,且 node.js 里有 vue.cmd- 一般下载了 node 就顺带安装了 npm(可以理解为一种 node.js 内置的一套包管理工具,就可以 npm xxx 下载依赖包了)
- 没有 vue.cmd 就 npm install -g vue安装好 vue
- 再继续下一步安装脚手架
 
- 
安装脚手架(已安装) npm install -g @vue/cli- 然后就可以 npm list vue查看 vue 版本指令
- vue -v查看脚手架版本指令
 
- 然后就可以 
- 
创建项目 
vue create 项目名
- 选项
Vue CLI v5.0.8
? Please pick a preset:
  Default ([Vue 3] babel, eslint)
  Default ([Vue 2] babel, eslint)
> Manually select features     这次选择自定义
- 手动选择下述四个(空格就是选中)

- 选择vue的版本
  3.x
> 2.x
- 是否使用 history 模式

- 选择 css 预处理

- 选择 eslint 的风格(eslint 代码规范的检验工具,检验代码是否符合规范)
- 比如:const age = 18; => 报错!多加了分号!后面有工具,一保存,全部格式化成最规范的样子

- 选择校验的时机(直接回车)

- 选择配置文件的生成方式(直接回车)

- 是否保存预设,下次直接使用? => 不保存,输入 N

- 
等待安装,项目初始化完成:绿色 success 
- 
启动项目 
npm run serve
ESlint 代码规范及手动修复
- 代码规范:一套写代码的约定规则。例如:赋值符号的左右是否需要空格?一句结束是否是要加;?等
- ESLint:是一个代码检查工具,用来检查你的代码是否符合指定的规则(你和你的团队可以自行约定一套规则)
- 创建项目时,使用的是 JavaScript Standard Style 代码风格的规则
JavaScript Standard Style 规范说明
- 
建议把:https://standardjs.com/rules-zhcn.html 看一遍,然后在写的时候, 遇到错误就查询解决 
- 
下面是这份规则中的一小部分: - 
字符串使用单引号 — 需要转义的地方除外 
- 
无分号 
- 
关键字后加空格 — if (condition) { ... }
- 
函数名后加空格 — function name (arg) { ... }
- 
坚持使用全等 ===摒弃==一 但在需要检查null || undefined时可以使用obj == null
- 
等等 
 
- 
代码规范错误
- 如果你的代码不符合 standard 的要求会红色提醒
手动修正
- 如果不认识命令行中的语法报错是什么意思,可以根据错误代码(func-call-spacing, space-in-parens,.....)去 ESLint 规则列表中查找其具体含义
- 打开 ESLint 规则表,页面搜索这个代码,查找对该规则的一个释义

通过 eslint 插件来实现自动修正
- eslint 会自动高亮错误显示
- 通过配置,eslint会自动帮助我们修复错误
- 安装插件

- 
如何配置 - 
左下角设置,点击右上角打开设置:settings.json 
- 
在打括号内加入以下语句: // 当保存的时候,eslint自动帮我们修复错误 "editor.codeActionsOnSave": { "source.fixAll": true }, // 保存代码,不自动格式化 "editor.formatOnSave": false
 
- 
- 
注意:eslint 的配置文件必须在根目录下,这个插件才能才能生效。打开项目必须以根目录打开,一次打开一个项目 
- 
注意:使用了 eslint 校验之后,把 vscode 带的那些格式化工具全禁用了 Beatify 
- 
settings.json 参考: 
{
    "window.zoomLevel": 2,
    "workbench.iconTheme": "vscode-icons",
    "editor.tabSize": 2,
    "emmet.triggerExpansionOnTab": true,
    // 当保存的时候,eslint自动帮我们修复错误
    "editor.codeActionsOnSave": {
        "source.fixAll": true
    },
    // 保存代码,不自动格式化
    "editor.formatOnSave": false
}
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号