Vue中的ajax请求、Vuex、Vue UI组件库

文章目录

  • Vue中的ajax请求
    • 解决开发环境 Ajax 跨域问题
      • 准备好测试的服务器
      • 准备访问5000服务器 存在跨域问题
      • 配置代理方式一:
      • 配置代理方式二:
    • 2、github用户搜索案例
      • 1、静态编写
      • 2、展示动态的数据和交互
      • 3、完善功能
      • 4、完整数据
    • 3、vue 项目中常用的 2 个 Ajax 库
      • axios 强力推荐
      • vue-resource(插件库)
    • 4、Vue插槽solt
      • 效果
      • 默认插槽
      • 作用域插槽
  • Vue中vuex 重要
    • 1、Vuex
      • 1、什么时候使用Vuex
      • 2、案例纯粹的vue
      • 3、Vuex 工作原理图
      • 4、搭建Vuex环境
        • 步骤
        • 创建store两种方式:
        • 引入Store
      • 5、vuex实现案例(vuex的基本使用)
      • 6、Vuex开发者工具使用
        • 问题一:
        • 问题二:
        • 问题三:
    • 2、Store中的配置项
      • 1、Store中的配置项getters
      • 2、Store中的配置项_mapState与mapGetters
      • 3、Store中的配置项_mapActions与mapMutations.mp4
      • 4、多组件共享数据
    • 3、Vuex的模块编码 + 命名空间
      • ① 原始臃肿的写法方式
      • ② 改进: store/index.js
      • ③ 改进:把store/index.js拆分
      • 练习Actions调用Backend API 后端API
    • 4、Vue路由Route
      • 1、基本路由
        • 路由的基本使用
        • 路由的注意点
      • 2、嵌套(多级)路由
      • 3、路由传参
        • 路由接收参数之一:query参数
        • 命名路由 name
        • 路由接收参数之二:params参数
        • 路由props配置
        • router-link的replace属性
      • 4、编程式路由导航
        • 缓存路由组件
      • 5、两个新的声明周期钩子
      • 6、路由守卫
        • 全局守卫
        • 独享路由守卫
        • 组件内路由守卫
      • 7、路由器的两种工作模式
        • hash模式
        • history模式
  • Vue UI 组件库
    • 1、移动端常用 UI 组件库
    • 2、PC 端常用 UI 组件库

作者: gh-xiaohe
gh-xiaohe的博客
觉得博主文章写的不错的话,希望大家三连(✌关注,✌点赞,✌评论),多多支持一下!!!

Vue中的ajax请求

解决开发环境 Ajax 跨域问题

总结:

Vue中的ajax请求、Vuex、Vue UI组件库_第1张图片

准备好测试的服务器

server1.js

const express = require('express')
const app = express()

app.use((request,response,next)=>{
	console.log('有人请求服务器1了');
	// console.log('请求来自于',request.get('Host'));
	// console.log('请求的地址',request.url);
	next()
})

app.get('/students',(request,response)=>{
	const students = [
		{id:'001',name:'tom',age:18},
		{id:'002',name:'jerry',age:19},
		{id:'003',name:'tony',age:120},
	]
	response.send(students)
})

app.listen(5000,(err)=>{
	if(!err) console.log('服务器1启动成功了,请求学生信息地址为:http://localhost:5000/students');
})

server2.js

const express = require('express')
const app = express()

app.use((request,response,next)=>{
	console.log('有人请求服务器2了');
	next()
})

app.get('/cars',(request,response)=>{
	const cars = [
		{id:'001',name:'奔驰',price:199},
		{id:'002',name:'马自达',price:109},
		{id:'003',name:'捷达',price:120},
	]
	response.send(cars)
})

app.listen(5001,(err)=>{
	if(!err) console.log('服务器2启动成功了,请求汽车信息地址为:http://localhost:5001/cars');
})

启动

  • node server1.js
  • node server2.js

准备访问5000服务器 存在跨域问题

Vue中的ajax请求、Vuex、Vue UI组件库_第2张图片

安装 axios

  • npm i axios
  • 引入 import axios from ‘axios’

app.vue




Vue中的ajax请求、Vuex、Vue UI组件库_第3张图片

解决跨域

  • cors 不用前端人员做任何的事情
    • 写服务器(后端人员)的人,在服务器里面,给你返回响应的时候,加几个特殊的响应头
    • 不是随便的配置的,造成的后果,任何人都可以找你这台服务器要数据
  • jsonp 开发时使用微乎其微
    • 借助了 srcipt 便签里面 src 属性 不受同源策略限制
    • 前端人员需要写特殊的写法后端人员也需要配合你,并且只能解决 get请求
  • 代理服务器
    • 和所处的位置(前端)是一样的,协议名、主机名、端口号都保持一致
    • 服务器和服务器之间传递不用ajax,使用的是传统的http请求
      • nginx 代理服务器
      • vue-cli 开启一个代理服务器

配置代理方式一:

