# Vue(5)

# 15. ESLint

注意

在创建Vue项目的时候要选中Linter / Formatter,并选中ESLint + Standard config,接着选择Lint on save

ESLint (opens new window)是检查代码格式的一款插件,会让写出来的代码风格保持统一

VScode格式设置

  1. 打开右下角设置,输入tabsize
  2. Editor: Tab SizeVetur › Format › Options: Tab Size的值都改为2
  3. 继续搜索format
  4. Editor: Format On Save选项打勾☑️

报错可以访问Rules规则 (opens new window)进行查阅

# 16. router路由

# 16.1 路由

# 16.1.1 什么是路由

路由(router)就是对应关系,通俗易懂的概念:Hash地址与组件之间的对应关系

# 16.1.2 SPA与前端路由

**单页Web应用(single page web application,SPA)**指的是一个web网站只有唯一的一个HTML页面,所有组件的展示与切换都在这唯一的一 个页面内完成。此时,不同组件之间的切换需要通过前端路由来实现。 结论: 在SPA项目中,不同功能之间的切换,要依赖于前端路由来完成!

# 16.2 前段路由的工作方式

  1. 用户点击了页面上的路由链接
  2. 导致了URL地址栏中的Hash值发生了变化
  3. 前端路由监听了到Hash地址的变化(window.onhashchange事件 => location.hash => #/home)
  4. 前端路由把当前Hash地址对应的组件渲染都浏览器中

注意

hash地址都要小写

# 16.3 Vue-router

返回顶部
  1. 输入命令npm install vue-router@3.5.2 -S进行安装

如果出现以下错误,是因为安装版本过高引起的,安装3.5.2就可以了

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: firstvue@0.1.0
npm ERR! Found: vue@2.6.14
npm ERR! node_modules/vue
npm ERR!   vue@"^2.6.11" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer vue@"^3.2.0" from vue-router@4.0.15
npm ERR! node_modules/vue-router
npm ERR!   vue-router@"4" from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR! 
npm ERR! See /Users/karl/.npm/eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/karl/.npm/_logs/2022-05-21T07_06_49_632Z-debug.log
  1. 在src源代码目录下,新建router/index.js路由模块,并初始化如下的代码:
// 1.导入Vue和VueRouter 的包
import Vue from 'vue'
import VueRouter from 'vue-router'

// 2.调用Vue.use()函数, 把VueRouter 安装为Vue的插件
Vue.use(VueRouter)

// 3.创建路由的实例对象
const router = new VueRouter()

//4.向外共享路由的实例对象
export default router
  1. 在main.js文件里挂载router模块
import Vue from 'vue'
import App from './App.vue'
import router from './router/index.js'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  router
}).$mount('#app')
  1. 使用vue-router
// router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
// 导入需要的组件
import HelloWorld from '@/components/HelloWorld.vue'
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue'

const router = new VueRouter({
  // 路由规则
  routes: [
    { path: '/index', component: HelloWorld },
    { path: '/left', component: Left },
    { path: '/right', component: Right }
  ]
})
<template>
  <div>
    <p>hello world</p>
    <a href="#/index">index</a>&nbsp;
    <a href="#/left">Left</a>&nbsp;
    <a href="#/right">Right</a>&nbsp;
		<hr />
    <!--只要在项目中安装和配置了vue-router, 就可以使用router-view 这个组件了-->
		<!-- 它的作用很单纯:占位符-->
    <!-- 在.vue文件中使用<router-view></router-view> -->
    <router-view></router-view>
  </div>
</template>
  
<!-- 官方建议把<a></a>标签换成<router-link></router-link> -->
<router-link to="/home">主页</router-link>
<router-link to="/count">计数器</router-link>

# 16.4 路由重定向

路由重定向指的是:用户在访问地址A的时候,强制用户跳转到地址C,从而展示特定的组件页面。通过路由规则的redirect属性,指定一个新的路由地址,可以很方便地设置路由的重定向:

const router = new VueRouter({
  routes: [
    // 重定向地址
    { path: '/',redirect: '/home'},
    ......
  ]
})

# 16.5 嵌套路由

// App.vue
<template>
  <div>
    <p>hello world</p>
    <router-link to="/home">主页</router-link>
    <router-link to="/count">计数器</router-link>
    <router-link to="/about">关于</router-link>
    <hr />
    <router-view></router-view>
  </div>
</template>

// about.vue
<template>
  <div>
    <h3>About 组件</h3>
    
    <router-link to="/about/tab1">tab1</router-link>
    <router-link to="/about/tab2">tab2</router-link>
    
    <router-view></router-view>
  </div>
</template>
  1. 在src/components/目录下先创建tab文件夹,并在文件夹里创建tab1.vue和tab2.vue文件

  2. 使用children属性声明子路由规则

import Tab1 from '@/components/tabs/Tab1.vue'
import Tab2 from ' @/components/tabs/Tab2.vue'

const router = new VueRouter({
  routes: [
    {//about页面的路由规则(父级路由规则)
      path: '/about',
      component: About,
      // 重定向路由
      redirect: '/about/tab1'
      children: [ 
      	// 1.通过children属性,嵌套声明子级路由规则
        // 2.访问/about/tab1 时,展示Tab1组件
      	// 子路由一般不加/
      //默认子路由: 如果children数组中,某个路由规则的path值为空字符串,则这条路由规则,叫做“默认子路由”
        { path: 'tab1',component: Tab1 }// 2.访问/about/tab2 时,展示Tab2组件
        { path: 'tab2',component: Tab2 } 
      ]
    }
  ]
})

