Vue2

脚手架文件结构

(treer -d 路径)

image-20230128104810285

关于不同版本的Vue说明

  • vue.js与vue.runtime.xxx.js的区别:

    ​ (1) vue.js是完整版的Vue,包含:核心功能+模板解析器。

    ​ (2) vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。

  • 因为vue.runtime.xxx,js没有模板解析器,所以不能使用templatei配置项,需要使用renderi函数接收到的createElementi函数去指定具体内容。

vue.config.js配置文件

  • 使用vue inspect > output.js 可以查看到Vue脚手架的默认配置
  • 使用vue.config.js 可以对脚手架进行个性化定制,详情 https://cli.vuejs.org/zh/config/

ref属性

1.被用来给元素或子组件注册引用的信息(id的替代

2.应用在html标签上获取的是真实DOM元素,应用在组件标签上获取的是组件实例对象

3.使用方式:

  • 打标识 <h1 ref="title">哈哈</h1> 或者 <School ref="sch"/>
  • 获取 this.$refs.title啥的

配置项props

功能:让组件接收外部传过来的数据

  • 传递数据:<Demo name="xxx"/>

  • 接收数据:

    • 只接收:props: ['name','sex','age']
    • 限制类型:
    1
    2
    3
    4
    5
    props: {
    name: String,
    sex: String,
    age: Number
    }
    • 限制类型、限制必要性、指定默认值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    props :{
    name: {
    type: String,//类型
    required: true//必须
    },
    sex: {
    type: String,
    required: true//默认值
    },
    age: {
    type: Number,
    default: 99
    }
    }
  • 备注:props是只读的。Vue底层会监测你对props的修改,如有修改会发出警告;若业务需求需要改,那么得从props中复制一份到data里,然后去修改data中的那个数据。

mixin-混入

  • 功能:可以吧多个组件供用电额配置提取成一个混入对象

  • 使用方式:

    • 第一步定义混合
    1
    2
    3
    4
    5
    {
    data(){},
    methods:{}
    ……
    }
    • 第二步混入
    1
    2
    3
    4
    局部引入:
    mixins:['xxx','yyy']
    全局引入:
    Vue.mixin(xxx)

插件

  • 功能:用于增强Vue
  • 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据
  • 定义插件:
1
2
3
4
5
6
7
8
9
10
11
对象.install = function(Vue, options) {
//1.添加全局过滤器
Vue.filter(....)
//2.添加全局指令
Vue.directive(....)
//3.配置全局混入
Vue.mixin(....)
//4.添加实例方法
Vue.prototype.$myMethod = function(){....}
Vue.prototype.$myProperty = xxx
}
  • 使用插件:
    Vue.use()

scoped样式

  • 作用:让样式在布局生效,防止冲突
  • 写法:<style scoped></style>

总结TodoList案例

  1. 组件化编码流程
  • 拆分静态组件:组件按照功能点拆分,命名不要与html元素冲突

  • 实现动态组件:考虑好数据的存放位置,数据是组件在用,还是一些组件在用

    • 一个组件在用:放在组件自身即可
    • 一些组件在用:放在他们的共同父组件上(状态提升)
  • 实现交互:从绑定事件开始

  1. props适用于:
  • 父组件→子组件 通信
  • 子组件→父组件 通信(要求父先给自已个函数)
  1. 用v-model时切记:v-model绑定的值不能是props传过来的值,因为props是不可以被修改的!!

  2. props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。

web Storage

  1. 存储内容大小一般5MB左右(不同浏览器不一样)

  2. 浏览器通过 Window.sessionStorage 和 Window.localStorage 属性实现本地存储机制

  3. 相关API

    1. xxxStorage.setItem('key', 'value'):接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,更新其对应的值。
    2. xxxStorage.getItem('key'):接受一个键名作为参数,返回键名对应的值。
    3. xxxStorage.removeItem('key'):接受一个键名作为参数,把该键值从存储中删除。
    4. xxxStorage.clear():清空存储中所有的数据。
  4. 备注

    1. SessionStorage存储的内容会随着浏览器窗口关闭而消失
    2. LocalStorage存储的内容需要手动清除
    3. setItem如果对应键的值获取不到,那么getItem返回值是null
    4. JSON.parse(null)结果依然是null

组件的自定义事件

  1. 一种组件间的通信方式,适用于:子组件=>父组件

  2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)

  3. 绑定自定义事件:

    1. 第一种,在父组件中:<Demo @qvq='test'/>(v-on)

    2. 第二种,在父组件中:

      1
      2
      3
      4
      5
      <Demo ref="demo"/>
      ......
      mounted() {
      this.$refs.demo.$on('qvq',this.test)
      }
    3. 若想让自定义事件只触发一次,用once修饰符,或$once方法

  4. 触发自定义事件:this.$emit('qvq',数据)

  5. 解绑自定义事件:this.$off('qvq')

  6. 组件上也可以绑定原生DOM事件,需要使用native修饰符

  7. 注意:通过this.$refs.xxx.$on('ref值',回调)绑定自定义事件时,回调要么配置在methods中,要么箭头函数怼进去,否则this指向调用它的组件捏。

