vue之vuex和router的使用
一、vuex的简介
# vue的插件,增强了vue的功能, 在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信 # Vuex的使用流程 -state:存数据的地址 -actions:服务员,中转站 -mutations:厨师,真正改state数据的地方
我们只要在创建vue项目的时候选择了Vuex那么就会帮我们自动下载了
如果没有 那么就需要手动下载
cnpm install Vuex
1.Vuex的流程图
2.代码演示
现在我们可以写一个添加购物车
首先我们要写两个组件 一个为购物车组件 一个为添加购物车组件
实现跨组件通信
2.1 Goods.vue
<template> <div> <div> <ul> <h1>模拟购物车</h1> <li>汽车---》 <button @click="addShoppingCart">点我加入购物车</button> </li> <li>自行车---》 <button @click="addShoppingCart">点我加入购物车</button> </li> <li>摩托车---》 <button @click="addShoppingCart">点我加入购物车</button> </li> <li>火车---》 <button @click="addShoppingCart">点我加入购物车</button> </li> </ul> </div> </div> </template> <script> export default { name: "Goods", methods: { addShoppingCart() { // 点击事件需要修改state的值 所以需要先执行dispatch函数 this.$store.dispatch('add', 1) // 第二个是我们传入的参数 // 这个时候就会执行actions中的add函数 } } } </script>
2.2 shoppingcart.vue
<template> <div> <p>Vuex中的state中的值 显示在这里 模拟购物车数量:{{ $store.state.shoppingNum }}</p> </div> </template> <script> export default { name: "shoppingcart" } </script>
2.3 Vuex
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) // 插件 export default new Vuex.Store({ state: { shoppingNum: 0 // 购物车数量 }, mutations: { // 这个时候就可以修改state的值了 up(state, num) { state.shoppingNum += num } }, actions: { // 执行dispatch其实就是执行了actions 该对象中可以写多个函数 add(context, num) { // 第一个参数是context 内部有commit和dispatch // 调用commit会触发mutations执行 // 执行dispatch会触发actions中函数的执行 // 所以这里可以写逻辑代码 就是把用户的token传入到后端看一下该用户有没有权限 // 有权限在修改 没有就返回 我们就默认可以执行 context.commit('up', num) // 这个时候就会触发mutations中的up函数执行 } }, })
2.4 app.vue
<template> <div id="app"> <h2>购物车组件:</h2> <shoppingcart></shoppingcart> <h2>添加购物车组件:</h2> <Goods></Goods> </div> </template> <script> import Goods from '@/components/Goods' import shoppingcart from '@/components/shoppingcart' export default { components: { Goods,shoppingcart // 将子组件注册 } } </script>
2.5 使用步骤
1 在state中定义变量 2 在组件中通过this.$store.dispatch('actions中定义的函数'),触发actions中得函数执行 3 在actions中得函数中,调用 context.commit('mutations中定义的函数') 4 在mutations中定义的函数实现真正的修改state中得数据 5 页面中只要使用$store.state.变量,变量变化,页面就变化 实现了组件间通信 6 注意: -在组件中可以直接调用commit触发【mutations中定义的函数】 -在组件中可以直接修改state中定义变量
注意:
addShoppingCart() { this.$store.state.shoppingNum ++ // 其实可以直接改 但是不建议 this.$store.commit('up', 1) // 也可以直接调用mutations中的up 也不建议 }
二、Vue-router的使用
# 我们现在开发vue都是单页面开发 那么这肯定是不对的 那么怎么多页面开发呢? 那么就需要router的使用 这样就可以跳转到其他页面 # 官方提供的用来实现SPA 的vue 插件:有了它以后,我们可以写很多页面组件,通过地址栏不同的路径显示不同的页面组件
更多知识点:https://router.vuejs.org/zh/index.html
# 也是一样的 在创建vue项目的时候 只需要选择了 router那么就会帮我们自动创建 # 没有选择的话需要手动下载 cnpm install router
1 使用步骤
# 1.新建文件夹router/index.js 在const routes中写路由配置 const routes = ['路由1','路由2'] # 2 在main.js中使用,已经写好了 import router from './router' new Vue({ ... router, ... }).$mount('#app') # 3 只需要写页面组件,配置路由即可 # 4 在App.vue中加入 <router-view> # 配置好了路由 那么就会在这个标签中显示 </router-view> # 5 在浏览器访问const routes中配置的路径,就能看到对应的页面组件了
2 代码演示 路由跳转
创建两个组件:home组件 login组件
2.1 home.vue
<template> <div> <h1>我是首页</h1> <router-link :to="path">去登入</router-link> </div> </template> <script> export default { name: "Home", data() { return { path: 'login' } }, } </script>
2.2 login.vue
<template> <div> <p>用户名:<input type="text" v-model="username"></p> <p>密码:<input type="text" v-model="password"></p> <p> <button>登入</button> </p> </div> </template> <script> export default { name: "Loginview", data() { return { username: '', password: '' } }, } </script>
2.3 index.js
import Vue from 'vue' import VueRouter from 'vue-router' import Loginview from "../views/Loginview"; import Home from "../views/Home"
Vue.use(VueRouter) const routes = [ { path: '/', // 首页 name: 'home', // 取别名 component: Home // home组件的名字 }, { path: '/login', name: 'login', component: Loginview }, ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router
2.4 app.vue
<template> <div id="app"> <!--外面写的标签是每个组件都会显示--> <router-view> <!--以后app.vue其实只要写个router-view标签即可--> </router-view> </div> </template> <script> export default { } </script>
3 路由跳转的多种用法
<!--第一种绑定变量 然后变量绑定 router中的name值--> <router-link :to="path">登入</router-link> data() { return { path: 'login' <!--这个login是router中我们自己写的name值--> } <!--第二种写字符串 也是写router中的name值--> <router-link to="login">登入</router-link> <!--第三种 绑定事件 使用js跳转--> <button @click="handleLogin">点我登录</button> methods: { handleLogin() { this.$router.push('login') <!--这里的login也是router中我们自己写的name值--> } }
4 携带参数跳转
# 两种情况 -带在请求地址中以 ?name=lqz&age=19 -在地址中类似于django的分组 /goods/1/
4.1 第一种
<!--第一种:有两种写法 --> <!--第一种写法:--> <router-link to="/login/?name=lqz&age=19">去登录</router-link> <!--直接在地址后面写--> 组件中接收: this.$route.query created() { console.log(this.$route.query) }, <!--第二种写法:--> <router-link :to="path">去登录</router-link> <!--绑定变量--> <script> export default { name: "Home", data() { return { path: { // 给path写一个对象 name: 'login', // 这里写router中name值 query: {name: 'lqz', age: 19} // 往query中写参数 } }, } </script> 组件中接收跟第一种写法是一样的: this.$route.query created() { console.log(this.$route.query) },
4.2 第二种
<!--第二种也有两种写法--> <!--第一种写法--> <router-link to="/login/1">去登录</router-link> <!--也是直接在后面加上--> 组件中接收: this.$route.params.id <script> created() { // 方式二:/login/1 console.log(this.$route.params.id) }, </script> <!--第二种写法--> <router-link :to="path">去登录</router-link> <script> data() { return { path: { name: 'login', params: {id: 'lyf'} // 直接在params中写上对象 } } }, </script> <!--第二种写法的组件接收 跟第一种写法是一样的--> this.$route.params.id <script> created() { // 方式二:/login/1 console.log(this.$route.params.id) }, </script> <!--这样就可以根据用户选择的id或则其他来过滤掉一些数据-->
5 路由嵌套
# 就是像这样 goods/list ... 在该标签中还可以继续加点击路由
我们可以在商城下再来几个路由 :goods/list、goods/detail、goods/shopcart 但是如果是嵌套那么必须写在goods路由中的children下
5.1 index.js
const routes = [ { path: '/', name: 'home', component: Home }, { path: '/goods', name: 'goods', component: Goods, children: [ // 在children中编写 goods的子路由 { name: 'list', // 也是name和path,component path: 'list', component: GoodList }, { name: 'detail', path: 'detail', component: GoodDetail }, { name: 'shoppingcart', path: 'shoppingcart', component: ShoppingCart } ] },
5.2 goods.vue
<template> <div> <h1>我是商品</h1> <p> <router-link to="/goods/detail"><span>详情</span></router-link> | <router-link to="/goods/list"><span>列表</span></router-link> | <router-link to="/goods/shoppingcart"><span>购物车</span></router-link> </p> <router-view> <!--在goods组件中在写一个router-view标签 那么goods的子路由就会显示在这个标签中--> </router-view> </div> </template>
5.3 总结
# 使用步骤: 1 router/index.js 相应的路由中 { path: '/goods', name: 'goods', component: Goods, children: [ { path: 'list', component: GoodList }, { path: 'detail', component: GoodDetail } ] }, 2 必须要在Goods组件中,写<router-view></router-view> 3 使用router-link标签跳转 4 只会变更Goods下router-view包裹的位置
6 路由守护
# 就是根据用户的权限来判断用户能不能使用这个路由
6.1 代码演示
# 我们可以根据用户登入的时候把用户信息放入到localStorage然后在用户在点击路由的时候来判断 用户是否有没有这个权限
6.2 home.vue
<!--模拟用户登入成功 然后把用户信息放入到 localStorage--> <button @click="handleLogin">点我登录</button> <script> export default { methods: { handleLogin() { localStorage.setItem('name', 'lqz') // 放入到localStorage中 } } } </script>
6.3 index.js
router.beforeEach((to, from, next) => { // 前置路由守护 就是路由在访问之前先做判断 // to:去到哪个路由 from:来自哪个路由 console.log('前置路由守卫', to, from) if (to.name == 'shoppingcart') { // 判断当前用户是不是要去shoppingcart这个路由 let name = localStorage.getItem('name') if (name) { // 在判断localStorage 中是否有值 next() // 有值就跳过 } else { alert('不好意思没有权限') // 没值就相当于没有权限 } } else { next() } })
上面这个是前置守护 还有后置守护
router.afterEach((to,from)=>{ console.log('后置路由守卫',to,from) // 后置守护就是进入到了这个路由但是出来的时候可以判断一下 document.title = to.name })