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的五大核心
2.3 安装store
npm install vuex --save
2.4 建立store
  1. 新建一个文件夹,名字叫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
    }
})
  1. 在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'])
}
上一篇下一篇

猜你喜欢

热点阅读