全局事件总线(GlobalEventBus)

  1. 一种组件间通信的方式,适用于任意组件间通信

  2. 安装全局事件总线:

    1
    2
    3
    4
    5
    6
    7
    new Vue({
    ...
    beforeCreate() {
    Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
    },
    ...
    })
  3. 使用事件总线:

    1. 接受数据:A想接收数据,则A组件给$bus绑定自定义事件,事件的回调留在A组件自身。

      1
      2
      3
      4
      5
      6
      7
      8
      methods() {
      demo(data){....}
      }
      ....
      mounted() {
      this.$bus.$on('xxx',this.demo)
      }
      或者用箭头函数
    2. 提供数据:this.$bus.$on('xxx',this.demo)

  4. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。

消息订阅与发布(pubsub)

  1. 一种组件间通信的方式,适用于任意组件间通信

  2. 使用步骤:

    1. 安装pubsub:npm i pubsub-js

    2. 引入:import pubsub from 'pubsub-js'

    3. 接受数据:A想收数据,则在A中订阅消息,订阅的回调留在A自己这里

      1
      2
      3
      4
      5
      6
      7
      methods() {
      demo(data){....}
      }
      ....
      mounted() {
      this.pid = pubsub.subscribe('xxx', this.demo)//订阅消息
      }
    4. 提供数据:pubsub.publish('xxx',数据)

    5. 最好在beforeDestroy钩子中,用pubsub.unsubscribe(pid)去取消订阅。

nextTick

  1. 语法:this.$nextTick(回调函数)
  2. 作用:在下一次DOM更新结束后执行其指令回调
  3. 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作,要在nextTick所指定的回调函数中执行

Vue封装的过度与动画

  1. 作用:在插入、更新或移除DOM元素时,在核实的时候给元素添加样式类名

  2. 图示:

    image-20230129200244340

  3. 写法

    1. 准备好样式

      • 元素进入的样式

        v-enter:进入的起点

        v-enter-active:进入的过程中——单用active 可animation:搭配@keyframes animationName {}动画

        v-enter-to:进入的终点

      • 元素离开的样式

        v-leave:离开的起点

        v-leave-active:离开的过程中

        v-leave-to:离开的终点

    2. 使用<transition>包裹要过度的元素,并配置name属性

      1
      2
      3
      4
      5
      <transition name="hello">
      <h1 v-show="isShow">
      你好啊!
      </h1>
      </transition>
    3. 备注:若有多个元素需要过度,则需要用:<transition-group>,且每个元素指定<key>

      1
      2
      3
      4
      <transition-group name="qvq" appear>
      <h1 v-show="isShow" key="1">你好:D</h1>
      <h1 v-show="!isShow" key="2">嗨嗨嗨:D</h1>
      </transition-group>

vue脚手架配置代理

方法一

在vue.config.js中添加如下配置:

1
2
3
devServer: {
proxy:"http://localhoost:5000"
}

​ 说明:

 1. 优点:配置简单,请求资源时直接发给前端(8080)即可
 2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理
 3. 工作方式:若按照上述代理配置,当请求了前端不存在的资源时,那么该请求会专访给服务器(优先匹配前端资源)            

方法二

