day06vue2学习

day06

路由的封装抽离

问题:所有的路由配置都堆在main.js中不太合适么?不好,会加大代码的复杂度

目标:将路由模块抽离出来。好处:差分模块,利于维护。

大致的做法就是,将路由相关的东西都提取到router文件下的index.js中。

以后的main.js文件中

在这里插入图片描述

router文件的index.js文件

// import Find from './views/Find'
// import My from './views/My'
// import Friend from './views/Friend'
// 在这里由于以后可能会移动文件夹,到时候需要回来改源代码,这时可以用绝对路径来适当的避免这种情况,而 @ 又可以简化绝对路径的写法

import Find from '@/views/Find';
import My from '@/views/My';
import Friend from '@/views/Friend';

// @ 代表的就是src目录 @/views 表示src目录下的views文件夹

import VueRouter from 'vue-router';
import Vue from 'vue'; // 由于文件中没有Vue对象所以要导入Vue对象

Vue.use(VueRouter); // VueRouter插件初始化

const router = new VueRouter({
	// routes路由规则们
	// route一条路由规则 { path:路径,componeroutes: 组件名 }
	routes: [
        { path: "/find" , component: Find },
        { path: "/my " , component: My },
        { path: '/friend ' , component: Friend }
    	]
})

// 导出 router 
export default router;

main.js中

import Vue from "vue'
import App from "./App.vue'
// 导入封装的router文件
import router from "./router/index'

vue.config-productionTip = false

new Vue({
	render: h => h(App),
    router // 注入vue路由
}).$mount('#app');

一、声明式导航-导航链接

1.需求

实现导航高亮效果

在这里插入图片描述

如果使用a标签进行跳转的话,需要给当前跳转的导航加样式,同时要移除上一个a标签的样式,太麻烦!!!

2.解决方案

vue-router 提供了一个全局组件 router-link (取代 a 标签)

  • 能跳转,配置 to 属性指定路径(必须) 。本质还是 a 标签 ,to 无需 #
  • 能高亮,默认就会提供高亮类名,可以直接设置高亮样式

以前的写法:

如果是a标签,需要添加类名来让其高亮

在这里插入图片描述

学完后的写法:

如果是 router-link 会默认提供高亮类名

router-link 最后会直接渲染成 a 标签,并且会在a标签上添加一些特定的类名,那个a标签被选中了,特定的类名就会添加到被选中的a标签上。

在这里插入图片描述

语法: 发现音乐

  <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>
<style>
    a.router-link-active {
        background-color: green;
    }
</style>

3.通过router-link自带的两个样式进行高亮

使用router-link跳转后,我们发现。当前点击的链接默认加了两个class的值 router-link-exact-activerouter-link-active

我们可以给任意一个class属性添加高亮样式即可实现功能

4.总结

  • router-link是什么?
  • router-link怎么用?
  • router-link的好处是什么?

二、声明式导航-两个类名

当我们使用<router-link></router-link>跳转时,自动给当前导航加了两个类名

在这里插入图片描述

1.router-link-active

模糊匹配(用的多)

to=“/my” 可以匹配 /my /my/a /my/b …

只要是以/my开头的路径 都可以和 to="/my"匹配到

2.router-link-exact-active

精确匹配

to=“/my” 仅可以匹配 /my 无法匹配 /my/a /my/b …

3.在地址栏中输入二级路由查看类名的添加

4.总结

  • router-link 会自动给当前导航添加两个类名,有什么区别呢?

三、声明式导航-自定义类名(了解)

1.问题

router-link的两个高亮类名 太长了,我们希望能定制怎么办

在这里插入图片描述

2.解决方案

我们可以在创建路由对象时,额外配置两个配置项即可。 linkActiveClasslinkExactActiveClass

const router = new VueRouter({
  routes: [...],
  linkActiveClass: "类名1",
  linkExactActiveClass: "类名2"
})

在这里插入图片描述

3.代码演示

// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    ...
  ], 
  linkActiveClass: 'active', // 配置模糊匹配的类名
  linkExactActiveClass: 'exact-active' // 配置精确匹配的类名
})

4.总结

如何自定义router-link的两个高亮类名

四、声明式导航-查询参数传参

1.目标

在跳转路由时,进行传参

在这里插入图片描述

比如:现在我们在搜索页点击了热门搜索链接,跳转到详情页,需要把点击的内容带到详情页,改怎么办呢?

2.跳转传参

我们可以通过两种方式,在跳转的时候把所需要的参数传到其他页面中

  • 查询参数传参
  • 动态路由传参

3.查询参数传参

  • 如何传参?和以前的地址参数是差不多的。

  • 如何接受参数

    固定用法:$router.query.参数名

4.代码演示

App.vue

<template>
  <div id="app">
    <div class="link">
      <router-link to="/home">首页</router-link>
      <router-link to="/search">搜索页</router-link>
    </div>

    <router-view></router-view>
  </div>
</template>

<script>
export default {};
</script>