细节:

  • 代理服务器不是所有的请求,都转发给5000(不能灵活的配置走不走代理)
    • 代理服务器本事就有的数据,就不转发给5000
  • 不能配置多个代理

vue.config.js

 // 开启代理服务器
 devServer: {
   proxy: 'http://localhost:5000'
 }, 

app.vue

端口改成8080




Vue中的ajax请求、Vuex、Vue UI组件库_第4张图片

配置代理方式二:

	开启代理服务器(方式二)
	devServer: {
   proxy: {
     '/atguigu': { // 请求前缀
       target: 'http://localhost:5000', // 请求地址
				pathRewrite:{'^/atguigu':''}, // 重写路径 key-value  key正则的匹配条件 把以atguigu 开头的变成 空字符串
       // ws: true, //用于支持websocket  默认true
       // changeOrigin: true //用于控制请求头中的host值 默认true
     },
     '/demo': {
       target: 'http://localhost:5001',
				pathRewrite:{'^/demo':''},
       // ws: true, //用于支持websocket
       // changeOrigin: true //用于控制请求头中的host值
     }
   }
 }

app.vue




Vue中的ajax请求、Vuex、Vue UI组件库_第5张图片

2、github用户搜索案例

项目接口:https://api.github.com/search/users?q=xxx

1、静态编写

① 基础

app.vue






把bootstop的样式引入

  • 方式一:src下创建文件夹assets(静态资源)/css 把 bootstrap.css 存在里面
  • 引入:
    • ① main.js 中引入 不推荐
    • 里面用到了第三方的样式,这些资源还不去使用,目前不用,不推荐assets方式
    • ② 根组件app.vue引入 import ‘./assets/css/bootstrao.css’
      • 此方式,脚手架会做一个非常严格的检查,有引入不存在的资源就会报错,没有使用也不可以
  • 方式二:在public下建立一个css文件夹 把 bootstrap 放入里面,在index.html页面中引入
  • 相对路径

② 拆组件

app.vue

  • 样式都是控制列表区的



List.vue






Search.vue

  • 使用的是 bootstop 中的样式



Vue中的ajax请求、Vuex、Vue UI组件库_第6张图片

2、展示动态的数据和交互

Search.vue

  • 获取用户输入
  • 发送请求
  • 把数据通过全局事件总线的方式传递给list




Vue中的ajax请求、Vuex、Vue UI组件库_第7张图片

main.js安装全局事件总线

//创建vm
new Vue({
	el:'#app',
	render: h => h(App),
	beforeCreate() {
		Vue.prototype.$bus = this
	},
})

List.vue

  • List接收数据 Search 传输数据
  • avatar_url 用户的头像地址 展示
  • html_url 每一个人的github主页 点击时实现跳转
  • login 用户的登录名 展示
>

Vue中的ajax请求、Vuex、Vue UI组件库_第8张图片



Vue中的ajax请求、Vuex、Vue UI组件库_第9张图片

3、完善功能

  • 一上来使用有欢迎词 list组件
  • 搜索没有加载出来时,限制正在加载中 list组件
  • error

List.vue




Search.vue


Vue中的ajax请求、Vuex、Vue UI组件库_第10张图片

4、完整数据

App.vue




List.vue






Search.vue





main.js

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false

//创建vm
new Vue({
	el:'#app',
	render: h => h(App),
	beforeCreate() {
		Vue.prototype.$bus = this
	},
})

3、vue 项目中常用的 2 个 Ajax 库

axios 强力推荐

通用的 Ajax 请求库, 官方推荐,使用广泛

vue-resource(插件库)

vue 插件库, vue1.x 使用广泛, 官方已不维护。

安装

  • npm i vue-resource

引入插件

  • import VueResource from ‘vue-resource’

使用插件

  • vue.use(VueResource )

vm 和 vc 身上都多了 $http:(…)

Vue中的ajax请求、Vuex、Vue UI组件库_第11张图片

Search.vue


4、Vue插槽solt

总结:

Vue中的ajax请求、Vuex、Vue UI组件库_第12张图片

效果

① 基础

Category.vue






app.vue






Vue中的ajax请求、Vuex、Vue UI组件库_第13张图片

② 实现

Category.vue




app.vue




Vue中的ajax请求、Vuex、Vue UI组件库_第14张图片

默认插槽

  • 改需求,如下效果

Vue中的ajax请求、Vuex、Vue UI组件库_第15张图片

app.vue


Category.vue




props:['title']

ok 实现

作用域插槽

  • 改需求,如下效果

Vue中的ajax请求、Vuex、Vue UI组件库_第16张图片

① 基础

Category.vue




app.vue




Vue中的ajax请求、Vuex、Vue UI组件库_第17张图片

② 数据不在app组件中 在 Category 组件中

  • 插槽也就不需要了

Category.vue




app.vue




同样实现

Vue中的ajax请求、Vuex、Vue UI组件库_第18张图片