编写vue.config.js配置具体代理规则:

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
module.exports = {
....
//开启代理服务器(方式二)
devServer: {
proxy: {
'/api1': {//请求前缀,匹配所有以'/api1'开头的请求路径
target: 'http://localhost:5000',//代理目标的基本路径
pathRewrite: {'^/api1':''},//路径重写,贼重要!!!
ws: true,//用于支持websocket
changeOrigin: true//用于控制请求头中的host值→请求说谎,说自己是5000的,可爱捏;默认值是false
},
'/api2': {//请求前缀
target: 'http://localhost:5001',
pathRewrite: {'^/api2':''},
ws: true,
changeOrigin: true
},
}
}
}
/*
changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
false:localhoost:8080
默认值为true
*/

说明:

  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理
  2. 缺点:配置略微繁琐,请求资源时必须加前缀

插槽

  1. 作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间的通信方式,适用于 父组件=>子组件

  2. 分类:默认插槽,具名插槽,作用域插槽

  3. 使用方式

    1. 默认插槽

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      父组件中:
      <Category>
      <div>
      html结构1
      </div>
      </Category>
      子组件中:
      <template>
      <div>
      <!--定义插槽-->
      <slot>插槽默认内容...</slot>
      </div>
      </template>
    2. 具名插槽

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      父组件中:
      <Category>
      <template slot="center">
      <div>
      html结构1
      </div>
      </template>
      <template slot="footer">
      <div>
      html结构2
      </div>
      </template>
      </Category>
      子组件中:
      <template>
      <div>
      <!--定义插槽-->
      <slot name="center">插槽默认内容</slot>
      <slot name="footer">插槽默认内容</slot>
      </div>
      </template>
    3. 作用域插槽

      1. 理解:数据在组件的自身,但数据生成的结构需要组件的使用者来决定。(game数据在Category组件中,但是用数据所遍历出来的结构由APP组件决定)…….当然它也可以具名

      2. 具体编码:

        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
        父组件中:
        <Category>
        <template scope="scopeData">
        <ul>
        <li v-for="g in scopeData.games" :key="g">{{g}}</li>
        </ul>
        </template>
        </Category>
        <Category>
        <template slot-scope="scopeData">
        <ol>
        <li v-for="g in scopeData.games" :key="g">{{g}}</li>
        </ol>
        </template>
        </Category>
        <Category>
        <template scope="{games}">
        <h4 v-for="g in games" :key="g">{{g}}</h4>
        </template>
        </Category>
        子组件中:
        <template>
        <div>
        <slot :games="games">默认</slot>
        </div>
        </template>

        <script>
        export default {
        name: 'Category',
        props: ['title'],
        //数据在子组件自身
        data() {
        return {
        games: ['原神', '使命召唤', '赛特斯2']
        }
        }
        }
        </script>

Vuex

vuex

1.概念

在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多一个组件的共享状态进行集中式管理(读/写),也是一种组件间的通信方式,切实用于任意组件间的通信。

2.何时使用

多个组件需要共享数据时。

3.搭建vuex环境

  1. 创建文件:src/store/index.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //该文件用于创建Vuex中最为核心的store

    //引入Vue核心库
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //使用Vuex插件
    Vue.use(Vuex)

    //准备actions,用于响应组件中的动作
    const actions = {}
    //准备mutations,用于操作数据(state)
    const mutations = {}
    //准备state,用于存储数据
    const state = {}

    //创建并暴露store
    export default new Vuex.Store({
    actions,
    mutations,
    state,
    })
  2. main.js中创建vm时传入store配置项

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ....
    //引入store
    import store from './store'
    ....
    //创建vm
    new Vue({
    el:'#app',
    render: h => h(App),
    store
    })

4.基本使用

  1. 初始化数据,配置actions配置mutations操作文件store.js

    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
    //引入Vue核心库
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //引用Vuex
    Vue.use(Vuex)

    const actions = (
    //响应组建的加
    increase(context, value) {
    context.commit('INCREASE', value)
    },
    )

    const mutations = {
    ///执行加
    INCREASE(state,value) {
    state.sum += value
    }
    }

    const state = {
    //初始化数据
    sum: 0
    }

    export default new Vuex.Store({
    actions,
    mutations,
    state,
    })
  2. 组建中读取vuex中的数据:$store.state.sum

  3. 组建中修改vuex中的数据:$store.dispatch('action中的方法名', 数据)$store.commit('mutations中的方法名', 数据)

  4. 备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dipatch,直接commit