<style scoped>
.link {
  height: 50px;
  line-height: 50px;
  background-color: #495150;
  display: flex;
  margin: -8px -8px 0 -8px;
  margin-bottom: 50px;
}
.link a {
  display: block;
  text-decoration: none;
  background-color: #ad2a26;
  width: 100px;
  text-align: center;
  margin-right: 5px;
  color: #fff;
  border-radius: 5px;
}
</style>

Home.vue

<template>
  <div class="home">
    <div class="logo-box"></div>
    <div class="search-box">
      <input type="text">
      <button>搜索一下</button>
    </div>
    <div class="hot-link">
      热门搜索:
      <router-link to="/search?word=黑马程序员">黑马程序员</router-link>
      <router-link to="/search?word=前端培训">前端培训</router-link>
      <router-link to="/search?word=如何成为前端大牛">如何成为前端大牛</router-link>
    </div>
  </div>
</template>

<script>
export default {
  name: 'FindMusic'
}
</script>

<style>
.logo-box {
  height: 150px;
  background: url('@/assets/logo.jpeg') no-repeat center;
}
.search-box {
  display: flex;
  justify-content: center;
}
.search-box input {
  width: 400px;
  height: 30px;
  line-height: 30px;
  border: 2px solid #c4c7ce;
  border-radius: 4px 0 0 4px;
  outline: none;
}
.search-box input:focus {
  border: 2px solid #ad2a26;
}
.search-box button {
  width: 100px;
  height: 36px;
  border: none;
  background-color: #ad2a26;
  color: #fff;
  position: relative;
  left: -2px;
  border-radius: 0 4px 4px 0;
}
.hot-link {
  width: 508px;
  height: 60px;
  line-height: 60px;
  margin: 0 auto;
}
.hot-link a {
  margin: 0 5px;
}
</style>

Search.vue

<template>
  <div class="search">
    <p>搜索关键字: {{ $route.query.word }}</p>
    <p>搜索结果: </p>
    <ul>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'MyFriend',
  created () { // 上面的参数有了,但是如何获取下面的li的内容呢
    // 就用created钩子函数,一旦dom元素加载完成就直接向后台获取参数
    // 在created中,获取路由参数,也可以用$route.query.参数名,但是必须在created函数中必须在前面加this,
    // this在created函数中不可以省略,但是在template标签中可以省略。
      console.log(this.$route.query.word);
  }
}
</script>

<style>
.search {
  width: 400px;
  height: 240px;
  padding: 0 20px;
  margin: 0 auto;
  border: 2px solid #c4c7ce;
  border-radius: 5px;
}
</style>

router/index.js

import Home from '@/views/Home'
import Search from '@/views/Search'
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter) // VueRouter插件初始化

// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/search', component: Search }
  ]
})

export default router

main.js

...
import router from './router/index'
...
new Vue({
  render: h => h(App),
  router
}).$mount('#app')

五、声明式导航-动态路由传参

1.动态路由传参方式

  • 配置动态路由

    动态路由后面的参数可以随便起名,但要有语义

    const router = new VueRouter({
      routes: [
        ...,
        { 
          path: '/search/:words', component: Search 
        }
      ]
    })
    
  • 配置导航链接

    to=“/path/参数值”

  • 对应页面组件接受参数

    $route.params.参数名

    params后面的参数名要和动态路由配置的参数保持一致

上面的部分代码:

router/index.js

// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/search/:word', component: Search }
    // 配路由规则
  ]
})

Home.vue

<template>
  <div class="home">
    <div class="logo-box"></div>
    <div class="search-box">
      <input type="text">
      <button>搜索一下</button>
    </div>
    <div class="hot-link">
      热门搜索:
      <router-link to="/search/黑马程序员">黑马程序员</router-link>
      <router-link to="/search/前端培训">前端培训</router-link>
      <router-link to="/search/如何成为前端大牛">如何成为前端大牛</router-link>
      // 配导航链接
    </div>
  </div>
</template>

Search.vue

<template>
  <div class="search">
    // 传递参数,接收参数
    <p>搜索关键字: {{ $route.parmas.word }}</p>
    <p>搜索结果: </p>
    <ul>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'MyFriend',
  created () { 
      console.log(this.$route.parmas.word);
  }
}
</script>

2.查询参数传参 VS 动态路由传参

  1. 查询参数传参 (比较适合传多个参数)

  2. 跳转:to=“/path?参数名=值&参数名2=值”

  3. 获取:$route.query.参数名

  4. 动态路由传参 (优雅简洁,传单个参数比较方便)

    1. 配置动态路由:path: “/path/:参数名”
    2. 跳转:to=“/path/参数值”
    3. 获取:$route.params.参数名

    注意:动态路由也可以传多个参数,但一般只传一个

3.总结

声明式导航跳转时, 有几种方式传值给路由页面?

  • 查询参数传参(多个参数)
  • 动态路由传参(一个参数,优雅简洁)

六、动态路由参数的可选符(了解)

