作者: gh-xiaohe
gh-xiaohe的博客
觉得博主文章写的不错的话,希望大家三连(✌关注,✌点赞,✌评论),多多支持一下!!!
总结:
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
安装 axios
- npm i axios
- 引入 import axios from ‘axios’
app.vue
解决跨域
- cors 不用前端人员做任何的事情
- 写服务器(后端人员)的人,在服务器里面,给你返回响应的时候,加几个特殊的响应头
- 不是随便的配置的,造成的后果,任何人都可以找你这台服务器要数据
- jsonp 开发时使用微乎其微
- 借助了 srcipt 便签里面 src 属性 不受同源策略限制
- 前端人员需要写特殊的写法,后端人员也需要配合你,并且只能解决 get请求
- 代理服务器
- 和所处的位置(前端)是一样的,协议名、主机名、端口号都保持一致
- 服务器和服务器之间传递不用ajax,使用的是传统的http请求
- nginx 代理服务器
- vue-cli 开启一个代理服务器
细节:
vue.config.js
// 开启代理服务器 devServer: { proxy: 'http://localhost:5000' },
app.vue
端口改成8080
开启代理服务器(方式二) 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
项目接口:https://api.github.com/search/users?q=xxx
① 基础
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 中的样式
Search Github Users
Search.vue
- 获取用户输入
- 发送请求
- 把数据通过全局事件总线的方式传递给list
Search Github Users
//创建vm new Vue({ el:'#app', render: h => h(App), beforeCreate() { Vue.prototype.$bus = this }, })
List.vue
- List接收数据 Search 传输数据
- avatar_url 用户的头像地址 展示
- html_url 每一个人的github主页 点击时实现跳转
- login 用户的登录名 展示
>
List.vue
Search.vue
App.vue
List.vue
Search.vue
Search Github Users
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 }, })
通用的 Ajax 请求库, 官方推荐,使用广泛
vue 插件库, vue1.x 使用广泛, 官方已不维护。
安装
- npm i vue-resource
引入插件
- import VueResource from ‘vue-resource’
使用插件
- vue.use(VueResource )
vm 和 vc 身上都多了 $http:(…)
Search.vue
总结:
① 基础
Category.vue
xxxxxx分类
- xxxx
- xxxx
- xxxx
- xxxx
app.vue
Category.vue
{{title}}分类
- {{item}}
app.vue
app.vue
- {{g}}
Category.vue
props:['title']{{title}}分类
我是一些默认值,当使用者没有传递具体结构时,我会出现 ok 实现
① 基础
Category.vue
{{title}}分类
我是默认的一些内容 app.vue
- {{g}}
- {{g}}
- {{g}}
- 插槽也就不需要了
Category.vue
{{title}}分类
- {{g}}
app.vue
同样实现
③ 需求:数据是一样的,数据的结构根据使用者的结构来定义
games 的作用域,games 在 Category 中,app中如何使用
插槽提供了便捷的方式,插槽绑定 games,就传给了插槽的使用者
使用者如何拿到,使用template标签 属性scope=“名字随意”,就可以收到数据
第一次使用数据是无序列表
第二次使用数据是有序列表
第二次使用数据每一个都是 h4 标题
Category.vue
{{title}}分类
我是默认的一些内容 app.vue
- {{g}}
- {{g}}
{{g}}
ok 实现
总结:
- 此时组件太多了,而且数据共享
① 基础结构
Count.vue
当前求和为:????
app.vue
② Count.vue
当前求和为:{{sum}}
方式一: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, })
//引入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的位置
- 简单易懂
// 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
当前求和为:{{$store.state.sum}}
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, })
问题一:
问什么在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(书写业务逻辑)中,可以写在方法中,同样可以实现,看组件就非常的直观
- 原因:比如不是加操作,而是发票的报销,传递的是发票号,非常非常复杂的发票报销判断逻辑,
- 难不成所有的人的都要写复杂的逻辑判断,自己发请求去链接服务器验证发票的真伪,非常冗余,可复用性高
① 让sum的值放大十倍展示
- 日后的逻辑可能很复杂,而且可能不止使用一个getters
当前求和为:{{$store.state.sum}}
当前求和放大10倍为:{{$store.state.sum * 10}}
- 计算属性实现
- 计算属性不能跨组件使用,只能自己组件使用
当前求和为:{{$store.state.sum}}
当前求和放大10倍为:{{dahe}
- 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
当前求和为:{{$store.state.sum}}
当前求和放大10倍为:{{$store.getters.bigSum}}
① 需求
- 展示我自己在自学,学习前端,学习方式,和学习内容是State中的数据
store/index.js
//准备state——用于存储数据 const state = { sum: 0, //当前的和 school: '自学', subject: '前端' }
Count.vue
当前求和为:{{$store.state.sum}}
当前求和放大10倍为:{{$store.state.sum * 10}}
我自己在{{$store.state.school}},学习{{$store.state.subject}}
简化想要实现的效果
- 把$store.state 省略不写
当前求和为:{{sum}}
当前求和放大10倍为:{{bigSum}}
我自己在{{school}},学习{{subject}}
② 实现
- 计算属性,就自己组件使用
- 使用Vuex中的==…mapState== 和 …mapGetters来实现
- 需要引入
优化:actions
- 需要引入
Count.vue
优化
在写一个组件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
人员列表
- {{p.name}}
② 实现多组件共享数据
store/index.js
//准备mutations——用于操作数据(state) const mutations = { ADD_PERSON(state, value) { console.log('mutations中的ADD_PERSON被调用了') state.personList.unshift(value) } }
person.vue
人员列表
Count组件求和为:{{sum}}
- {{p.name}}
count.vue
Person组件的总人数是:{{personList.length}}
person.vue
Count组件求和为:{{sum}}
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 } }
// 求和相关的配置 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 } })
Count.vue
① 非简写
当前求和为:{{countAbout.sum}}
当前求和放大10倍为:{{countAbout.bigSum}}
我在{{countAbout.school}},学习{{countAbout.subject}}
Person组件的总人数是:{{personAbout.personList.length}}
② 简写
- 开启命名空间:namespaced:true,
- …mapState、…mapMutations、…的简写方式
当前求和为:{{sum}}
当前求和放大10倍为:{{bigSum}}
我在{{school}},学习{{subject}}
Person组件的总人数是:{{personList.length}}
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'
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) } ) } } }
- 之后正常引用
总结:
实现什么功能:
SPA(single page web application)应用,单页面应用
① 基础
样式都是引入的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), })
app.vue
Home.vue
我是Home的内容
About.vue
我是About的内容
安装 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 } ] })
找到导航区,切换路径
需要路由提供的特殊的标签router-link引入,不是href 而是 to=“/home”,router-view制定位置呈现
router-link 最终转换成的是 a 标签,如果是按钮等等跳转,后面 编程式路由导航
app.vue
About Home
1、路由组件和一般组件
- 路由组件:不需写组价标签,靠路由规则,匹配出来,由路由器来进行渲染的组件。 pages放置路由组件
- 一般组件:亲自书写组件,是一般组件。components
- 路由组件被销毁了
3、路由组件身上多了两个人,$route 和 $ routers、
- route:配置信息
- routers: 整个应用的路由器只有一个,800个路由规则也只有一个路由器
效果
Home.vue
- 路径要加上一级路由的路径
//原来
Home组件内容
// 最新Home组件内容
Message.vue
News.vue
- news001
- news002
- news003
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, } ] } ] })
效果
Message.vue
- 展示Detail组件把消息带过去,展示的都是Detail组件,但是展示的数据是不同的
Detail.vue
- 消息编号:???
- 消息标题:???
② 展示
Message.vue
{{m.title}}
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, } ] } ] } ] })
Message.vue
- 传递参数
{{m.title}}
Detal.vue
- 接收传递的参数
- 消息编号:{{$route.query.id}}
- 消息标题:{{$route.query.title}}
实现
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 {{m.title}} {{m.title}}
Message.vue
{{m.title}}
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
- 消息编号:{{$route.params.id}}
- 消息标题:{{$route.params.title}}
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
--------------------------------------------------------------------
- 消息编号:{{$route.params.id}}
- 消息标题:{{$route.params.title}}
- 消息编号:{{id}}
- 消息标题:{{title}}
app.vue
About Home
Message.vue
{{m.title}}
Banner.vue
Vue Router Demo
News.vue
- news001
- news002
- news003
Home.vue
Home组件内容
News.vue
- 欢迎学习Vue
- news001
- news002
- news003
问题:news组件没有被销毁,定期器一直调用,引出两个新的生命周期钩子,路由组件独有
- activated,激活
- deactivated,取消激活(失活)
- News组件出现在你面前激活,消失在你面前失活
- 欢迎学习Vue
- news001
- news002
- news003
meta 标识是否需要进行权限的校验,路由元信息
meta:{isAuth:true,title:‘新闻’}
保护路由的权限
- 设置权限
// 该文件专门用于创建整个应用的路由器 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
对新闻路由进行限制
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
about 组件 实现组件内路由守卫
about.vue
router/index.js
const router = new VueRouter({ mode:'history', // 两个值 一个 history 一个 hash routes:[ ] })
区别:
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'))
解决
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/#/
1、Element UI https://element.eleme.cn
2、IView UI https://www.iviewui.com
完整引入 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), })
安装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" } ] ] }
//按需引入 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), })