1基础用法
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
router/index.js
里面注释的部分 包含路由独享守卫 与路由全局守卫
import Vue from 'vue'
import Router from 'vue-router'
import List from '@/components/list.vue';
import About from '@/components/about.vue';
import Detail from '@/components/detail.vue';
import Login from '@/components/login.vue';
import HelloWorld from '@/components/HelloWorld.vue';
Vue.use(Router)
let router = new Router({
mode:"history",
base:process.env.BASE_URL,
routes:[
{
path: '/',
name: 'HelloWorld',
component: HelloWorld,
children:[{
path: '',
name: 'List',
component: List,
},
{path:'/detail/:id',
name:Detail,
component:Detail
}
]
},
{
path: '/about',
name: 'About',
// beforeEnter:(to,from,next) => {//路由独享守卫
// // //判断是否登陆
// if(!window.isLogin){//如果去about页 并且没登陆 那么就去登陆页
// next('/login?redirect='+to.path)
// }else{
// next()
// }
// },
component: About,
},
{
path: '/login',
name: 'Login',
component: Login,
}
]
})
//每次路由激活前都会执行回调函数
// router.beforeEach((to,form,next)=>{ //全局的守卫
// //判断是否登陆
// if(to.path ==='/about'&&!window.isLogin){//如果去about页 并且没登陆 那么就去登陆页
// next('/login?redirect='+to.path)
// }else{
// next()
// }
// })
export default router
about.vue
组件守卫
<template>.
<div>
about
</div>
</template>
<script>
export default {
beforeRouteEnter(to,from,next){//组件守卫
//判断是否登陆
if(!window.isLogin){// 没登陆 那么就去登陆页
next('/login?redirect='+to.path) //重定向
}else{
next()
}
}
}
</script>
<style scoped>
</style>
login.vue
<template>
<div>
登陆
<button @click="onload">登陆</button>
</div>
</template>
<script>
export default {
methods: {
onload() {
window.isLogin = true
let redirect = this.$route.query.redirect||'/'
this.$router.push(redirect)
}
},
}
</script>
<style scoped>
</style>
list.vue
<template>
<div>
<ul>
<li v-for="item in data" :key="item.price">
<router-link :to="`/detail/${item.id}`">
<span>{{ item.name }}</span>
<span>{{ item.price }}</span>
<!-- 去掉默认行为和冒泡 -->
<button @click.prevent.stop="addCar(item)">添加购物车</button>
</router-link>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
data: [
{ name: "辣条", price: 10, id: 1 },
{ name: "糖果", price: 1, id: 2 }
]
};
},
methods: {
addCar(){
}
},
}
</script>
<style scoped>
</style>
HelloWorld.vue
<template>
<div>
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>
app.vue
<template>
<div id="app">
<div>
<router-link to="/about">ABOUT</router-link>
<router-link to="/">HOME</router-link>
<router-link to="/login">登录</router-link>
</div>
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
.
.
.
原理
app.vue
<!--
* @Author: yang
* @Date: 2020-08-03 09:47:09
* @LastEditors: yang
* @LastEditTime: 2020-08-10 14:28:35
* @FilePath: \project\src\App.vue
-->
<template>
<div id="app">
<div>
<router-link to="/about">ABOUT</router-link>
<router-link to="/">HOME</router-link>
<router-link to="/login" v-if="!isLogin">登录</router-link>
<span v-else>{{getLogin}}</span>
</div>
<router-view/>
<button @click="addCount">加一</button>
{{count}}
</div>
</template>
<script>
import {mapState,mapGetters} from 'vuex'
import store from './Ystore.js'
export default {
name: 'App',
computed: {
...mapState(['isLogin']),
...mapGetters(['getLogin']),
count(){
return store.state.count
},
},
methods: {
addCount(){
store.commit('add')
},
},
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
login.vue
<!--
* @Description:
* @Autor: wangDuJuan
* @Date: 2020-08-08 14:45:23
-->
<template>
<div>
登陆
<h1>用户登录</h1>
<button @click="onload">{{loadding?'登陆中':"登陆"}}</button>
</div>
</template>
<script>
import {mapActions} from 'vuex'
export default {
data() {
return {
loadding: false
}
},
methods: {
...mapActions(['requestLogin']),
onload() {
// window.isLogin = true
// commit提交
// this.$store.commit('login')
// action dispatch
this.loadding = true
let that = this
this.requestLogin({name:'tom'}).then((login)=>{
console.log(that.$route.query.redirect)
// that.loadding = false
console.log(that.loadding)
let redirect = that.$route.query.redirect||'/'
that.$router.push(redirect)
})
}
},
}
</script>
<style scoped>
</style>
home.vue
<template>
<div>
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>
about.vue
<!--
* @Description:
* @Autor: wangDuJuan
* @Date: 2020-08-08 14:45:01
-->
<template>
<div>
about
</div>
</template>
<script>
export default {
// beforeRouteEnter(to,from,next){//组件守卫
// //判断是否登陆
// if(!window.isLogin){// 没登陆 那么就去登陆页
// next('/login?redirect='+to.path) //重定向
// }else{
// next()
// }
// }
}
</script>
<style scoped>
</style>
store.js
/*
* @Description:
* @Autor: wangDuJuan
* @Date: 2020-08-08 18:07:01
*/
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state:{
isLogin:false
},
mutations:{
login(state){
state.isLogin = true
}
},
getters:{
getLogin(state){
return state.isLogin ? '欢迎回来':'游客'
}
},
actions:{
requestLogin(context,prop){
//context函数的上下文 prop 传过来的参数
console.log(context,prop)
return new Promise((resolve)=>{
setTimeout(()=>{
resolve(true)
context.commit('login')
},1000)
})
}
}
})
router.js
/*
* @Description:
* @Autor: wangDuJuan
* @Date: 2020-08-08 14:31:45
*/
import Vue from 'vue'
import Router from 'vue-router'
import List from '@/components/list.vue';
import About from '@/components/about.vue';
import Detail from '@/components/detail.vue';
import Login from '@/components/login.vue';
import HelloWorld from '@/components/HelloWorld.vue';
import store from './store.js'
Vue.use(Router)
let router = new Router({
mode:"history",
base:process.env.BASE_URL,
routes:[
{
path: '/',
name: 'HelloWorld',
component: HelloWorld,
children:[{
path: '',
name: 'List',
component: List,
},
{path:'/detail/:id',
name:Detail,
component:Detail
}
]
},
{
path: '/about',
name: 'About',
// beforeEnter:(to,from,next) => {//路由独享守卫
// // //判断是否登陆
// if(!window.isLogin){//如果去about页 并且没登陆 那么就去登陆页
// next('/login?redirect='+to.path)
// }else{
// next()
// }
// },
component: About,
},
{
path: '/login',
name: 'Login',
component: Login,
}
]
})
//每次路由激活前都会执行回调函数
router.beforeEach((to,form,next)=>{ //全局的守卫
//判断是否登陆
if(to.path ==='/about'&&!store.state.isLogin){//如果去about页 并且没登陆 那么就去登陆页
next('/login?redirect='+to.path)
}else{
next()
}
})
export default router
Yrouter.js
/*
* @Description:
* @Autor: wangDuJuan
* @Date: 2020-08-09 16:24:02
*/
class VueRouter{
constructor(Vue,options){
this.$option = options
this.routeMap = {}
this.app = new Vue({
data:{
current:'#/'
}
})
this.init()
this.initCreateRouterMap(options)
this.initComponent(Vue)
}
init(){
window.addEventListener('load',this.onHashchange,false)
window.addEventListener('hashchange',this.onHashchange,false)
}
getHash(){
return window.location.hash.splice(1)||'/'
}
onHashchange(){
this.app.current = this.getHash()
}
initCreateRouterMap(options){
options.routers.forEach(item=>{
this.routeMap[item.path] = item.component
})
}
initComponent(Vue){
// props可以使用实例中的变量赋值
// 全局组件可以获取用使用prop 的做操作 ,指定类型
Vue.component('router-link',{
prop:{
to:String
},
// 用来访问被 slot 分发的内容。每个具名 slot 有其相应的属性
// (例如:slot="foo" 中的内容将会在 vm.$slots.foo 中被找到)
// default 属性包括了所有没有被包含在具名 slot 中的节点。
render:function(h){
return h(
"a",
{attr:{href:this.to}},
this.$slots.default
)
}
})
let _this = this
Vue.component('route-view',{
render(h){
let component = _this.routeMap[_this.app.current]
h(component)
}
})
}
}
Ystore.js
/*
* @Description:
* @Autor: wangDuJuan
* @Date: 2020-08-09 15:24:40
*/
import Vue from 'vue'
class Ystore{
constructor(options){
this.state = options.state
this.mutations = options.mutations
this.actions = options.actions
// 借助Vue本身的数据响应机制
new Vue({
data:{
state:this.state
}
})
}
commit(type,payload){
let mutation = this.mutations[type]
mutation(this.state,payload)
}
dispatch(type,payLoad){
let action = this.actions[type]
// createClass 创建类的函数里面中es5的写法默认是绑定了bind方法,而es6中 新增加了class,绑定的方法需要绑定this,如果是箭头函数就不需要绑定this,用箭头的方式
let atx= {
state:this.state.bind(this),
mutations:this.mutations,
dispatch:this.dispatch.bind(this)
}
return action(atx,payLoad)
}
}
export default new Ystore({
state:{
count:1
},
mutations:{
add(state){
state.count++
}
}
})
vue.config.js(mock数据)
/*
* @Author: yang
* @Date: 2020-08-07 11:36:56
* @LastEditors: Please set LastEditors
* @LastEditTime: 2020-08-08 19:03:45
* @FilePath: \testproject\vue.config.js
*/
// node代码
module.exports = {
publicPath:'/cart',
lintOnSave: false,
configureWebpack:{//webpack的配置项 webpack开发服务器
devServer:{//mock数据 服务器的代理 都可以在这里配置
before(app){ //在服务器启动之前的钩子函数,在这里可以对服务器的实例做一些提前的操作
//app 是express的实例
app.get('/goods',(req,res)=>{
res.json([{
id:1,text:'kk'
},{id:2,text:'lll'}
])
})
}
}
}
}