③ 需求:数据是一样的,数据的结构根据使用者的结构来定义

  • games 的作用域,games 在 Category 中,app中如何使用

  • 插槽提供了便捷的方式,插槽绑定 games,就传给了插槽的使用者

  • 使用者如何拿到,使用template标签 属性scope=“名字随意”,就可以收到数据

  • 第一次使用数据是无序列表

  • 第二次使用数据是有序列表

  • 第二次使用数据每一个都是 h4 标题

Category.vue




app.vue




ok 实现

Vue中vuex 重要

总结:


Vue中的ajax请求、Vuex、Vue UI组件库_第19张图片

理解:

全局事件总线

  • 此时组件太多了,而且数据共享

Vue中的ajax请求、Vuex、Vue UI组件库_第20张图片

vuex 共享

Vue中的ajax请求、Vuex、Vue UI组件库_第21张图片

1、Vuex

1、什么时候使用Vuex

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

2、案例纯粹的vue

① 基础结构

Count.vue






app.vue




Vue中的ajax请求、Vuex、Vue UI组件库_第22张图片

② Count.vue




Vue中的ajax请求、Vuex、Vue UI组件库_第23张图片

3、Vuex 工作原理图

Vue中的ajax请求、Vuex、Vue UI组件库_第24张图片

4、搭建Vuex环境

步骤
  • 1、npm i vuex
    • vue3成为默认版本的同时,vuex也更新到了4版本
    • npm i vuex 安装的是vuex4
    • vuex的4版本,只能在vue3中使用
      • vue2中,要用vuex的3版本 npm i vuex@3
      • vue3中,要用vuex的4版本
  • 2、Vue.use(Vuex)
  • 3、store 管理
    • Actions
    • Mutations
    • State
  • 4、vc 看的见 store
创建store两种方式:

方式一:src下创建个文件夹vuex,创建一个store.js

方式二:文件夹交store 里面有个index.js 官网推荐

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
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,
})
引入Store
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入插件
import vueResource from 'vue-resource'
//引入store
import store from './store/index'

//关闭Vue的生产提示
Vue.config.productionTip = false
//使用插件
Vue.use(vueResource)


//创建vm
new Vue({
	el:'#app',
	render: h => h(App),
	store,
	beforeCreate() {
		Vue.prototype.$bus = this
	}
})

注意:引入vuex的位置

  • 要在index.js中,如果在main.js中不会报错
    • 还需要引入vue,并且要在最上方

Vue中的ajax请求、Vuex、Vue UI组件库_第25张图片

  • 成功
    Vue中的ajax请求、Vuex、Vue UI组件库_第26张图片

5、vuex实现案例(vuex的基本使用)

  • 简单易懂
// 1、准备state——用于存储数据
const state = {
	sum:0 //当前的和
}

// 2、准备actions——用于响应组件中的动作
const actions = {
	jia(context,value){
		console.log('actions中的jia被调用了')
		context.commit('JIA',value)
	}
}
// 3、准备mutations——用于操作数据(state)
const mutations = {
	JIA(state,value){
		console.log('mutations中的JIA被调用了')
		state.sum += value
	}
}
// 引用
<h1>当前求和为:{{$store.state.sum}}</h1>

this.$store.dispatch('jiaWait',this.n)

// 如果 Actions 中没有业务逻辑时,可以直接调用Mutations
this.$store.commit('JIA',this.n) // 和 Mutations 对话 名字是大写的

// 拓展:Actions可以有多个,一个处理不过来
	jiaOdd(context,value){
		console.log('actions中的jiaOdd被调用了')
		console.log('处理了一些事情--jiaOdd')
		context.dispatch('demo1',value)
	},
	demo1(context,value){
		console.log('处理了一些事情--demo1')
		context.dispatch('demo2',value)
	},
	demo2(context,value){
		console.log('处理了一些事情--demo2')
		if(context.state.sum % 2){
			context.commit('JIA',value)
		}
	},

Count.vue






index.js

  • 开发中推荐
  • actions 中小写
  • mutations 中大写
//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions——用于响应组件中的动作
const actions = {
   // context 上下文
   // 此时没有意义,拿过来就转发
	/*jia(context,value){
		console.log('actions中的jia被调用了')
		context.commit('JIA',value)
	},
	jian(context,value){
		console.log('actions中的jian被调用了')
		context.commit('JIAN',value)
	},*/
	jiaOdd(context,value){
		console.log('actions中的jiaOdd被调用了')
		if(context.state.sum % 2){
			context.commit('JIA',value)
		}
	},
	jiaWait(context,value){
		console.log('actions中的jiaWait被调用了')
		setTimeout(()=>{
			context.commit('JIA',value)
		},500)
	}
}
//准备mutations——用于操作数据(state)
const mutations = {
	JIA(state,value){
		console.log('mutations中的JIA被调用了')
		state.sum += value
	},
	JIAN(state,value){
		console.log('mutations中的JIAN被调用了')
		state.sum -= value
	}
}
//准备state——用于存储数据
const state = {
	sum:0 //当前的和
}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
})

6、Vuex开发者工具使用

Vue中的ajax请求、Vuex、Vue UI组件库_第27张图片
Vue中的ajax请求、Vuex、Vue UI组件库_第28张图片