1.问题

配了路由 path:“/search/:words” 为什么按下面步骤操作,会未匹配到组件,显示空白?

在这里插入图片描述

2.原因

/search/:words 表示,必须要传参数。如果不传参数,也希望匹配,可以加个可选符"?"

const router = new VueRouter({
  routes: [
 	...
    { path: '/search/:words?', component: Search }
  ]
})

七、Vue路由-重定向

1.问题

网页打开时, url 默认是 / 路径,未匹配到组件时,会出现空白。

在这里插入图片描述

2.解决方案

重定向 → 匹配 / 后, 强制跳转 /home 路径

重定向的效果可以通过,vue的钩子函数created和编程式导航的两种跳转方式来实现。

3.语法

{ path: 匹配路径, redirect: 重定向到的路径 },
比如:
{ path:'/' ,redirect:'/home' }
// 这里的 path 不一定是 '/' 也可以换成其他的路径,redirect 也可以换成其他的路径

4.代码演示

const router = new VueRouter({
  routes: [
    { path: '/', redirect: '/home' }, // 最好是放在第一个
    { path: '/Home', component: Home },
    { path: '/Search/:word?', component: Search }
 	 ...
  ]
})

八、Vue路由-404

1.作用

当路径找不到匹配时,给个提示页面

2.位置

404的路由,虽然配置在任何一个位置都可以,但一般都配置在其他路由规则的最后面

3.语法

path: “*” (任意路径) – 前面不匹配就命中最后这个

import NotFind from '@/views/NotFind'

const router = new VueRouter({
  routes: [
    ...
    { path: '*', component: NotFind } // 必须放在最后一个
  ]
})

4.代码示例

NotFound.vue

<template>
  <div>
    <h1>404 Not Found</h1>
  </div>
</template>

<script>
export default {

}
</script>

<style>
</style>

router/index.js

...
import NotFound from '@/views/NotFound'
...

// 创建了一个路由对象
const router = new VueRouter({
  routes: [
     ...
    { path: '*', component: NotFound }
  ]
})

export default router

九、Vue路由-模式设置

1.问题

路由的路径看起来不自然, 有#,能否切成真正路径形式?

  • hash路由(默认) 例如: http://localhost:8080/#/home
  • history路由(常用) 例如: http://localhost:8080/home (以后上线需要服务器端支持,服务端需要配置一些访问规则,如果不配置会出现页面空白的情况,开发环境中webpack给规避掉了history模式的问题)

hash路由是基于a标签毛链接跳转实现的。

history路由是基于新增的html5 history API 来实现的。

2.语法

const router = new VueRouter({
    mode:'histroy', //默认是hash
    routes:[]
})

注意:一旦采用了 history 模式,地址栏就没有 # 了,这时是需要后台配置访问规则的。具体是什么访问规则,和后端说一下,后端自己会明白的。

十、编程式导航-两种路由跳转方式

1.问题

点击按钮跳转如何实现?

在这里插入图片描述

2.方案

编程式导航:用JS代码来进行跳转,直接 location.herf=“路径”。

但是,vue路由的本质就是一个单页,无法通过 JS 的 location.herf 来进行跳转。于是就有了路由专有的跳转方式。

3.语法

两种语法:

  • path 路径跳转 (简易方便)
  • name 命名路由跳转 (适合 path 路径长的场景)

4.path路径跳转语法

特点:简易方便

//简单写法
this.$router.push('路由路径');
// 注意这里是 router 而不是,route,要注意区分。
// router 指的是一个大的router对象。

//完整写法 完整写法会在后面的传参的时候用到
this.$router.push({
  path: '路由路径'
})

5.代码演示 path跳转方式

Home.vue

<template>
	...
      <button @click="toSearch">搜索一下</button>
	...
</template>

<script>
export default {
  name: 'FindMusic',
  methods: {
    toSearch () {
      this.$router.push('/Search');
      // 下面这样也是可以的
      this.$router.push({
        path: '/Search',
      })
    }
  }
}
</script>

6.name命名路由跳转

特点:适合 path 路径长的场景

语法:

  • 路由规则,必须事先给要跳转的配置项添加name属性,如果没有name配置项,是无法跳转到对应的配置项的。

    ...
    { name: '路由名', path: '/path/xxx', component: XXX },
    ...
    
  • 通过name来进行跳转

    this.$router.push({
      name: '路由名'
    })
    

name跳转和path跳转互不冲突,可以一起使用。

7.代码演示通过name命名路由跳转

8.总结

编程式导航有几种跳转方式?

十一、编程式导航-path路径跳转传参

1.问题

点击搜索按钮,跳转需要把文本框中输入的内容传到下一个页面如何实现?

在这里插入图片描述

2.两种传参方式

1.查询参数

2.动态路由传参

3.传参

两种跳转方式,对于两种传参方式都支持:

① path 路径跳转传参

② name 命名路由跳转传参

4.path路径跳转传参(query传参)