5.getter的使用

  1. 概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。

  2. store.js中追加getters配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ....
    const getters = {
    bigSum(state) {
    return state.sum*10//这里假装一波复杂运算
    }
    }
    //创建并暴露
    export default new Vuex.Store({
    ....
    getters
    })
  3. 组件中读取数据:$store.getters.bigSum

6.四个map方法的使用

  1. mapState方法:用于帮助我们映射state中的数据为计算属性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    computed: {
    //借助mapState生成计算属性,从state中读取数据(对象写法)
    ...mapState({//...解构赋值,把对象里的东西展开
    'sum': 'sum',//规范'sum',图个简单↓
    school: 'school',
    kecheng: 'subject',
    }),

    //借助mapState生成计算属性,从state中读取数据(数组写法)
    ...mapState(['sum', 'school', 'subject']),
    }
  2. mapGetters方法:用于帮助我们映射getters中的数据为计算属性。

    1
    2
    3
    4
    5
    6
    7
    computed: {
    //借助mapGetters生成计算属性,从getters中读取数据(对象写法)
    ...mapGetters({bigSum: 'bigeSum'}),

    //借助mapGetters生成计算属性,从getters中读取数据(数组写法)
    ...mapGetters(['bigSum']),
    }
  3. mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数。

    1
    2
    3
    4
    5
    6
    7
    methods: {
    //借助mapActions生成对应的方法,方法中会调用despatch去联系actions(对象写法)——它自动生成的是func(value){},所以说在调用的时候要传参,这样是相较于再从methods里面调方法更简单的
    ...mapActions({increamentOdd: 'increaseOdd', increamentWait: 'increaseWait'}),

    //借助mapActions生成对应的方法,方法中会调用despatch去联系actions(数组写法)——注意这里只能是actions中的名,那么前面调用就得用这种
    ...mapActions(['increamentOdd', 'increamentWait']),
    }
  4. mapMutations方法:用于帮助我们生成与mutations对话的方法,即:$store.commit(xxx)的函数。

    1
    2
    3
    4
    5
    6
    methods: {
    //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)——它自动生成的是func(value){},所以说在调用的时候要传参,这样是相较于再从methods里面调方法更简单的
    ...mapMutations({increament: 'INCREASE', decreament: 'DECREASE'}),
    //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组写法)——注意这里只能是mutations中的名,那么前面调用就得用这种
    ...mapMutations(['INCREASE', 'DECREASE']),
    }
  5. 备注:mapActions与mapMutations使用时,若需要传递参数,需要:在模板中绑定事件时传递好参数,否则参数是事件对象。

7.模块化+命名空间

  1. 目的:让代码更好的维护,让多种数据分类更加明确。

  2. 修改store.js(这里直接份文件了)

    count.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //求和相关的配置
    ...
    const countOptions = {
    namespaced: true,//开启命名空间,不想麻烦一定要写!
    actions: {...},
    mutations: {...},
    state: {...},
    getters: {...}
    }

    export default countOptions

    person.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //人名相关的配置
    ...
    const personOptions = {
    namespaced: true,
    actions: {...},
    mutations: {...},
    state: {...},
    getters: {...}
    }

    export default personOptions

    index.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //该文件用于创建Vuex中最为核心的store

    //引入Vue
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //引入俩模块
    import countOptions from './count'
    import personOptions from './person'

    //使用Vuex插件
    Vue.use(Vuex)

    //浅浅暴露一下
    export default new Vuex.Store({
    modules: {
    countAbout: countOptions,//简写也行
    personAbout: personOptions
    }
    })
  3. 开启命名空间后,组件中读取state数据:

    1
    2
    this.$store.state.personAbout.list//自己读
    ...mapState('countAbout', ['sum', 'school', 'subject'])//借助mapState读
  4. 开启命名空间后,组件中读取state数据:

    1
    2
    this.$store.getters['personAbout/firstPersonName']//自己读
    ...mapState('countAbout', ['bigSum'])//借助mapGetters读
  5. 开启命名空间后,组件中调用dispatch:

    1
    2
    this.$store.dispatch('personAbout/addPersonWang', person)//自己调用
    ...mapActions('countAbout', {increaseOdd: 'jiaOdd', increasementWait: 'jiaWait'})//借助map.Actions调用
  6. 开启命名空间后,组件中调用commit:

    1
    2
    this.$store.commit('personAbout/ADD_PERSON', person)//自己调用
    ...mapMutations('countAbout', {increasement:'JIA', decreasement:'JIAN'})