问题一:

问什么在Actions 中给的是 context(上下文),明明只有一个commint操作,为啥不直接给一个commint就可以了

  • 如果给你commint 那么就没有退路可严,只能commint向下操作
  • 但是Actions可以有多个,一个业务逻辑完成不了,通过上下文可以继续向下调用
// 拓展:Actions可以有多个,一个处理不过来
	jiaOdd(context,value){
		console.log('actions中的jiaOdd被调用了')
		console.log('处理了一些事情--jiaOdd')
		context.dispatch('demo1',value)
	},
	demo1(context,value){
		console.log('处理了一些事情--demo1')
		context.dispatch('demo2',value)
	},
	demo2(context,value){
		console.log('处理了一些事情--demo2')
		if(context.state.sum % 2){
			context.commit('JIA',value)
		}
	},
问题二:

context.state.sum += value // 同样可以实现,但是开发者失效了,不建议(开发者工具捕获的是Mutations中数据的变化)

	jiaOdd(context,value){
		console.log('actions中的jiaOdd被调用了')
		if(context.state.sum % 2){
			//context.commit('JIA',value)
            context.state.sum += value // 同样可以实现,但是开发者失效了,不建议(开发者工具捕获的是Mutations中数据的变化)
		}
	},
问题三:

为什么要把业务逻辑写在 actions(书写业务逻辑)中,可以写在方法中,同样可以实现,看组件就非常的直观

  • 原因:比如不是加操作,而是发票的报销,传递的是发票号,非常非常复杂的发票报销判断逻辑,
    • 难不成所有的人的都要写复杂的逻辑判断,自己发请求去链接服务器验证发票的真伪,非常冗余,可复用性高

2、Store中的配置项

1、Store中的配置项getters

① 让sum的值放大十倍展示

  • 日后的逻辑可能很复杂,而且可能不止使用一个getters

  • 计算属性实现
  • 计算属性不能跨组件使用,只能自己组件使用



  • getters

store/index.js

//准备getters——用于将state中的数据进行加工
const getters = {
	bigSum(state){
		return state.sum*10
	}
}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
	getters
})

Count.vue


Vue中的ajax请求、Vuex、Vue UI组件库_第29张图片

2、Store中的配置项_mapState与mapGetters

① 需求

  • 展示我自己在自学,学习前端,学习方式,和学习内容是State中的数据

store/index.js

//准备state——用于存储数据
const state = {
	sum: 0, //当前的和
	school: '自学',
	subject: '前端'
} 

Count.vue


简化想要实现的效果

  • 把$store.state 省略不写

② 实现

  • 计算属性,就自己组件使用

  • 使用Vuex中的==…mapState== 和 …mapGetters来实现
  • 需要引入



Vue中的ajax请求、Vuex、Vue UI组件库_第30张图片
Vue中的ajax请求、Vuex、Vue UI组件库_第31张图片

3、Store中的配置项_mapActions与mapMutations.mp4

优化:actions

  • 需要引入

Count.vue





优化




4、多组件共享数据

在写一个组件Person展示人员的信息

  • 需要在vuex中展示的信息sum、persons
  • count 组件读取sum、persons,进行展示
  • person 组件 读取sum、persons,进行展示
  • 添加一个人信息

① 基础

store/index.js

//准备state——用于存储数据
const state = {
	sum:0, //当前的和
	school:'尚硅谷',
	subject:'前端',
	personList:[
		{id:'001',name:'张三'}
	]
}

Person




Vue中的ajax请求、Vuex、Vue UI组件库_第32张图片

② 实现多组件共享数据

store/index.js

//准备mutations——用于操作数据(state)
const mutations = {
	ADD_PERSON(state, value) {
		console.log('mutations中的ADD_PERSON被调用了')
		state.personList.unshift(value)
	}
}

person.vue




count.vue




person.vue




Vue中的ajax请求、Vuex、Vue UI组件库_第33张图片
(VUE入门.assets/image-20220808220828347.png)]

3、Vuex的模块编码 + 命名空间

  • action、mutations、state、getters中如果有多个模块(订单、人员、求和),都放在一个显得臃肿,更容易造成git中的版本控制冲突
    • 把不同分类的action、mutations、state、getters放在不同的位置

① 原始臃肿的写法方式

store/index.js

//准备actions——用于响应组件中的动作
const actions = {
	jiaOdd(context, value) {
		console.log('actions中的jiaOdd被调用了')
		if (context.state.sum % 2) {
			context.commit('JIA', value)
		}
	},
	jiaWait(context, value) {
		console.log('actions中的jiaWait被调用了')
		setTimeout(() => {
			context.commit('JIA', value)
		}, 500)
	}
}
//准备mutations——用于操作数据(state)
const mutations = {
	JIA(state, value) {
		console.log('mutations中的JIA被调用了')
		state.sum += value
	},
	JIAN(state, value) {
		console.log('mutations中的JIAN被调用了')
		state.sum -= value
	},
	ADD_PERSON(state, value) {
		console.log('mutations中的ADD_PERSON被调用了')
		state.personList.unshift(value)
	}
}
//准备state——用于存储数据
const state = {
	sum: 0, //当前的和
	school: '自学',
	subject: '前端',
	personList: [
		{ id: '001', name: '张三' }
	]
}
//准备getters——用于将state中的数据进行加工
const getters = {
	bigSum(state) {
		return state.sum * 10
	}
}