//简单写法
this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
//完整写法
this.$router.push({
  path: '/路径',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})

接受参数的方式依然是:$route.query.参数名

Home.vue

<template>
    	...
      <input v-model="inputValue" type="text">
      <button @click="toSearch">搜索一下</button>
    	...
</template>

<script>
export default {
  name: 'FindMusic',
  data: {
    inputValue: '',
    key: ''
  },
  methods: {
    toSearch () {
      // this.$router.push(`/search?word=${this.inputValue}`);
      // 当参数比较多时不太好用,但是可以用完整写法,比如下面的写法
      this.$router.push({
        path: '/serach',
        query: {
          word: this.inputValue, // 注意:inputValue的获取要在前面加 this,否则无法获取。
          key: this.key
        }
      })
    }
  }
}
</script>

5.path路径跳转传参(动态路由传参)

//简单写法
this.$router.push('/路径/参数值')
//完整写法
this.$router.push({
  path: '/路径/参数值'
})

接受参数的方式依然是:$route.params.参数值

注意: path不能配合params使用,所以path的方式更加适合传递参数比较少时使用。

Home.vue

<script>
export default {
  name: 'FindMusic',
  data: {
    inputValue: ''
  },
  methods: {
    toSearch () {
      toSearch () {
        // this.$router.push(`/search/${this.inputValue}`);
        this.$router.push({
          path: `/search/${this.inputValue}`
        });
      }
    }
  }
}
</script>

十二、编程式导航-name命名路由传参

1.name 命名路由跳转传参 (query传参)

this.$router.push({
  name: '路由名字',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})

2.name 命名路由跳转传参 (动态路由传参)

this.$router.push({
  name: '路由名字',
  params: {
    参数名: '参数值',
  }
})

3.总结

编程式导航,如何跳转传参?

1.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: '/路径/参数值'
    })
    

2.name命名路由跳转

  • query传参

    this.$router.push({
      name: '路由名字',
      query: {
        参数名1: '参数值1',
        参数名2: '参数值2'
      }
    })
    
  • 动态路由传参 (需要配动态路由)

    this.$router.push({
      name: '路由名字',
      params: {
        参数名: '参数值',
      }
    })
    

十三、面经基础版-案例效果分析

源码

1.面经效果演示

2.功能分析

  • 通过演示效果发现,主要的功能页面有两个,一个是列表页,一个是详情页,并且在列表页点击时可以跳转到详情页
  • 底部导航可以来回切换,并且切换时,只有上面的主题内容在动态渲染

在这里插入图片描述

3.实现思路分析:配置路由+功能实现

1.配置路由

  • 首页和面经详情页,两个一级路由
  • 首页内嵌套4个可切换的页面(嵌套二级路由)

2.实现功能

  • 首页请求渲染
  • 跳转传参 到 详情页,详情页动态渲染
  • 组件缓存,性能优化

在这里插入图片描述

解释:App.vue中嵌套了两个路由,一个是首页,另一个时面经详情,当点击首页中的某个面经条例时,会直接跳转到条例对应的面经详情页面。首页中又包含了一些路由,当点击这些路由时,首页的面经条例会显示(跳转到)对应的条例页面。

十四、面经基础版-一级路由配置

1.把文档中准备的素材拷贝到项目中

2.针对router/index.js文件 进行一级路由配置

...
import Layout from '@/views/Layout.vue'
import ArticleDetail from '@/views/ArticleDetail.vue'
...


const router = new VueRouter({
  routes: [
    {
      path: '/',
      component: Layout
    },
    {
      path: '/detail',
      component: ArticleDetail
    }
  ]
})

十五、面经基础版-二级路由配置

二级路由也叫嵌套路由,当然也可以嵌套三级、四级…

1.使用场景

当在页面中点击链接跳转,只是部分内容切换时,我们可以使用嵌套路由

2.语法

  • 在一级路由下,配置children属性即可
  • 配置二级路由的出口

1.在一级路由下,配置children属性

注意:一级的路由path 需要加 / 二级路由的path不需要加 /

const router = new VueRouter({
  routes: [
    {
      path: '/',
      component: Layout,
      children:[
        //children中的配置项 跟一级路由中的配置项一模一样 
        {path:'xxxx',component:xxxx.vue},
        {path:'xxxx',component:xxxx.vue},
      ]
    }
  ]
})

技巧:二级路由应该配置到哪个一级路由下呢?

这些二级路由对应的组件渲染到哪个一级路由下,children就配置到哪个路由下边

2.配置二级路由的出口

注意: 配置了嵌套路由,一定配置对应的路由出口,否则不会渲染出对应的组件

Layout.vue

<template>
  <div class="h5-wrapper">
    <div class="content">
      <router-view></router-view>
    </div>
  ....
  </div>
</template>

3.代码实现

router/index.js

...
import Article from '@/views/Article.vue'
import Collect from '@/views/Collect.vue'
import Like from '@/views/Like.vue'
import User from '@/views/User.vue'
...

