• Vue.2x秘籍(下)


    1.Vuex

    1-1.Vuex原理图

    Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成Vue 的官方调试工具 devtools extension (opens new window),提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

    请添加图片描述

    1-2.Vuex环境搭建

    1. 安装vuex(vue2配vuex3)
    npm i vue@3
    
    • 1

    请添加图片描述

    1. src下面创建store文件夹>创建index.js文件
      请添加图片描述
    2. 在index.js中引入vue和vuex,并且应用vuex插件
    // 引入vue
    import Vue from "vue"
    // 引入vuex
    import Vuex from "vuex"
    // 应用vuex
    Vue.use(Vuex)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 在index.js中准备action,mutations和state
    // 配置action
    const action = {}
    // 配置mutations
    const mutations = {}
    // 配置state
    const state = {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 创建store并且暴露store
    
    // 创建store
    const store = new Vuex.Store({
        action,
        mutations,
        state
    })
    // 暴露store
    export default store
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1. 打开main.js,导入store下的index
    import store from './store/index'
    
    • 1
    1. 在vue实例上配置store
    new Vue({
      el:'#app',
      store,
      render: h => h(App)
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1-2-1.计数案例

    Count.vue

    <template>
        <div>
            <h1>当前求和为:{{sum}}</h1>
            <h3>放大十倍后:{{$store.getters.bigSum}}</h3>
            <h4>我在{{school}}学习{{subject}}</h4>
            <select v-model.number="n">
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
            </select>
            <button @click="addOne">+</button>
            <button @click="lessOne">-</button>
            <button @click="oddAddOne">奇数+</button>
            <button @click="waitAddOne">待会儿加</button>
        </div>
    </template>
    <script>
    // 导入mapState
    import {mapState} from 'vuex'
    export default{
        name:'App',
        data(){
            return {
                n:1
            }
        },
        computed:{
            // sum(){
            //     return this.$store.state.sum
            // },
            // school(){
            //    return this.$store.state.school
            // },
            // subject(){
            //    return this.$store.state.subject
            // }
            ...mapState({sum:'sum',school:'school',subject:'subject'})
        },
        methods:{
            addOne(){
                this.$store.dispatch('jia',this.n) 
            },
            lessOne(){
                this.$store.dispatch('jian',this.n) 
            },
            oddAddOne(){
                this.$store.dispatch('oddjia',this.n) 
            },
            waitAddOne(){
                this.$store.dispatch('waitjia',this.n) 
            }
        },
        mounted(){
            // console.log(this);
        }
    }
    </script>
    <style>
        .test1{
            width: 200px;
            height: 200px;
            background: #ccc;
        }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    index.js

    // 引入vue
    import Vue from "vue"
    // 引入vuex
    import Vuex from "vuex"
    // 应用vuex
    Vue.use(Vuex)
    // 配置action
    const actions = {
        jia(context,value){
            console.log('action的jia被调用了');
            context.commit('JIA',value)
        },
        jian(context,value){
            console.log('action的jian被调用了');
            context.commit('JIAN',value)
        },
        oddjia(context,value){
            if(context.state.sum % 2){
                context.commit('JIA',value)
            }
        },
        waitjia(context,value){
            setTimeout(()=>{
                context.commit('JIA',value)
            },500)
        }
    }
    // 配置mutations
    const mutations = {
        JIA(state,value){
            console.log('mutations的JIA被调用了',state,value);
            state.sum += value
        },
        JIAN(state,value){
            console.log('mutations的JIAN被调用了',state,value);
            state.sum -= value
        }
    }
    
    // 配置state
    const state = {
        sum:0,
        school:'尚硅谷',
        subject:'前端'
    }
    // 配置getter
    const getters = {
        bigSum(state){
            return state.sum*10
        }
    }
    // 创建store
    const store = new Vuex.Store({
        actions,
        mutations,
        state,
        getters
    })
    // 暴露store
    export default store
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    1-3.getter的使用

    1. 在Count.vue下,从state下面的getters下面拿到bigSum的返回值,就是放大十倍的效果
    <h3>放大十倍后:{{$store.getters.bigSum}}</h3>
    
    • 1
    1. 在index.js下
    // 配置getter
    const getters = {
        bigSum(state){
            return state.sum*10
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1-4.mapState的使用

    1. sum:'sum’中,后者代表return this.$store.state.sum,前者就代表一个名字

    请添加图片描述

    1-5.mapGetters的使用

    跟mapState一样替换掉了被注释的代码,或者说是用这个方法生成了别替换掉的代码

            // bigSum(){
            //     return this.$store.getters.bigSum
            // }, 
            ...mapGetters({bigSum:'bigSum'})
    
    • 1
    • 2
    • 3
    • 4

    1-6.mapMutations的使用

    点击事件后面的函数要传参数

    <button @click="addOne(n)">+</button>
    <button @click="lessOne(n)">-</button>
    
    • 1
    • 2

    用mapMutations代替this.$store.commit()方法
    commit传递的方法名和参数要在mutations里面操作所以这个方法叫做mapMutations

    methods:{
    // addOne(){
            //     this.$store.commit('JIA',this.n) 
            // },
            // lessOne(){
            //     this.$store.commit('JIAN',this.n) 
            // },
            ...mapMutations({addOne:'JIA',lessOne:'JIAN'}),  //模板里面的点击事件要穿value
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1-7.mapActions的使用

            <button @click="oddAddOne(n)">奇数+</button>
            <button @click="waitAddOne(n)">待会儿加</button>
    
    • 1
    • 2

    mapActions代替this.$store.dispatch()
    dispatch传递的方法名和参数要在actions里面操作所以这个方法叫做mapActions

    methods:{
            // oddAddOne(){
            //     this.$store.dispatch('oddjia',this.n) 
            // },
            // waitAddOne(){
            //     this.$store.dispatch('waitjia',this.n) 
            // }
            ...mapActions({oddAddOne:'oddjia',waitAddOne:'waitjia'})
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1-8.vuex命令空间

    请添加图片描述

    1-9.vuex模块化

    请添加图片描述

    2.路由

    2-1.路由的基本使用步骤

    1. 安装路由
    npm i vue-router@3
    
    • 1
    1. 配置路由

    再src下面创建router文件夹,然后创建一个index.js文件
    index.js

    import VueRouter from 'vue-router'
    import Home from '../pages/Home'
    import About from '../pages/About'
    
    export default new VueRouter({
        routes:[
            {
                path:'/home',
                component:Home
            },
            {
                path:'/about',
                component:About
            },
        ]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    1. 注册路由

    在main.js中引入路由并且注册路由,然后把router>index.js引入并且挂载
    main.js

    import Vue from 'vue'
    import App from './App.vue'
    Vue.config.productionTip = false
    
    import VueRouter from 'vue-router'
    import router from './router'
    Vue.use(VueRouter)
    new Vue({
      el:'#app',
      router:router,
      render: h => h(App)
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    1. 跳转路由
      把要跳转的链接替换成< router-link to=‘路由地址’>
    <router-link class="list" active-class="active" to="/About">About</router-link>
    <router-link class="list" active-class="active" to="/Home">Home</router-link>
    
    • 1
    • 2
    1. 路由视图
      要展示哪个路由对应的组件的地方使用< router-view>< /router-view>
    <router-view></router-view>
    
    • 1

    注意:

    1. 路由组件一般放在pages文件夹中
    2. 通过切换隐藏的路由组件是被销毁了,要使用,又被挂载回来
    3. 每个组件都有自己的$router属性,里面储存着自己的路由信息
    4. 整个应用只有一个router,可以通过$router获取

    3.嵌套路由

    创建相关组件引入,然后在一级路由下写二级路由,注意不用加/
    index.js

    import VueRouter from 'vue-router'
    import Home from '../pages/Home'
    import About from '../pages/About'
    import News from '../pages/News'
    import Message from '../pages/Message'
    export default new VueRouter({
        routes:[
            {
                path:'/home',
                component:Home,
                // 二级路由不用加/
                children:[
                    {
                        path:'News',
                        component:News
                    },
                    {
                        path:'Message',
                        component:Message
                    },
                ]
            },
            // 一级路由
            {
                path:'/about',
                component:About
            },
        ]
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    使用的时候to后面要加完整的路径

    <template>
        <div>
            我是Home组件
            <ul>
                <router-link class="news-item" active-class="active" to="/home/News">News</router-link>
                <router-link class="news-item" active-class="active" to='/home/Message'>Message</router-link>
            </ul>
            <div class='content'>
                <router-view></router-view>
            </div>
        </div>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.路由的query传参

    1. to的字符串和对象写法

    Message.vue

    <template>
        <div>
            <ul>
                <li v-for="m in messageList" :key="m.id">
                    <!-- 第一种写法:to的字符串写法 -->
                    <!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link> -->
                    <!-- 第二种写法:to的对象写法 -->
                    <router-link :to="{
                        path:'/home/message/detail',
                        query:{id:m.id,title:m.title}
                    }">
                    {{m.title}}</router-link>
                </li>
                <hr>
                <router-view></router-view>
            </ul>
        </div>
    </template>
    <script>
    export default{
        name:'Message',
        data(){
            return {
                messageList:[{
                id:'001',title:'001消息'},
                {id:'002',title:'002消息'},
                {id:'003',title:'003消息'}
            ]
            }
                
           
        }
    }
    </script>
    <style>
    li{
        list-style: none;
    }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    Detail.vue
    2. Detail组件接收

    <template>
        <div>
            <li>消息编号是:{{$route.query.id}}</li>
            <li>消息标题是:{{$route.query.title}}</li>
            <hr>
        </div>
    </template>
    <script>
        export default {
            name:'About',
        }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4-1.命名路由

    5.路由的params参数

    第一种to的字符串写法
    请添加图片描述
    第二种to的对象写法
    请添加图片描述

    6.路由的props配置

    1. 第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
      请添加图片描述

    2. 第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
      请添加图片描述

    3. 第三种写法:props值为函数该函数返回的对象中每一组key-value都会通过props传给Detail组件
      请添加图片描述

    7.router-link的push模式跟replace模式

    1. 默认开启push模式,可以实现网页的前进后退
    2. 开启replace模式过后,就不能实现后退了
    3. 直接在router-link标签添加:replace='true’或者直接写一个replace就开启了replace模式

    8.编程式路由导航

    请添加图片描述

    8-1.back、forward、go

    methods:{
            back(){
            this.$router.back()
        },
        forward(){
            this.$router.forward()
        },
        go(){
            // 传入的参数是正数,就往前走几步,
            // 是负数就往后走几步
            this.$router.go(3)
        }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    9.缓存路由组件

    1. 作用:让不展示的路由保持挂载,不被销毁
    2. 如果要缓存多个组件中的一部分就要绑定给一个数组,如下
    <keep-alive :include=["News",'Message']>
         <router-view></router-view>
    </keep-alive>
    
    • 1
    • 2
    • 3
    1. 具体编码:
    <keep-alive include="News">
         <router-view></router-view>
    </keep-alive>
    
    • 1
    • 2
    • 3

    10.两个新的生命周期钩子

    1. 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态
    2. 具体名字:
      activated:路由组件被激活时的触发
      deactivated:路由组件失活时触发
    activated(){
            this.timer = setInterval(()=>{
                this.opacity -= 0.01
                if(this.opacity <= 0){
                    this.opacity = 1
                }
            },10)
            console.log('组件被激活了');
        },
        deactivated(){
            console.log('即将被销毁了');
            clearInterval(this.timer)
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    11.路由守卫

    11-1.前置路由守卫

    1. router.beforeEach((to,from,next)=>{})
    2. 组件之间切换的间隙触发,可以设置一些规则阻止切换,不满足就不允许切换,满足条件就允许切换
    3. to是切换的目标地址
    4. from时切换的初始地址
    5. next是是否允许切换
    6. to.meta.isAuth是设置在路由配置项的元配置项里,标识该组件是否要鉴权
    router.beforeEach((to,from,next)=>{
        console.log('前置路由守卫',to,from);
        if(to.meta.isAuth){//判断是否 需要鉴权
            if(localStorage.getItem('school') === '三河'){
                next()
            }
        }else{next()}
        
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    11-2.后置路由守卫

    1. router.afterEach((to,from)=>{})
    2. 该守卫是组件切换完成后执行的,用来修改切换完成的title
    3. 路由里应该配置每个路由的title,在元配置项里meta:{title:‘zhuye’}
    // 全局后置路由守卫
    router.afterEach((to,from)=>{
        console.log('后置路由守卫',to,from);
    document.title = to.meta.title
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    11-3.独享路由守卫

    1. 某个路由单独享受的路由守卫
    2. beforeEnter:(to,from,next)=>{}
    3. 进入路由组件的时候触发
    4. 如果不符合条件就进入不了
    children:[
                    {
                        name:'xinwen',
                        path:'News',
                        component:News,
                        meta:{isAuth:true,title:'新闻'},
                        // 单独路由守卫
                        beforeEnter:(to,from,next)=>{
                            if(to.meta.isAuth){//判断是否 需要鉴权
                                if(localStorage.getItem('school') === '三河'){
                                    next()
                                }
                            }else{next()}
                        }
                    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    11-4.组件内路由守卫

    1. 在组件里面写的守卫

    11-4-1.beforeRouteEnter

    1. 进入守卫,通过路由规则进入该组件的时候触发
    beforeRouteEnter(to,from,next){
        console.log('beforeRouteEnter组件内路由守卫',to,from);
        if(to.meta.isAuth){//判断是否 需要鉴权
            if(localStorage.getItem('school') === '三河'){
                next()
            }
        }else{next()}
            },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    11-4-2.beforeRouteLeave

    1. 离开守卫,通过路由规则离开该组件的时候触发
    beforeRouteLeave(to,from,next){
                console.log('beforeRouteLeave',to,from);
                next()
            }
    
    • 1
    • 2
    • 3
    • 4

    12.history和hash两种工作模式

    12-1.hash

    1. 对于一个url来说 ----- #及其后面的内容就是hash值
    2. hash值不会包含在http请求中,就是说hash值不会带给服务器
    3. 地址中永远带着#号
    4. 若是以后将地址通过第三方手机app分享,app校验严格的话,
    5. 地址会被标记为不合法
    6. 兼容性较好

    12-2.history

    1. 地址干净,美观
    2. 兼容性和hash模式相比略差
    3. 应用部署上线需要后端人员解决刷新页面中的404问题

    13.Vue UI组件库(Elment UI)

    省略

  • 相关阅读:
    读书会丨如何才能不做情绪的人质?
    1949-2020年全国31省铁路里程数据
    C语言--输入三角形的三边,输出三角形的面积
    《管理学》试卷
    009.查找手机电话簿【散列表】
    Linux安装MySQL8
    HPA控制器
    蓝桥杯印章
    P02 Look And Feel
    MySQL 8.0 在线修改redo log 容量
  • 原文地址:https://blog.csdn.net/LQlove1/article/details/126861434