② 改进: store/index.js

// 求和相关的配置
const countOptions = {
    // 书写完后countAbout 名才你能被 computed 中的 ...mapState 认识
    // ...mapState('countAbout',['sum','school','subject']), 不书写  countAbout 不被认识
    namespaced:true,
	actions:{
		jiaOdd(context, value) {
			console.log('actions中的jiaOdd被调用了')
			if (context.state.sum % 2) {
				context.commit('JIA', value)
			}
		},
		jiaWait(context, value) {
			console.log('actions中的jiaWait被调用了')
			setTimeout(() => {
				context.commit('JIA', value)
			}, 500)
		}
	},
	mutations:{
		JIA(state, value) {
			console.log('mutations中的JIA被调用了')
			state.sum += value
		},
		JIAN(state, value) {
			console.log('mutations中的JIAN被调用了')
			state.sum -= value
		}
	},
	state:{
		sum: 0, //当前的和
		school: '自学',
		subject: '前端',
	},
	getters:{
		bigSum(state) {
			return state.sum * 10
		}
	},
}

// 人员管理相关的配置
const personOptions = {
    namespaced:true,
	actions:{},
	mutations:{
		ADD_PERSON(state, value) {
			console.log('mutations中的ADD_PERSON被调用了')
			state.personList.unshift(value)
		}
	},
	state:{
		personList: [
			{ id: '001', name: '张三' }
		]
	},
	getters:{},
}

//创建并暴露store
export default new Vuex.Store({
	modules:{
		countAbout:countOptions,
		personAbout:personOptions
	}
})

Vue中的ajax请求、Vuex、Vue UI组件库_第34张图片

Count.vue

① 非简写




② 简写

  • 开启命名空间:namespaced:true,
  • …mapState、…mapMutations、…的简写方式



Vue中的ajax请求、Vuex、Vue UI组件库_第35张图片

③ 改进:把store/index.js拆分

store/count.js

//求和相关的配置
export default {
	namespaced:true,
	actions:{
		jiaOdd(context,value){
			console.log('actions中的jiaOdd被调用了')
			if(context.state.sum % 2){
				context.commit('JIA',value)
			}
		},
		jiaWait(context,value){
			console.log('actions中的jiaWait被调用了')
			setTimeout(()=>{
				context.commit('JIA',value)
			},500)
		}
	},
	mutations:{
		JIA(state,value){
			console.log('mutations中的JIA被调用了')
			state.sum += value
		},
		JIAN(state,value){
			console.log('mutations中的JIAN被调用了')
			state.sum -= value
		},
	},
	state:{
		sum:0, //当前的和
		school:'尚硅谷',
		subject:'前端',
	},
	getters:{
		bigSum(state){
			return state.sum*10
		}
	},
}

store/person.js

//人员管理相关的配置
export default {
	namespaced:true,
	actions:{
		addPersonWang(context,value){
			if(value.name.indexOf('王') === 0){
				context.commit('ADD_PERSON',value)
			}else{
				alert('添加的人必须姓王!')
			}
		}
	},
	mutations:{
		ADD_PERSON(state,value){
			console.log('mutations中的ADD_PERSON被调用了')
			state.personList.unshift(value)
		}
	},
	state:{
		personList:[
			{id:'001',name:'张三'}
		]
	},
	getters:{
		firstPersonName(state){
			return state.personList[0].name
		}
	},
}

store/index.js 引入

import countOptions from './count'
import personOptions from './person'

练习Actions调用Backend API 后端API

store/count.js

//人员管理相关的配置
import axios from 'axios'
import { nanoid } from 'nanoid'
export default {
	namespaced:true,
	actions:{
		addPersonWang(context,value){
			if(value.name.indexOf('王') === 0){
				context.commit('ADD_PERSON',value)
			}else{
				alert('添加的人必须姓王!')
			}
		},
		addPersonServer(context){
			axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
				response => {
					context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
				},
				error => {
					alert(error.message)
				}
			)
		}
	}
}
  • 之后正常引用

4、Vue路由Route

总结:


Vue中的ajax请求、Vuex、Vue UI组件库_第36张图片

理解:

Vue中的ajax请求、Vuex、Vue UI组件库_第37张图片
Vue中的ajax请求、Vuex、Vue UI组件库_第38张图片

实现什么功能:

SPA(single page web application)应用,单页面应用

1、基本路由

路由的基本使用

① 基础

  • 样式都是引入的bootstarp的样式

  • public/index.html

  • 	<link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css">
    