const router = new VueRouter({
  routes: [
    {
      path: '/',
      component: Layout,
      redirect: '/article',
      children:[
        {
          path:'/article',
          component:Article
        },
        {
          path:'/collect',
          component:Collect
        },
        {
          path:'/like',
          component:Like
        },
        {
          path:'/user',
          component:User
        }
      ]
    },
    ....
  ]
})

Layout.vue

<template>
  <div class="h5-wrapper">
    <div class="content">
      <!-- 内容部分 -->
      <!-- 二级路由出口,匹配到的二级路由组件就会展示在这里 -->
      <router-view></router-view>
    </div>
    <nav class="tabbar">
      <a href="#/article">面经</a>
      <a href="#/collect">收藏</a>
      <a href="#/like">喜欢</a>
      <a href="#/user">我的</a>
    </nav>
  </div>
</template>

十六、面经基础版-二级导航高亮

1.实现思路

  • 将a标签替换成 组件,配置to属性,不用加 #
  • 结合高亮类名实现高亮效果 (推荐模糊匹配:router-link-active)

2.代码实现

Layout.vue

....
    <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>
   a.router-link-active {
      color: orange;
    }
</style>

十七、面经基础版-首页请求渲染

1.步骤分析

1.安装axios

2.看接口文档,确认请求方式,请求地址,请求参数

3.created中发送请求,获取数据,存储到data中

4.页面动态渲染

2.代码实现

1.安装axios

yarn add axios npm i axios

2.接口文档

请求地址: https://mock.boxuegu.com/mock/3083/articles
请求方式: get

3.created中发送请求,获取数据,存储到data中

 data() {
    return {
      articelList: [],
    }
  },
  async created() {
    const {  data: { result: { rows } }} = await axios.get('https://mock.boxuegu.com/mock/3083/articles')
    this.articelList = rows
  },

4.页面动态渲染

<template>
  <div class="article-page">
    <div class="article-item" v-for="item in articelList" :key="item.id">
      <div class="head">
        <img :src="item.creatorAvatar" alt="" />
        <div class="con">
          <p class="title">{{ item.stem }}</p>
          <p class="other">{{ item.creatorName }} | {{ item.createdAt }}</p>
        </div>
      </div>
      <div class="body">
        {{item.content}}
      </div>
      <div class="foot">点赞 {{item.likeCount}} | 浏览 {{item.views}}</div>
    </div>
  </div>
</template>

十八、面经基础版-查询参数传参

1.说明

跳转详情页需要把当前点击的文章id传给详情页,获取数据

  • 查询参数传参 this.$router.push(‘/detail?参数1=参数值&参数2=参数值’)
  • 动态路由传参 先改造路由 在传参 this.$router.push(‘/detail/参数值’)

2.查询参数传参实现

Article.vue

<template>
  <div class="article-page">
    <div class="article-item" 
      v-for="item in articelList" :key="item.id" 
      @click="$router.push(`/detail?id=${item.id}`)">
     ...
    </div>
  </div>
</template>

ArticleDetail.vue

  created(){
    console.log(this.$route.query.id)
  }

十九、面经基础版-动态路由传参

1.实现步骤

  • 改造路由
  • 动态传参
  • 在详情页获取参数

2.代码实现

改造路由

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)
  }

index.js

routes: [
  {
      path: '/',
      cpmponent: Layout,
      redirect: '/article', // 当到Layout的时候就直接重定向到指定的子路由中
      children: [
        { path: '/article', component: Article },
        ...
      ]
  },
  ...
]

3.额外优化功能点-点击回退跳转到上一页

ArticleDetail.vue

<template>
  <div class="article-detail-page">
    <nav class="nav"><span class="back" @click="$router.back()">&lt;</span> 面经详情</nav>
     ....
  </div>
</template>

二十、面经基础版-详情页渲染

1.实现步骤分析

  • 导入axios
  • 查看接口文档
  • 在created中发送请求
  • 页面动态渲染

2.代码实现

接口文档

 请求地址: https://mock.boxuegu.com/mock/3083/articles/:id
 请求方式: get

在created中发送请求

 data() {
    return {
      articleDetail:{}
    }
  },
  async created() {
    const id = this.$route.params.id
    const {data:{result}} = await axios.get(
      `https://mock.boxuegu.com/mock/3083/articles/${id}`
    )
    this.articleDetail = result
  },

页面动态渲染

<template>
  <!-- 由于数据的请求是需要时间的,这时候页面会出现暂时显示一些残缺的结构 -->
  <!-- 可以通过v-if判断是否有文章的id值来决定是否渲染页面,具体操作如下 -->
  <div class="article-detail-page" v-if="article.id">
    <nav class="nav">
      <span class="back" @click="$router.back()">&lt;</span> 面经详情
    </nav>
    <header class="header">
      <h1>{{articleDetail.stem}}</h1>
      <p>{{articleDetail.createAt}} | {{articleDetail.views}} 浏览量 | {{articleDetail.likeCount}} 点赞数</p>
      <p>
        <img
          :src="articleDetail.creatorAvatar"
          alt=""
        />
        <span>{{articleDetail.creatorName}}</span>
      </p>
    </header>
    <main class="body">
      {{articleDetail.content}}
    </main>
  </div>
