Vue3 路由
 一、安装路由
 1、创建新项目
vue create vuecli
please pick a preset:
  Default ([Vue 2] babel, eslint)
  Default (Vue 3) ([Vue 3] babel, eslint)
  Manually select features
Check the features needed for your project:
  Choose Vue version                  
  Babel                               
  TypeScript                          
  Progressive Web App (PWA) Support   
  Router                              
  Vuex                                
  CSS Pre-processors                  
  Linter / Formatter                  
  Unit Testing                        
  E2E Testing                         
Choose a version of Vue.js that you want to start the project with:
  2.x
  3.x
Use history mode for router? (Requires proper server setup for index fallback in production)
    y
    n
Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default):
  Sass/SCSS (with dart-sass)
  Sass/Scss (with node-sass)
  Less
  Stylus
Where do you prefer placing config for Babel, ESlint, etc.?
  In dedicated config files   
  In package.json             
Save this as a preset for future projects?
  y   
  n   
 2、关闭语法检查器(eslint)
module.exports = {
    
    lintOnSave: false,
    devServer: {
        overlay: {
            warnings: false, 
            errors: false, 
        }
    }
};
 二、路由介绍(Vue Route)
- 跳转到当前页面前,进行操作
- 离开当前页面后,进行操作
- 路径名称,别名
- 获取url:完整url,不带域名url
- url上的参数
 三、路由操作
 1、配置新路由
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'   
import store from './store'     
createApp(App).use(store).use(router).mount('#app')
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
    {
        path: '/',
        name: 'Home',
        component: Home
    },
    {
        path: '/about',
        name: 'About',
        component: () => import('../views/About.vue')
    }
]
const router = createRouter({
    history: createWebHistory(process.env.BASE_URL),
    routes  
})
export default router
<template>
    <div>
        <h1>这是用户中心页面</h1>
    </div>
</template>
<script>
export default {
    name: "User",
};
</script>
<template>
    <div>
        <h1>这是课程列表页面</h1>
    </div>
</template>
<script>
export default {
    name: "Course",
};
</script>
  建议用这个:https:
import User from '../views/Course.vue'
const routes = [
    {
        path: '/',
        name: 'Home',
        component: Home
    },
    {
        path: '/about',
        name: 'About',
        component: () => import('../views/About.vue')
    },
    {
        path: '/user',
        name: 'User',
        component: User
    },
    {
        path: '/course',
        name: 'Course',
        component: () => import('../views/Course.vue')
    }
]
import { createRouter, createWebHistory,createWebHashHistory } from 'vue-router'
const router = createRouter({
    
    history: createWebHashHistory(process.env.BASE_URL),    
    routes
})
 2、使用路由
<template>
    <div id="nav">
        <router-link to="/">首页</router-link> |
        <router-link to="/about">帮助中心</router-link> |
        <router-link to="/course">课程列表</router-link> |
        <router-link to="/user">个人中心</router-link>
    </div>
    <router-view />
</template>
<style>
    
        color: red;
    }
</style>
<template>
    <div id="nav">
        <router-link to="/">首页</router-link> |
        <router-link to="/about">帮助中心</router-link> |
        <router-link to="/course">课程列表</router-link> |
        <a href="/user">个人中心</a>
    </div>
    
    <router-view />
</template>
 3、路由全局变量
- $route获取当前路由
- $router获取当前路由器,分发器:可以进行页面跳转
<template>
    <div id="nav">
        <router-link to="/">首页</router-link> |
        <router-link to="/about">帮助中心</router-link> |
        <router-link to="/course">课程列表</router-link> |
        
        <a href="/user" :class="{active:$route.path=='/user'}">个人中心</a>
        
        <button @click="$router.push('/course')">跳转</button>
    </div>
    <router-view />
</template>
<style>
.active {
    color: red !important;
}
</style>
<template>
    <div id="nav">
        <router-link to="/">首页</router-link> |
        <router-link to="/about">帮助中心</router-link> |
        <router-link to="/course">课程列表</router-link> |
        <a href="/user" :class="{active:$route.path=='/user'}">个人中心</a>
        <button @click="go_url('/course')">跳转</button>
    </div>
    <router-view />