app.vue





  • 样式都是引入的bootstarp的样式

    • public/index.html

    • 	<link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css">
      
  • src/main.js 使用

    • //引入Vue
      import Vue from 'vue'
      //引入App
      import App from './App.vue'
      
      //关闭Vue的生产提示
      Vue.config.productionTip = false
      
      //创建vm
      new Vue({
      	el:'#app',
      	render: h => h(App),
      })
      

Vue中的ajax请求、Vuex、Vue UI组件库_第39张图片

② 展示

app.vue



Home.vue




About.vue




Vue中的ajax请求、Vuex、Vue UI组件库_第40张图片

③ 使用vue-router

  • 安装 npm i vue-router@3

    • vue-router 4 只能在 vue 3中使用

    • vue-router 3 才能在 vue 2中使用

  • 引入vue-router,mian.js

    • 并且引入了路由器

    • //引入VueRouter
      import VueRouter from 'vue-router'
      //引入路由器
      import router from './router'
      
      //应用插件
      Vue.use(VueRouter)
      
      //创建vm
      new Vue({
      	el:'#app',
      	render: h => h(App),
      	router:router
      })
      
    • 使用vue-router需要创建router文件夹/index.js , 创建整个应用的路由器,重要

    • // 该文件专门用于创建整个应用的路由器
      import VueRouter from 'vue-router'
      //引入组件
      import About from '../components/About'
      import Home from '../components/Home'
      
      //创建并暴露一个路由器
      export default new VueRouter({
      	routes:[
      		{
      			path:'/about',
      			component:About
      		},
      		{
      			path:'/home',
      			component:Home
      		}
      	]
      })
      

    Vue中的ajax请求、Vuex、Vue UI组件库_第41张图片

    ④ 实现单页面应用

  • 找到导航区,切换路径

  • 需要路由提供的特殊的标签router-link引入,不是href 而是 to=“/home”router-view制定位置呈现

  • router-link 最终转换成的是 a 标签,如果是按钮等等跳转,后面 编程式路由导航

app.vue



Vue中的ajax请求、Vuex、Vue UI组件库_第42张图片

路由的注意点

1、路由组件和一般组件

  • 路由组件:不需写组价标签,靠路由规则,匹配出来,由路由器来进行渲染的组件。 pages放置路由组件
  • 一般组件:亲自书写组件,是一般组件。components

Vue中的ajax请求、Vuex、Vue UI组件库_第43张图片

2、在频繁的切换时

  • 路由组件被销毁了

Vue中的ajax请求、Vuex、Vue UI组件库_第44张图片

3、路由组件身上多了两个人,$route 和 $ routers、

  • route:配置信息

Vue中的ajax请求、Vuex、Vue UI组件库_第45张图片

  • routers: 整个应用的路由器只有一个,800个路由规则也只有一个路由器

2、嵌套(多级)路由

效果

Vue中的ajax请求、Vuex、Vue UI组件库_第46张图片

只关注Home中里面的内容

Home.vue

  • 路径要加上一级路由的路径
//原来


// 最新




Message.vue




News.vue




router/index.js

  • 一级路由 加 /
  • 某一个路由里面的子路由不需要
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'

//创建并暴露一个路由器
export default new VueRouter({
	routes:[
		{
			path:'/about',
			component:About
		},
		{
			path:'/home',
			component:Home,
			children:[
				{
					path:'news',
					component:News,
				},
				{
					path:'message',
					component:Message,
				}
			]
		}
	]
})

3、路由传参

路由接收参数之一:query参数

效果

Vue中的ajax请求、Vuex、Vue UI组件库_第47张图片

① 基础

Message.vue

  • 展示Detail组件把消息带过去,展示的都是Detail组件,但是展示的数据是不同的



Detail.vue




② 展示

Message.vue


router/index.js

// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from '../pages/Detail'

//创建并暴露一个路由器
export default new VueRouter({
	routes:[
		{
			path:'/about',
			component:About
		},
		{
			path:'/home',
			component:Home,
			children:[
				{
					path:'news',
					component:News,
				},
				{
					path:'message',
					component:Message,
					children:[
						{
							path:'detail',
							component:Detail,
						}
					]
				}
			]
		}
	]
})

Vue中的ajax请求、Vuex、Vue UI组件库_第48张图片

③ 实现

Message.vue

  • 传递参数

Detal.vue

  • 接收传递的参数

实现

命名路由 name

router/index.js

  • name 属性
  • 作用:在跳转的时候可以简化一些编码
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from '../pages/Detail'

//创建并暴露一个路由器
export default new VueRouter({
	routes:[
		{
			name:'guanyu',
			path:'/about',
			component:About
		},
		{
			path:'/home',
			component:Home,
			children:[
				{
					path:'news',
					component:News,
				},
				{
					path:'message',
					component:Message,
					children:[
						{
							name:'xiangqing',
							path:'detail',
							component:Detail,
						}
					]
				}
			]
		}
	]
})

Message.vue

// 不配置名字  path



// 路由配置名字  name

路由接收参数之二:params参数
  • 如果使用的是params参数,就必须使用name,不能使用path 报错

Message.vue