</template>

二十一、面经基础版-缓存组件

1.问题

从面经列表 点到 详情页,又点返回,数据重新加载了,并没有回到点进来之前滚动条的位置 → 希望回到原来的位置

在这里插入图片描述

2.原因

当路由被跳转后,原来所看到的组件就被销毁了(会执行组件内的beforeDestroy和destroyed生命周期钩子),重新返回后组件又被重新创建了(会执行组件内的beforeCreate,created,beforeMount,Mounted生命周期钩子),所以数据被加载了

3.解决方案

利用keep-alive把原来的组件给缓存下来

4.什么是keep-alive

keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。

keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件中。

优点:

在组件切换过程中把切换出去的组件保留在内存中,防止重复渲染DOM,

减少加载时间及性能消耗,提高用户体验性。

App.vue

<template>
  <div class="h5-wrapper">
    <!-- 包裹了 keep-alive 一级路所匹配的组件都会被缓存
		这里的一级路由是 Layout 和 Detail 被缓存了 -->
    <keep-alive>
      <router-view></router-view>
    </keep-alive>
  </div>
</template>

直接这样写的小问题:

比如说从页面中点击一个文章1进去,这时,Layout 和 文章1的 Detail 会被缓存,点击返回时会回到原来的滚动条的位置,此时再点击一个文章3进去,由于文章1被缓存了,这样做会直接显示文章1而不是文章3。

这说明了并不是所有的组件都需要被缓存的,这可以通过keep-alive的属性来解决问题。

问题:

缓存了所有被切换的组件

5.keep-alive的三个属性

① include : 组件名数组,只有匹配的组件会被缓存,其他的组件默认不会被缓存。

② exclude : 组件名数组,任何匹配的组件都不会被缓存,其他的组件默认会被缓存。

③ max : 最多可以缓存多少组件实例

include和exclude并不可以同时用

App.vue

<template>
  <div class="h5-wrapper">
    <keep-alive :include="['LayoutPage']">
      <router-view></router-view>
    </keep-alive>
  </div>
</template>

注意:include和exclude是组件名数组,也就是他们的值是一些组件名组成的数组,组件名就是每一个组件导出的name属性。如果没有配置name属性才会去找文件名作为组件名。通俗一点讲就是,name的优先级更高,没有name属性时才会去找文件名作为属性。

也可以这样写:App.vue

<template>
  <div class="h5-wrapper">
    <keep-alive :include="keepArr">
      <router-view></router-view>
    </keep-alive>
  </div>
</template>
<script>
export default {
  name: 'h5-wrapper',
  data () {
    return {
      // 缓存组件的组件名数组
      keepArr: ['LayoutPage']
    }
  }
}
</script>

6.额外的两个生命周期钩子

keep-alive的使用会触发包裹的组件的两个生命周期函数

activated 当组件被激活(使用)的时候触发 → 进入这个页面的时候触发

deactivated 当组件不被使用的时候触发 → 离开这个页面的时候触发

注意是组件缓存之后!注意是组件缓存之后!注意是组件缓存之后!组件缓存后不会执行组件的created, mounted, destroyed 等钩子了,缓存之前是会正常执行这些钩子函数的。

所以其提供了actived 和deactived钩子,帮我们实现业务需求。

Layout.vue

<script>
export default {
  name: 'LayoutPage',
  created () {
    console.log('created 组件被加载了');
  },
  mounted () {
    console.log('mounted dom渲染完了');
  },
  destroyed () {
    console.log('destroyed 组件被销毁了');
  },
    
  activated () {
    console.log('activated 组件被激活了');
  },
  deactivated () {
    console.log('deactivated 组件失活了');
  },
}
</script>

一开始加载页面时控制台显示:

created 组件被加载了
mounted dom渲染完了
activated 组件被激活了

说明已经创建,挂载并且缓存了起来。当点击一篇文章时控制台会继续出现:

deactivated 组件失活了

当点击返回时,控制台会继续出现:

activated 组件被激活了

7.总结

1.keep-alive是什么

vue的内置组件,包裹动态组件时,

2.keep-alive的优点

组件切换过程中把切换出去的组件保留在内存中(提升性能)

3.keep-alive的三个属性 (了解)

include :组件名数组,只有匹配的组件会被缓存

exclude :组件名数组,任何匹配的组件都不会被缓存

max︰最多可以缓存多少组件实例

4.keep-alive的使用会触发两个生命周期函数(了解)

activated当组件被激活(使用)的时候触发→进入页面触发

deactivated当组件不被使用的时候触发→离开页面触发

二十二、VueCli 自定义创建项目

1.安装脚手架 (已安装)

npm i @vue/cli -g