</template>
<script>
export default {
    methods: {
        go_url(url) {
            
            
            this.$router.push(url);
            
            console.log(this.$route);
        }
    }
};
</script>
 4、嵌套路由(子路由)
<template>
    <div>
        <h1>这是用户 个人信息页面</h1>
    </div>
</template>
<template>
    <div>
        <h1>这是用户 个人配置页面</h1>
    </div>
</template>
<template>
    <div>
        <h1>这是个人中心页面</h1>
        <div class="menu">
            <ul>
                <li>
                    <router-link to="/user/config">个人设置</router-link>
                </li>
                <li>
                    <router-link to="/user/info">个人信息</router-link>
                </li>
            </ul>
        </div>
        <div class="main">
            <router-view />
        </div>
    </div>
</template>
<style scoped>
.menu {
    width: 30%;
    height: 300px;
    float: left;
    background: 
}
.main {
    width: 65%;
    height: 300px;
    float: right;
    background: 
}
a {
    font-weight: bold;
    color: 
}
.router-link-exact-active {
    color: red;
}
</style>
const routes = [
    {
        path: "/",
        name: "Home",
        component: Home
    },
    {
        path: "/about",
        name: "About",
        component: () => import("../views/About.vue")
    },
    {
        path: "/user",
        name: "User",
        component: () => import("../views/User.vue"),
        children: [
            {
                
                path: "config",
                name: "Userconfig",
                component: () => import("../views/Userconfig.vue")
            },
            {
                path: "info",
                name: "Userinfo",
                component: () => import("../views/Userinfo.vue")
            }
        ]
    },
    {
        path: "/course",
        name: "Course",
        component: () => import("../views/Course.vue")
    }
];
 5、动态路由
{
    path: "/course/:id",
    name: "Course",
    component: () => import("../views/Course.vue"),
}
localhost:8080/course/10
localhost:8080/course   
<template>
    <div>
        <h1>这是课程列表页面</h1>
        
        {{ $route.params.id }}
        
        {{ one() }}
    </div>
</template>
<script>
export default {
    methods: {
        one() {
            
            console.log(this.$route.params.id);
        }
    }
};
</script>
<template>
    <div id="nav">
        <router-link to="/">首页</router-link> |
        <router-link to="/about">帮助中心</router-link> |
        <router-link to="/course/200">课程列表</router-link> |
        <router-link to="/user">个人中心</router-link>
    </div>
    <router-view />
</template>
<template>
    <div id="nav">
        <router-link to="/">首页</router-link> |
        <router-link to="/about">帮助中心</router-link> |
        <router-link to="/course/200">课程列表</router-link> |
        <router-link to="/user?uid=100&name=ouyangke">个人中心</router-link>
    </div>
    <router-view />
</template>
<template>
    <div>
        <h1>这是 {{ $route.query.name }} 个人中心页面</h1>
        <div class="menu">
        <ul>
            <li>
                <router-link to="/user/config">个人设置</router-link>
            </li>
            <li>
                <router-link to="/user/info">个人信息</router-link>
            </li>
        </ul>
        </div>
        <div class="main">
            <router-view />
        </div>
    </div>
</template>
<template>
    <div id="nav">
        <router-link to="/">首页</router-link> |
        <router-link to="/about">帮助中心</router-link> |
        <router-link to="/course/200">课程列表</router-link> |
        <router-link to="/user?uid=100&name=ouyangke">个人中心</router-link>
        
        <button @click="go_url()">课程详情</button>
    </div>
    <router-view />
</template>
<script>
export default {
    methods: {
        go_url() {
            
            this.$router.push({
                path: "/user/info",
                query: { uid: 100, name: "欧阳克" }
            });
            
            this.$router.push("/user/info");
        }
    }
};
</script>
 6、重定向、别名