router/index.js

//创建并暴露一个路由器
export default new VueRouter({
	routes:[
		{
			name:'guanyu',
			path:'/about',
			component:About
		},
		{
			path:'/home',
			component:Home,
			children:[
				{
					path:'news',
					component:News,
				},
				{
					path:'message',
					component:Message,
					children:[
						{
							name:'xiangqing',
							path:'detail/:id/:title',
							component:Detail,
						}
					]
				}
			]
		}
	]
})

Detail.vue


路由props配置
  • Detail 如何 读取出来别人传递过来的参数
  • props三种写法

router/index.js

//创建并暴露一个路由器
export default new VueRouter({
	routes:[
		{
			name:'guanyu',
			path:'/about',
			component:About
		},
		{
			path:'/home',
			component:Home,
			children:[
				{
					path:'news',
					component:News,
				},
				{
					path:'message',
					component:Message,
					children:[
						{
							name:'xiangqing',
							path:'detail',
							component:Detail,

			// props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
			// props:{a:1,b:'hello'}

			// props的第二种写法,值为布尔值,
           // 若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
			// props:true

							//props的第三种写法,值为函数
							props($route){
								return {
									id:$route.query.id,
									title:$route.query.title
								}
							}
						}
					]
				}
			]
		}
	]
})

第三种写法:简写过程,结构赋值和结构赋值的连续写法

							// 1
							props($route){
								return {
									id:$route.query.id,
									title:$route.query.title,
								}
							}
							// 2 结构赋
							props({query}){
								return {query.id,query.title}
							}
							// 3 结构赋值的连续写法 语义化不明确,不是十分推荐
							props({query:{id,title}}){
								return {id,title}
							}

Detail.vue



--------------------------------------------------------------------




router-link的replace属性
  • 路由对浏览器记录的影响
  • 结构:栈的结构 push 压栈
    • 指针默认指向最上面的结构 默认 push 模式
    • 替换当前栈顶的那一条 replace 模式

app.vue


About

Home

4、编程式路由导航

  • 不书写router-link 实现路由的跳转 转换成a标签
  • 需求一:实现用按钮来实现路由的跳转
  • 需求二:过几秒之后自动实现跳转

Message.vue




Vue中的ajax请求、Vuex、Vue UI组件库_第49张图片
Vue中的ajax请求、Vuex、Vue UI组件库_第50张图片

Banner.vue




Vue中的ajax请求、Vuex、Vue UI组件库_第51张图片

缓存路由组件

News.vue




Home.vue


Vue中的ajax请求、Vuex、Vue UI组件库_第52张图片

5、两个新的声明周期钩子

  • 案例:在news组件上面展示一串数据,颜色透明度发生改变
    • 生命周期中书写过

News.vue




问题:news组件没有被销毁,定期器一直调用,引出两个新的生命周期钩子,路由组件独有

  • activated,激活
  • deactivated,取消激活(失活)
  • News组件出现在你面前激活,消失在你面前失活



6、路由守卫

全局守卫
  • meta 标识是否需要进行权限的校验,路由元信息

  • meta:{isAuth:true,title:‘新闻’}

    • isAuth:true 是否授权
    • title:‘新闻’ 路由对应的title标题,点击时切换
  • 保护路由的权限

  • 设置权限

Vue中的ajax请求、Vuex、Vue UI组件库_第53张图片

router/index.js

// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from '../pages/Detail'

//创建并暴露一个路由器
const router =  new VueRouter({
	routes:[
		{
			name:'guanyu',
			path:'/about',
			component:About,
			meta:{title:'关于'}
		},
		{
			name:'zhuye',
			path:'/home',
			component:Home,
			meta:{title:'主页'},
			children:[
				{
					name:'xinwen',
					path:'news',
					component:News,
					meta:{isAuth:true,title:'新闻'}
				},
				{
					name:'xiaoxi',
					path:'message',
					component:Message,
					meta:{isAuth:true,title:'消息'},
					children:[
						{
							name:'xiangqing',
							path:'detail',
							component:Detail,
							meta:{isAuth:true,title:'详情'},

							//props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
							// props:{a:1,b:'hello'}

							//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
							// props:true

							//props的第三种写法,值为函数
							props($route){
								return {
									id:$route.query.id,
									title:$route.query.title,
									a:1,
									b:'hello'
								}
							}

						}
					]
				}
			]
		}
	]
})

//全局前置路由守卫————初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{ // 在每一次路由切换之前调用函数
   // to 去哪 from 来自于哪 next 放行
	console.log('前置路由守卫',to,from)
   //方式一: 路径	
// if(to.path === '/home/news' || to.path === '/home/messgae'){
   //方式二: 名字	
	// if(to.name === 'xinwen' || to.name === 'xiaoxi'){
// 方式三:推荐
	if(to.meta.isAuth){ // 判断是否需要鉴权
		if(localStorage.getItem('school')==='atguigu'){
			next()
		}else{
			alert('学校名不对,无权限查看!')
		}
	}else{
		next()
	}
})