路由

  1. 理解:一个路由(route)就是一组映射关系,多个路由需要路由器(router)进行管理
  2. 前端路由:key是路径,value是组件

1.基本使用

  1. 安装vue-router,命令npm i vue-router

  2. 应用插件:Vue.use(VueRouter)

  3. 编写router配置项

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //引入VueRouter
    import VueRouter from 'vue-router'
    //引入路由组件
    import About from '../components/About'
    import Home from '../components/Home'
    //创建router实例对象,去管理一组一组的路由规则
    const router = new VueRouter({
    routes: [
    {
    path: './about',
    component: About
    },
    {
    path: './home',
    component: Home
    }
    ]
    })
    //暴露router
    export default router
  4. 实现切换(active-class可配置高亮样式)

    1
    <router-link active-class="active" to="/about">About</router-link>
  5. 指定展示位置

    1
    <router-view></router-view>

2.几个注意点

  1. 路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹

  2. 通过切换,“隐藏”了路由组件,默认是被销毁掉的,需要的时候再去挂载

  3. 每个组件都有自己的$route属性,里面存储自己的路由信息

  4. 整个应用只有一个router,可以通过$router属性获取到

    image-20230202165843249

3.多级路由(嵌套路由)

  1. 配置路由规则,使用children配置项:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    routes: [
    { //一级路由
    path: './home',
    component: Home,
    children: [
    { //这个地方一定不要加斜杠,因为已经帮着加了
    path: 'news',
    component: News
    },
    {
    path: 'message',
    component: Message
    }
    ]
    }
    ]
  2. 跳转(要写完整路径):

    1
    <router-link to:'/home/news'>News</router-link>

4.路由传参

  1. 传递参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!-- 跳转路由并携带query参数,to的字符串写法 -->
    <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">跳转</router-link>&nbsp;&nbsp;

    <!-- 跳转路由并携带query参数,to的对象写法 -->
    <router-link
    :to="{
    path: '/home/message/detail',
    query: {
    id: m.id,
    title: m.title,
    },
    }">跳转
    </router-link>
  2. 接收参数

    1
    2
    $route.query.id
    $route.query.title

5.命名路由

  1. 作用:可以简化路由的跳转

  2. 如何使用

    1. 给路由命名

      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
      routes: [
      //一级路由
      {
      name: 'guanyu',
      path: '/about',
      component: myAbout,

      },
      {
      name: 'jia',
      path: '/home',
      component: myHome,
      children: [
      {
      name: 'xiaoxi',
      path: 'news',
      component: myNews,
      },
      {
      name: 'message'
      path: 'message',
      component: myMessage,
      children: [
      {
      name: 'detail',
      path: 'detail',
      component: myDetail,
      }
      ]
      }
      ]
      },
      ]
    2. 简化跳转

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      简化前,需要写完整路径
      <router-link class="list-group-item" active-class="active" to="/home/message">Message</router-link>

      简化后,直接通过名字跳转
      <router-link class="list-group-item" active-class="active" :to="{name: 'xiaoxi'}">News</router-link>

      简化写法配合传递参数
      <router-link
      :to="{
      name: 'xiangqing',
      query: {
      id: m.id,
      title: m.title,
      },
      }" > 跳转
      </router-link>

6.params参数

  1. 配置路由,声明接收params参数

    1
    2
    3
    4
    5
    {
    name: 'xiangqing',
    path: 'detail/:id/:title',
    component: myDetail,
    }
  2. 传递参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!-- 跳转路由并携带params参数,to的字符串写法 -->
    <router-link :to="`/home/message/detail/${m.id}/${m.title}`">跳转</router-link>

    <!-- 跳转路由并携带params参数,to的对象写法 -->
    <router-link
    :to="{
    name: 'xiangqing',
    //这个地方就必须得用name了
    params: {
    id: m.id,
    title: m.title,
    }">跳转
    </router-link>
  3. 接收参数

    1
    $route.params.id