const routes = [
    {
        path: "/",
        name: "Home",
        component: Home,
    },
    {
        path: "/home",
        name: "home",
        redirect: "/",
    }
];
const routes = [
    {
        path: "/",
        name: "Home",
        component: Home,
    },
    {
        path: "/about",
        name: "About",
        component: () => import("../views/About.vue"),
    },
    {
        path: "/home",
        name: "home",
        redirect: {name : "About" }
    }
];
const routes = [
      {
          path: "/",
          name: "Home",
          component: Home,
      },
      {
          path: "/home",
          name: "home",
          redirect: (to) => {
              
              
              return { path: "/user", query: { id: 200, name: "朱天蓬" } };
          }
      },
      {
          path: "/user",
          name: "User",
          component: () => import("../views/User.vue")
      }
];
const routes = [
    {
        path: "/",
        alias: "/home",
        name: "Home",
        component: Home,
    }
];
const routes = [
    {
        path: "/user",
        name: "User",
        component: () => import("../views/User.vue"),
        children: [
            {
                path: "config",
                name: "Userconfig",
                component: () => import("../views/Userconfig.vue"),
            },
            {
                path: "info",
                name: "Userinfo",
                component: () => import("../views/Userinfo.vue"),
                alias: ["/i", "in"]
            }
        ]
    }
];
 7、导航守卫
- 主要用来通过跳转或取消的方式守卫导航
- 有 前置守卫 和 后置钩子
- 植入路由导航位置:全局导航、路由独享、组件级守卫
const router = createRouter({
  history: createWebHashHistory(process.env.BASE_URL),
  routes,
});
router.beforeEach((to, from) => {
    
    console.log(to);
    console.log(from);
    
    document.title = to.meta.title;
});
export default router;
router.afterEach((to, from) => {
    
    console.log(to);
    console.log(from);
});
const routes = [
    {
        path: "/user",
        name: "User",
        component: () => import("../views/User.vue"),
        children: [
            {
                path: "config",
                name: "Userconfig",
                component: () => import("../views/Userconfig.vue"),
            },
            {
                path: "info",
                name: "Userinfo",
                component: () => import("../views/Userinfo.vue"),
                alias: ["/i", "in"],
                beforeEnter: (to, from) => {
                    console.log(to);
                    console.log(from);
                }
            }
        ]
    }
];
export default {
    beforeRouteEnter(to, from) {
        
        
        
        console.log(1);
        console.log(to,from);
    },
    beforeRouteUpdate(to, from) {
        
        
        
        
        console.log(2);
        console.log(to,from);
    },
    beforeRouteLeave(to, from) {
        
        
        console.log(3);
        console.log(to,from);
    }
}
 四、Vuex 状态管理器
 1、介绍
- Vuex是一个专为- Vue.js应用程序开发的状态管理模式 + 库。
- 它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- 例如:用户信息、登录状态、地理位置,这些就可以使用 Vuex状态管理器(超全局数组)
- 相当于响应式的超全局变量,在所有的组件中,都能使用
 2、单独安装
npm install vuex@next --save
yarn add vuex@next --save
 3、使用简单的 Vuex
- 状态(State),驱动应用的数据源
- 视图(View),以声明方式将状态映射到视图
- 操作(Actions),响应在视图上的用户输入导致的状态变化
- "单向数据流" 理念的简单示意。

<template>
    <div>
        <h1>这是课程列表页面</h1>
        <button @click="number--">减-</button>
        {{ number }}
        <button @click="number++">加+</button>
    </div>
</template>
<script>
export default {
    data() {
        return {
            number: 0,
        };
    }
};
</script>
import { createStore } from 'vuex'
export default createStore({
    state: {
        num : 0
    },
    mutations: {
    },
    actions: {
    },
    modules: {
    }
})
<template>
    <div>
        <h1>这是课程列表页面</h1>
        <button @click="number--">减-</button>
        {{ number }}
        <button @click="number++">加+</button>
        
        
        <button @click="$store.state.num--">减-</button>
        {{ $store.state.num }}
        <button @click="$store.state.num++">加+</button>
    </div>
</template>
 4、Mutations 多组件处理
- 解决问题一:多个视图依赖于同一状态(传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力)
- 解决问题二:来自不同视图的行为需要变更同一状态(我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝)

- Vue Components:Vue 组件 
- Actions:操作 - Backend API:后台 api 接口
- Commit:提交
 
- Mutations:改变 
- State:状态 
import { createStore } from "vuex";
export default createStore({
    state: {
        num: 0,
    },
    mutations: {
        add(state){
            
            state.num += 2;
        },
        sub(state){
            state.num -= 2;
        }
    },
    actions: {},
    modules: {},
});
<template>
    <div>
        <h1>这是课程列表页面</h1>
        
        <button @click="sub_c()">减-</button>
        {{ $store.state.num }}
		<button @click="add_c()">加+</button>
    </div>