2.创建项目

vue create hm-exp-mobile
  • 选项
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

在这里插入图片描述

  • 等待安装,项目初始化完成

在这里插入图片描述

  • 启动项目
npm run serve

二十三、ESlint代码规范及手动修复

代码规范:一套写代码的约定规则。例如:赋值符号的左右是否需要空格?一句结束是否是要加;?…

没有规矩不成方圆

ESLint:是一个代码检查工具,用来检查你的代码是否符合指定的规则(你和你的团队可以自行约定一套规则)。在创建项目时,我们使用的是 JavaScript Standard Style 代码风格的规则。

1.JavaScript Standard Style 规范说明

建议把:https://standardjs.com/rules-zhcn.html 看一遍,然后在写的时候, 遇到错误就查询解决。

下面是这份规则中的一小部分:

  • 字符串使用单引号 – 需要转义的地方除外
  • 无分号 – 这没什么不好。不骗你!
  • 关键字后加空格 if (condition) { ... }
  • 函数名后加空格 function name (arg) { ... }
  • 坚持使用全等 === 摒弃 == 一但在需要检查 null || undefined 时可以使用 obj == null
2.代码规范错误

如果你的代码不符合standard的要求,eslint会跳出来刀子嘴,豆腐心地提示你。

下面我们在main.js中随意做一些改动:添加一些空行,空格。

import Vue from 'vue'
import App from './App.vue'

import './styles/index.less'
import router from './router'
Vue.config.productionTip = false

new Vue ( {
  render: h => h(App),
  router
}).$mount('#app')


按下保存代码之后:

你将会看在控制台中输出如下错误:

在这里插入图片描述

eslint 是来帮助你的。心态要好,有错,就改。

3.手动修正

根据错误提示来一项一项手动修正。

如果你不认识命令行中的语法报错是什么意思,你可以根据错误代码(func-call-spacing, space-in-parens,…)去 ESLint 规则列表中查找其具体含义。

打开 ESLint 规则表,使用页面搜索(Ctrl + F)这个代码,查找对该规则的一个释义。

在这里插入图片描述

二十四、通过eslint插件来实现自动修正

  1. eslint会自动高亮错误显示
  2. 通过配置,eslint会自动帮助我们修复错误
  • 如何安装

在这里插入图片描述

  • 如何配置
// 当保存的时候,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
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/484541.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

codeTop102:二叉树的层序遍历

前言 在已知BFS的方式后&#xff0c;知道每次从队列中取一个节点&#xff0c;就要将这个节点的所有子节点按照顺序放入队列。 难点在于怎么确定将同一层的节点放在一个数组里面的输出&#xff0c;也就是输出一个二维数组&#xff1f; 解决方法: 每次while循环将队列上轮放入的…

蓝桥集训之矩形牛棚

蓝桥集训之矩形牛棚 核心思想&#xff1a;单调队列 模板&#xff1a;Acwing.131.直方图矩形面积首先遍历所有下界 然后确定以该下界为底的直方图 求最大矩形 #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 30…

Java学习day2

命名规则 在JAVA中&#xff0c;公共类的明朝必须与包含该类的源文件的文件名向匹配&#xff0c;即 这两个名称要一致 变量类型 与c/c基本一致 需要注意的是&#xff0c;long类型的数据在后面需要加上l或L&#xff08;建议加L&#xff0c;l可能会被误判&#xff09;&#xff…

【Redis】优惠券秒杀

全局唯一ID 全局唯一ID生成策略&#xff1a; UUIDRedis自增snowflake算法数据库自增 Redis自增ID策略&#xff1a;每天一个key&#xff0c;方便统计订单量ID构造是 时间戳 计数器 Component public class RedisIdWorker {// 2024的第一时刻private static final long BEGIN…

【C语言】编译和链接----预处理详解【图文详解】

欢迎来CILMY23的博客喔&#xff0c;本篇为【C语言】文件操作揭秘&#xff1a;C语言中文件的顺序读写、随机读写、判断文件结束和文件缓冲区详细解析【图文详解】&#xff0c;感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞关注收藏。 前言 欢迎来到本篇博客&…

易语言学习第一天(安装破解和配置)

一、引言 易语言是一个自主开发&#xff0c;适合国情&#xff0c;不同层次不同专业的人员易学易用的汉语编程语言。易语言降低了广大电脑用户编程的门槛&#xff0c;尤其是根本不懂英文或者英文了解很少的用户&#xff0c;可以通过使用本语言极其快速地进入Windows程序编写的大…

全新的分布式锁,功能简单且强大

分布式锁是分布式系统中一个极为重要的工具。 目前有多种分布式锁的设计方案&#xff0c;比如借助 redis&#xff0c;mq&#xff0c;数据库&#xff0c;zookeeper 等第三方服务系统来设计分布式锁。 tldb 提供的分布式锁&#xff0c;主要是要简化这个设计的过程&#xff0c;提…

安全之剑:深度解析 Apache Shiro 框架原理与使用指南