7.路由props配置

作用:让路由组件更方便收到参数

哈哈超级不喜欢params

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
name:'xiangqing',
path:'detail/:id',
component:Detail,

//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
props:{a:900]
//第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail:组件
/props:true
//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过propst传给Detail组件
props(route){
return {
id:route.query.id,
title:route.query.title
}
}
}

8.<router-link的replace属性

  1. 作用:控制路由调好钻时操作浏览器历史记录的模式

  2. 浏览器的历史记录有两种写入方式

    • push,追加历史记录(默认)
    • replace,替换当前记录
  3. 如何开启replace模式

    <router-link repalce>News</router-link>OR<router-link :repalce="true">News</router-link>

9.编程式路由导航

  1. 作用:不借助<router-link>实现路由跳转,让路由跳转更加灵活(因为会转化成<a>呀)

  2. 具体编码:

    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
    methods: {//按钮啥的
    pushShow(m) {
    this.$router.push({
    name: "xiangqing",
    query: {
    id: m.id,
    title: m.title,
    },
    });
    },
    replaceShow(m) {
    this.$router.replace({
    name: "xiangqing",
    query: {
    id: m.id,
    title: m.title,
    },
    });
    },
    },

    methods: { //前进后退啥的
    back() {
    this.$router.back()
    },
    forward() {
    this.$router.forward()
    },
    go() {
    //向前走n步
    this.$router.go(-2)
    }
    },

10.缓存路由组件

  1. 组件:让不展示的路由组件保持挂载,不被销毁

  2. 具体编码:

    1
    2
    3
    <keep-alive include="组件名">
    <router-view></router-view>
    </keep-alive>

11.三个新的生命周期钩子

  1. 作用:路由组件所独有的两个钩子,用于捕获有路由组件的激活状态

  2. 具体名字:

    1. activated路由组件被激活时触发
    2. deactivated路由组件失活时触发
  3. 还有一个叫nextTick

12.路由守卫

  1. 作用:对路由进行权限控制

  2. 分类:全局守卫、独享守卫、组件内守卫

  3. 全局守卫:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //全局 前置 路由守卫:初始化时/每一次路由切换之前调用
    router.beforeEach((to,from,next) => {
    if(to.meta.isAuth) {//判断是否需要鉴权
    if(localStorage.getItem('school') === 'qust') {
    next()
    }else {
    alert('当前用户无权限查看')
    }
    }else {
    next()
    }
    })

    //全局 后置 路由守卫:初始化时被调用/每次路由切换之后被调用
    router.afterEach((to,from) => {
    document.title = to.meta.title || '哈哈哈'
    })
  4. 独享守卫:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    beforeEnter: (to,from,next) => {
    if(to.meta.isAuth) {//判断是否需要鉴权
    if(localStorage.getItem('school') === 'qust') {
    next()
    }else {
    alert('当前用户无权限查看')
    }
    }else {
    next()
    }
    }
  5. 组件内守卫:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //进入守卫-组件路由守卫,通过路由规则,进入该组件时被调用
    beforeRouteEnter(to,from,next) {
    if(to.meta.idAuth) {
    if(localStorage.getItem('school') === 'qust') {
    next()
    }else {
    alert('该用户无权访问')
    }
    }else{
    next()
    }
    },
    //离开守卫-组件路由守卫,通过路由规则,离开该组件时被调用
    beforeRouteLeave(to,from,next) {
    next()
    }

13.路由器的两种工作模式

  1. 对于一个url来说,什么是hash值?——#及其后面的内容就是hash值
  2. hash值不包括在http请求中,即:hash值不会带给服务器
  3. hash模式:
    1. 地址中永远带着#号,不美观
    2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
    3. 兼容性较好
  4. history模式:
    1. 地址干净,美观
    2. 兼容性和hash模式相比略差
    3. 应用部署上线时需要后端人员支持,解决刷新页面服务器404的问题

Vue UI组件库

移动端常用UI组件库

  1. Vant
  2. Cube UI
  3. Mint UI

PC端常用UI组件库

  1. Element UI
  2. IView UI