</template>
<script>
export default {
    methods: {
        
        sub_c() {
          this.$store.commit("sub");
        },
        add_c() {
          this.$store.commit("add");
        }
    }
};
</script>
  
<template>
    <div>
        <h1>这是课程列表页面</h1>
        
        <button @click="sub_c(5)">减-</button>
        {{ $store.state.num }}
		<button @click="add_c(5)">加+</button>
    </div>
</template>
<script>
export default {
    methods: {
        
        sub_c(number) {
          this.$store.commit("sub",number);
        },
        add_c(number) {
          this.$store.commit("add",number);
        }
    }
};
</script>
import { createStore } from "vuex";
export default createStore({
    state: {
        num: 0,
    },
    mutations: {
        add(state,number){
            
            state.num += number;
        },
        sub(state,number){
            state.num -= number;
        }
    },
    actions: {},
    modules: {},
});
 5、Getter 计算属性
<template>
    <div>
      <h1>这是课程列表页面</h1>
      <button @click="sub_c(2)">减-</button>
      {{ jisuan }}
      <button @click="add_c(2)">加+</button>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                number: 10
            };
        },
        methods: {
            sub_c(number) {
                this.number = this.number - number;
            },
            add_c(number) {
                this.number = this.number + number;
            }
        },
        computed: {
            jisuan() {
                return this.number * this.number;
            }
        }
    };
</script>
  
import { createStore } from "vuex";
export default createStore({
    state: {
        num: 10,
    },
    mutations: {},
    getters: {
        jisuan(state) {
            return state.num * state.num * state.num;
        }
    },
    actions: {},
    modules: {},
});
<template>
    <div>
        <h1>这是课程列表页面</h1>
        <button @click="sub_c(2)">减-</button>
        {{ $store.getters.jisuan }}
        <button @click="add_c(2)">加+</button>
    </div>
</template>
<script>
export default {
    methods: {
        sub_c(number) {
            this.$store.commit("sub", number);
        },
        add_c(number) {
            this.$store.commit("add", number);
        }
    },
    computed: {
        jisuan() {
            return this.number * this.number;
        }
    }
};
</script>
 6、Actions 异步处理操作
import { createStore } from "vuex";
export default createStore({
    state: {
      num: 10,
    },
    mutations: {
        jisuan(state) {
            
            return (state.num = 1234);
        }
    },
    getters: {}, 
    actions: {
        
        ac_jisuan(all) {
            console.log(all); 
            
            
            
            all.commit('jisuan');
        }
      
        
        ac_jisuan(all) {
            const {commit, getter, state} = all;
            commit('jisuan');
        }
      
        
        ac_jisuan({commit, getter, state}) {
            setTimeout( ()=>{
                commit('jisuan');
            },3000 );
        }
    },
    modules: {},
});
<template>
    <div>
        <h1>这是课程列表页面</h1>
        {{ $store.state.num }}
        {{ setnum() }}
    </div>
</template>
<script>
export default {
    methods: {
        setnum() {
            this.$store.dispatch("ac_jisuan");
        }
    }
};
</script>
 7、Moduls 模块化
import { createStore } from "vuex";
export default createStore({
    state: {},
    mutations: {},
    getters: {},
    actions: {},
    modules: {
        user:{
            state: {},
            mutations: {},
            getters: {},
            actions: {},
        },
        course:{
            state: {},
            mutations: {},
            getters: {},
            actions: {},
        }
    }
});
 8、文件拆解
import { createStore } from "vuex";
const state = {
    num: 10,
};
const mutations = {
    jisuan(state) {
        return (state.num = 123);
    }
};
export default createStore({
    state,
    mutations,
    getters: {},
    actions: {},
    modules: {
        user: {},
        course: {},
    }
});
import { createStore } from "vuex";
import state from './state.js';
import mutations from './mutations.js';
export default createStore({
    state,
    mutations,
    getters: {},
    actions: {},
    modules: {
        user: {},
        course: {},
    }
});
const state = {
    num: 10,
};
export default state;
const mutations = {
    jisuan(state) {
        return (state.num = 123);
    }
};
export default mutations;