// 全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
// 没有 next
router.afterEach((to,from)=>{
	console.log('后置路由守卫',to,from)
	document.title = to.meta.title || '硅谷系统'
})

export default router

Vue中的ajax请求、Vuex、Vue UI组件库_第54张图片

独享路由守卫
  • 某一个路由单独响应的路由守卫
  • 没有后置路路由守卫

对新闻路由进行限制

router/index.js

//创建并暴露一个路由器
const router =  new VueRouter({
	routes:[
		{
			name:'guanyu',
			path:'/about',
			component:About,
			meta:{title:'关于'}
		},
		{
			name:'zhuye',
			path:'/home',
			component:Home,
			meta:{title:'主页'},
			children:[
				{
					name:'xinwen',
					path:'news',
					component:News,
					meta:{isAuth:true,title:'新闻'},
					beforeEnter: (to, from, next) => {
						console.log('独享路由守卫',to,from)
						if(to.meta.isAuth){ //判断是否需要鉴权
							if(localStorage.getItem('school')==='atguigu'){
								next()
							}else{
								alert('学校名不对,无权限查看!')
							}
						}else{
							next()
						}
					}
				},
				{
					name:'xiaoxi',
					path:'message',
					component:Message,
					meta:{isAuth:true,title:'消息'},
					children:[
						{
							name:'xiangqing',
							path:'detail',
							component:Detail,
							meta:{isAuth:true,title:'详情'},
							props($route){
								return {
									id:$route.query.id,
									title:$route.query.title,
									a:1,
									b:'hello'
								}
							}

						}
					]
				}
			]
		}
	]
})


//全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{
	console.log('后置路由守卫',to,from)
	document.title = to.meta.title || '硅谷系统'
})

export default router
组件内路由守卫
  • beforeRouteEnter 当路由进入之前
  • beforeRouteLeave 当路由离开之前

about 组件 实现组件内路由守卫

about.vue


7、路由器的两种工作模式

router/index.js

const router =  new VueRouter({
	mode:'history',  // 两个值 一个 history 一个 hash
	routes:[
	]
})
hash模式
  • http://localhost:8080/#/home/message
    • 路径中带 # 号
    • 从# 号开始到结尾,路径值都叫hash值
  • 特点:不会随着http请求发给服务器
history模式
  • http://localhost:8080/home/message

区别:

  • hash 兼容性好
    • hash 在部署服务器时,没有问题,后面的路径当做hash值,不会带给服务器
  • history 兼容性略差
    • history 在部署服务器时,单页面点击可用,刷新输错,原因:路径后面当做资源,没有这个资源

history 模式解决404问题

  • 需要后端工程师的帮助

connect-history-api-fallback 在node JS中解决 history 模式404 的问题

服务器中 server

  • 安装:npm i connect-history-api-fallback

  • 引入:const history = require(‘connect-history-api-fallback’);

  • 应用:在app之前

  • app.use(history())
    app.use(express.static(__dirname+'/static'))
    

解决

Vue UI 组件库

1、移动端常用 UI 组件库

1、Vant https://youzan.github.io/vant

2、Cube UI https://didi.github.io/cube-ui

3、Mint UI http://mint-ui.github.io

4、NutUI https://nutui.jd.com/#/

2、PC 端常用 UI 组件库

1、Element UI https://element.eleme.cn

2、IView UI https://www.iviewui.com

  • 高度定制化的UI,不适合适用于UI组件库

完整引入 ElementUI组件库

ElementUI 中的组件全不都注册成全局组件,所有的样式,所有的组件

main.js

//完整引入
//引入ElementUI组件库
import ElementUI from 'element-ui';
//引入ElementUI全部样式
import 'element-ui/lib/theme-chalk/index.css';


//关闭Vue的生产提示
Vue.config.productionTip = false

//应用ElementUI
Vue.use(ElementUI);

//创建vm
new Vue({
	el:'#app',
	render: h => h(App),
})

Vue中的ajax请求、Vuex、Vue UI组件库_第55张图片

按需引入 ElementUI组件库

  • 安装npm install babel-plugin-component -D // -D 开发依赖

  • 将 .babelrc 修改为 新版本名字为 babel.config.js

  • module.exports = {
      presets: [
        '@vue/cli-plugin-babel/preset',
    		["@babel/preset-env", { "modules": false }],
      ],
    	plugins:[
        [
          "component",
          {
            "libraryName": "element-ui",
            "styleLibraryName": "theme-chalk"
          }
        ]
      ]
    }
    

Vue中的ajax请求、Vuex、Vue UI组件库_第56张图片

main.js

//按需引入
import { Button,Row,DatePicker } from 'element-ui';

//关闭Vue的生产提示
Vue.config.productionTip = false

//应用ElementUI
Vue.component(Button.name, Button); // 
Vue.component(Row.name, Row);
Vue.component(DatePicker.name, DatePicker);

//创建vm
new Vue({
	el:'#app',
	render: h => h(App),
})

你可能感兴趣的:(Vue,vue.js,ajax,javascript)