# 16.6 动态路由

动态路由指的是: 把Hash地址中可变的部分定义为参数项,从而提高路由规则的复用性。在vue-router中使用英文的冒号(😃 来定义路由的参数项。示例代码如下:

{ path: '/movie/:id?name=zs age=20',component: Movie}

# 16.6.1 $route.param获取传参

拿到id值: this.$route.param.id$route.param.id

传参

  • 在hash地址中,/ 后面的参数项叫做“路径参数”,在路由“参数对象”中,需要使用this.$route.params来访问路径参数
  • 在hash地址中,? 后面的参数项叫做“查询参数”,在路由“参数对象”中,需要使用this.$route.query来访问查询参数
  • 在this.$route中,path只是路径部分,fullPath是完整的地址

# 16.6.2 开启props传参

  1. 在router/index.js中的routers数组中写入

{ path: '/movie/:id',component: Movie,props: true }

  1. 在movie.vue文件中写入,即可使用
exports default {
	props: ['id']
}

# 16.7 导航跳转

# 16.7.1 声明式导航 & 编程式导航

  • 在浏览器中,点击链接实现导航的方式,叫做声明式导航。例如: 普通网页中点击<a>链接、vue项目中点击<router-link>都属于声明式导航
  • 在浏览器中,调用API方法实现导航的方式,叫做编程式导航。例如: 普通网页中调用location.href跳转到新页面的方式,属于编程式导航

# 16.7.2 vue-router中的编程式导航API

vue-router(导航对象 )提供了许多编程式导航的API,其中最常用的导航API分别是:

  1. this.$router.push('hash 地址')
  • 跳转到指定hash地址,并增加一条历史记录

<button @click="$router.push('/about')">跳转到关于</button>

注意

以上代码只能在写跳转页面的页面上,比如Helloworld.vue文件中,不能写在App.vue中

  1. this.$router.replace('hash 地址')
  • 跳转到指定hash地址,并替换掉当前的历史记录
  1. this.$router.go(数值 n)
  • 前进或后退相应的记录

# 16.7.3 导航全局前置守卫

每次发生路由的导航跳转时,都会触发全局前置守卫

//创建路由实例对象
const router = new VueRouter ({...})
                               
//调用路由实例对象的beforeEach方法,即可声明“全局前置守卫”
//每次发生路由导航跳转的时候,都会自动触发fn这个“回调函数”
router.beforeEach((to,from,next) => {
	//to是将要访问的路由的信息对象
	//from是将要离开的路由的信息对象
	//next是一个函数,调用next()表示放行,允许这次路由导航
  1. next()//当前用户拥有后台主页的访问权限,直接放行
  2. next('/login')//当前用户没有后台主页的访问权限,强制其跳转到登录页面
  3. next(false)//当前用户没有后台主页的访问权限,不允许跳转到后台主页
})

模拟登陆操作

router.beforeEach((to,from,next) => {
if (to.path === '/main') {
	const token = localStorage.getItem('token')
	if (token) {
		next() //访问的是后台主页,且有token的值
  } else {
		next('/login') //访问的是后台主页,没有token的值
} else {
	next() //访问的不是后台主页,直接放行
)

# 16.8 Vant组件库

  1. 通过npm安装

TIP

  • Vue2项目,安装Vant2: npm i vant -S
  • Vue3项目,安装Vant3: npm i vant@next -S
  1. 在main.js文件中引入全部组件
import Vue from 'vue';
import Vant from 'vant';
import 'vant/lib/index.css';

Vue.use(Vant);

TIP

配置按需引入后,将不允许直接导入所有组件。

  1. 复制相应代码到.vue文件中使用组件

# 17. axios

全局使用axios的设置

  1. 挂载到Vue原型上
// main.js
import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'
Vue.config.productionTip = false
// 增加以下语句
//全局配置axios 的请求根路径
axios.defaults.baseURL = '请求根路径'
//把axios挂载到Vue.prototype上,供每个vue组件的实例直接使用
vue.prototype.axios= axios

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

注意

但是把axios挂载到Vue原型上,有一个缺点: 不利于API接口的复用! !

# 18. Vuex

# 18.1 理解vuex

# 18.1.1 vuex是什么

  1. 概念: 专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。

  2. Github 地址: https://github.com/vuejs/vuex

# 18.1.2 什么时候使用Vuex

  1. 多个组件依赖于同一状态
  2. 来自不同组件的行为需要变更同一状态

# 18.1.3 Vuex工作原理图

# 18.2 Vuex使用

提示

  • vue2中要用vuex的3版本
  • vue3中要用vuex的4版本
  1. 输入命令:npm install vuex@3npm install vuex(默认4版本)

  2. 创建文件:src/store/index.js

//该又件用于创建Vuex中最为核心的store

import Vue from 'vue'
import Vuex from 'vuex' 
// 使用Vuex插件
Vue.use(Vuex)
// 准备actions——用于响应组件中的动作
const actions = {}
// 准备mutations——用于操作数据(state)
const mutations = {}
// 准备state——用于存储数据
const state = {}

// 创建并暴露store
export default new Vuex.Store({
  actions,
	mutations,
	state,
})
  1. 在main.js中创建vm时传入store配置项
// main.js
// 引入store
import store from './store/index'
// 使用
new Vue({
  ...,
  store,
  ...
})