在现代软件开发中&#xff0c;安全性一直是至关重要的一个方面。随着网络攻击和数据泄露的不断增加&#xff0c;我们迫切需要一种强大而灵活的安全框架来保护我们的应用。Shiro框架就是这样一把利剑&#xff0c;它能够轻松地集成到你的项目中&#xff0c;为你的应用提供可靠的安…

用户增长的底层逻辑:从原理到实践

在互联网行业的洪流中&#xff0c;用户增长被视为企业生命力与竞争力的重要标志。理解并掌握用户增长的底层逻辑&#xff0c;是每一位产品经理、市场营销人员以及创业者不可或缺的基本功。 用户增长的底层逻辑&#xff1a;从原理到实践© 由 ZAKER科技 提供 一、用户增长的…

02.percona Toolkit工具pt-archiver命令实践

1.命令作用 Percona Toolkit有的32个命令&#xff0c;可以分为7大类 工具类别 工具命令 工具作用 备注 开发类 pt-duplicate-key-checker 列出并删除重复的索引和外键 pt-online-schema-change 在线修改表结构 pt-query-advisor 分析查询语句&#xff0c;并给出建议&#x…

深度学习知识点:神经网络

深度学习知识点&#xff1a;神经网络 前言神经网络激活函数的优缺点为什么ReLU常用于神经网络的激活函数&#xff1f;梯度消失和梯度爆炸的解决方案&#xff1f;梯度爆炸引发的问题&#xff1f;如何确定是否出现梯度爆炸&#xff1f;神经网络中有哪些正则化技术&#xff1f;批量…

知识图表示学习中的负抽样研究综述

摘要 知识图表示学习(KGRL)或知识图嵌入(KGE)在知识构建和信息探索的人工智能应用中起着至关重要的作用。这些模型旨在将知识图中的实体和关系编码到低维向量空间中。在KGE模型的训练过程中&#xff0c;使用正样本和负样本是区分的必要条件。然而&#xff0c;直接从现有的知识…

Qt 写一个邮件发送程序

最近在完成一个邮箱代替的告警功能&#xff0c;写了一个邮件发送的demo 以下为代码&#xff1a; #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include<QTcpSocket> namespace Ui { class MainWindow; }class MainWindow : public QMainWin…

C语言字节对齐关键字#pragma pack(n)的使用

0 前言 在进行嵌入式开发的过程中&#xff0c;我们经常会见到对齐操作。这些对齐操作有些是为了便于实现指针操作&#xff0c;有些是为了加速对内存的访问。因此&#xff0c;学习如何使用对齐关键字是对于嵌入式开发是很有必要的。 1 对齐规则 1.0 什么叫做对齐 众所周知&a…

深度学习pytorch——多层感知机反向传播(持续更新)

在讲解多层感知机反向传播之前&#xff0c;先来回顾一下多输出感知机的问题&#xff0c;下图是一个多输出感知机模型&#xff1a; 课时44 反向传播算法-1_哔哩哔哩_bilibili 根据上一次的分析深度学习pytorch——感知机&#xff08;Perceptron&#xff09;&#xff08;持续更新…

Django Ajax

【一】Json 【1】介绍 JSON&#xff08;javascript object otaition&#xff09;是一种轻量级的数据交换格式JSON使用了Javascript的一部分语法来定义其数据格式&#xff0c;但Json是独立于语言的Json采用完全独立于语言的文本格式&#xff0c;使得Json成为理想的数据交互语言…

从这15个简洁B端系统控制台页面,你悟到了什么?

从这15个简洁英文 B 端系统控制台页面中&#xff0c;我可以得出以下一些结论&#xff1a; 系统注重简洁性&#xff1a;这些页面采用了简洁的设计风格&#xff0c;避免了过多的装饰和冗余的信息&#xff0c;使用户界面更加清晰和易于使用。用户导航清晰&#xff1a;这些页面通常…

get_ipython()函数使用

今天发现一个很有意思的函数&#xff0c; 在jupyter notebook中&#xff0c;我也可以用命令实现这些值 get_ipython().system(nvidia-smi)结果如下 get_ipython().system(pwd)

学习大数据之JDBC(使用JAVA语句进行SQL操作)

文章目录 DCL语句创建用户授权用户撤销授权查看权限删除用户修改用户密码修改普通用户密码 JDBCjdbc介绍JDBC准备JDBC开发步骤以及详解JDBC注册驱动JDBC获取连接JDBC实现增删改操作JDBC 工具类的使用 DCL语句 我们现在默认使用的都是root用户&#xff0c;超级管理源&#xff0…

计算机基础系列 —— 汇编语言

Same hardware can run many different programs(Software) 文中提到的所有实现都可以参考&#xff1a;nand2tetris_sol&#xff0c;但是最好还是自己学习课程实现一遍&#xff0c;理解更深刻。 我们在之前的文章里&#xff0c;构建了 Register、RAM 和 ALU&#xff0c;使得我…