Vue路由与Vuex
2019-12-20 本文已影响0人
Aeroball
一、 VueRouter
Vue Router是Vue.js官方的路由管理器。它和Vue.js的核心深度集成,让构建单页面应用变得易如反掌
1.1 安装
npm install vue-router --save
本次协同bootstrap开发,所以也安装了bootstrap,并指定3.3.7版本
npm install bootstrap@3.3.7 --save
1.2 配置路由信息
新建一个router文件夹,并定义一个index.js文件,该文件配置如下:
import Vue from 'vue'
import Router from 'vue-router'
const About = () => import('../views/About') //按需加载,用到时才加载
const Home = () => import('../views/Home')
Vue.use(Router)
export default new Router({
//mode是模式,默认是hash
mode: 'history',
routes: [
{
path: '/about',
component: About
},
{
path: '/home',
component: Home
},
{
path: '/',
redirect: '/home' //根路径默认会重定向到/home
}
]
})
1.3 main.js文件配置
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 这是标准的使用bootstrap的方式, npm install bootstrap@3.3.7 --save
import 'bootstrap/dist/css/bootstrap.min.css'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
1.4 访问与渲染
使用<router-link>标签设置路径,to属性设置路由路径
<li class="list-group-item"><router-link to="/home">Home</router-link></li>
<li class="list-group-item"><router-link to="/about">About</router-link></li>
使用<router-view></router-view>标签,将对应的路由组件设置到这个标签当中:
<router-view></router-view>
1.5 子路由
在路由的配置中使用children配置子路由,如下配置about的子路由
path: '/about',
component: About,
children: [
{
//建议写绝对路径
path: '/about/info',
component:Info
}
]
1.6 参数的传递
在使用路由的过程中,经常会碰到路由参数的传递,那么传递的方式大概有三种
- 方式一
1. 路由配置
{path: '/about/info/:name/:id',component:Info,props: true}
2. 路由请求
<router-link :to="'/about/info/' + user.name + '/' + user.id">{{user.name}}</router-link>
3. 取值
在Info中使用 props: {name: String,id: String}来接受数据
- 方式二
路由请求:
<router-link :to="`/about/info/${user.name}/${user.id}`">{{user.name}}</router-link>
- 方式三
1. 路由配置
{path: '/home/detail/:id',component: Detail,props: true}
2. 路由请求
<router-link :to="{path: '/home/detail/'+user.id, query: {name: user.name}}">{{user.name}}</router-link>
3. 取值
mounted() { //第一次刷新时无法监听到,所以需要用mounted
this.name = this.$route.query.name;
},
watch: { //监听路由的变化
$route: function (newVal) {
this.name = newVal.query.name;
}
}
1.7 路由守卫
1.7.1 局部路由守卫
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
1.7.2 全局路由守卫
router.beforeEach((to,from,next) =>{
next();
});
1.8 编程式路由
实现页面跳转
实现跳转:
this.$router.push({
path: '/user',
query: {id:id}
});
取值:
mounted() {
this.id = this.$route.query.id;
},
watch:{
$route: {
handler(val) {
this.id = val.query.id;
}
}
}
二、 vuex
2.1 vuex是什么
vuex是对vue项目进行状态管理的js库,对于所有的组件来说,它是一个中央存储,这种模式就保证了只能按照特定的模式来更改状态。
2.2 vuex的五大核心
- state:说白了就是存储数据的地方
- actions:通过异步的方式更改状态值,但是不能直接更改,需要借助mutations来更改。
- mutations:通过直接同步的方式更改状态
- getters:类似于计算属性,通常是需要通过state来间接计算得到的值
- modules:一个项目中因为模块的原因,存在着各种不同的状态,需要按照模块来划分
2.3 安装store
npm install vuex --save
2.4 建立store
- 新建一个文件夹,名字叫store,在文件夹中新建一个index.js文件:
import Vue from 'vue'
import Vuex from 'vuex'
import infos from './infos'
Vue.use(Vuex);
// 对外暴露Vuex.Store的对象,在其他任何组件中都可以使用 $store来进行操作
export default new Vuex.Store({
modules: { //模块化管理
infos
}
})
- 在store文件夹中新建一个文件夹,名字叫infos,然后在info文件夹中新建一个index.js文件:
//state中是具体存放数据的地方
const state = {
todos: [
{title:'吃饭', completed: false},
{title:'睡觉', completed: true},
{title:'打豆豆', completed: false},
]
};
// 直接操作state中的数据
const mutations = {
/**
* mutations中定义方法的第一个参数全部都是state,
* 但是方法在具体调用的时候,将其忽略掉。
*/
addTodo(state, todo) {
state.todos.push(todo);
}
}
//actions是间接的操作state的数据的,是通过指挥mutations来操作
const actions = {
/**
* actions中第一个参数必须是context, 在调用的时候将其忽略掉,context的作用是
* 调用mutations的。
*/
addTodo(context, todo) {
// 该句话的意识是调用 mutations中的 addTodo方法,传入todo
context.commit('addTodo', todo);
}
}
// state的计算属性
const getters = { //只能对应get
//计算所有已经完成的todos的长度
completedTodosLength: state => {
return state.todos.reduce((num, todo) => num + (todo.completed ? 1 : 0), 0);
},
// 所有的todos的长度
todosLength: state => {
return state.todos.length;
}
}
export default {
namespaced: true, //命名空间
state,
mutations,
actions,
getters
}
2.5 main.js配置
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App),
}).$mount('#app')
2.6 组件中使用
2.6.1 方式一
this.$store.state.infos.todos //获取状态值
this.$store.commit('addTodo', todo); //通过mutations中的方法更新状态
this.$store.dispatch('addTodo', todo); //通过actions中的方法异步更新状态
this.$store.getters.completedTodoNumber; //获取getters中的属性
注意:
这里加了modules模块管理,所以获取state的时候需要加上infos命名空间,至于getters、actions、mutations都被注册到全局上,和之前的使用方式一样。
2.6.1 方式二 映射函数调用(扩展表达式方式)
import {mapState, mapActions, mapGetters, mapMutations} from 'vuex'
computed: {
// vuex中getters以及state都是在 计算属性中进行扩展的
// ...mapState('infos', {todos: state=>state.todos}) //state的扩展稍微有点不一样
...mapState({todos: state=>state.infos.todos})
// 将getters扩展到本地,需要在计算属性中扩展
...mapGetters('infos', ['completedTodosLength', 'todosLength']),
allTodosCompletedState: {
get() {
// 如果已经完成的todos的长度与总长度一致,就返回true
return this.completedTodosLength == this.todosLength;
},
set(value) {
this.changeAllTodosStatus(value);
}
}
},
methods: {
//引号中的内容为actions中定义的方法名, 可以直接使用this.addTodo来调用。
...mapActions('infos', ['addTodo']), //['addTodo']是数组,可以放多个
...mapMutations('infos',['addTodo'])
}