Vue插件学习

Vue插件

Vue-cli

官方网址:https://cli.vuejs.org/zh/guide/

安装vue-cli:npm install -g @vue/cli

查看版本:vue --version

单Vue开发

你可以使用vue server对单个Vue文件进行快速的原型开发,通过安装以下依赖

安装:npm install -g @vue/cli-service-global

Usage: serve [options] [entry]
在开发环境模式下零配置为 .js 或 .vue 文件启动一个服务器
Options:
  -o, --open  打开浏览器
  -c, --copy  将本地 URL 复制到剪切板
  -h, --help  输出用法信息

eg: 运行 vue -serve A.vue;打包 vue build MyComponent.vue

项目开发

创建一个Vue项目:vue create hello-world
通过图形化界面开发:vue ui

Vue Router

官方文档:https://router.vuejs.org/zh/guide/

API:https://router.vuejs.org/zh/api/

路由基本

{
  path: '/', // 路由
  name: 'Home', // name
  component: Home, // 组件地址,亦可component: () => import('../views/Home.vue')
  meta: { title:"首页"}, // 路由元信息
  alias: '/Root', // 别名,就是多个名字而已
  redirect: '/login' // 重定向
  children:[ // 嵌套路由
  	……
  ]
},

通过注入路由器,我们可以在任何组件内通过 this.$router 访问路由器,我们可以进行路由的跳转

  • 通过path跳转:this.$router.push("/about")

  • 通过name跳转:this.$router.push({name:‘About’})

  • 使用this.$router.go(n):正n负n等同于浏览器的前进后退步数,0刷新当前页面

goBack() {
	window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/')
}

也可以通过 this.$route 访问当前路由,包括fullpath,name,mate,params,query,path等信息

路由匹配与传参

匹配所有以http://localhost:8080/header开头路径

当输入:http://localhost:8080/header/1?id=99

​ 则通过this. r o u t e . p a r a m . i d 取 到 的 值 为 1 , 通 过 t h i s . route.param.id取到的值为1,通过this. route.param.id1this.route.query.id取到的值为99

等价于 this.$router.push({path:’/header/1’,query:{id:99}}),path不能和params 同时使用

等价于this.$router.push({name:‘Header’,params:{id:1},query:{id:99}})

等价于**<router-link :to="{ name: ‘user’, params: { userId: 123 }}">User</router-link>**

{
  path: '/',
  name: 'Home',
  component: Home,
  children:[
    {
      path: '/header/:id',
      component: () => import('../views/Header.vue')
    }
  ]
}
其他规则:官方说甚至可以写正则表达式,自上而下单一匹配
	path: '*' // 会匹配所有路径,放在路由底部可以匹配404
	path: '/user-*' // 会匹配以 `/user-` 开头的任意路径

路由嵌套

  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue'),
    redirect: '/about/contentB'//路由重定向,当访问/about会重定向到/about/contentB,也可以使用{ name: 'contentB' }
    children:[
      {
        path: '', // 当访问/about的界面,与redirect冲突不能一起使用
        component: () => import('../views/Bottom.vue')
      },
      {
        path: '/about/contentA', // 也可以contentA,不带‘/’使用相对路径
         name:'contentA',
        component: () => import('../views/ContentA.vue')
      },
      {
        path: '/about/ContentB',
        name:'ContentB',
        component: () => import('../views/ContentB.vue')
      },
    ]
  }

about界面

​ router-link默认使用a标签展示,使用tag可以指定标签

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <router-link to="/about/contentA" tag="div" >A</router-link> | 
    <router-link to="/about/contentB">B</router-link>
    <router-view/> // 这是承载路由展示的地方
  </div>
</template>

编程路由

声明式编程式
<router-link :to="...">router.push(...)
//默认path,变成 /home
ruter.push('/home')
// 对象,变成 /home
router.push({ path: '/home' })
// 命名的路由,变成 /user/123
router.push({ name: '/user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' }})

路由钩子

Vue提供了丰富多样的路由构造,这里我们只讲全局前置守卫和全局后置守卫,其余请查看文档

const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
  // 前置钩子...
})
router.afterEach((to, from) => {
  // 后置钩子...
})

当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中

每个守卫方法接收三个参数:

  • to: Route: 即将要进入的目标 路由对象
  • from: Route: 当前导航正要离开的路由
  • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
    • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
    • next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
    • next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: truename: 'home' 之类的选项以及任何用在 router-linkto proprouter.push 中的选项

确保 next 函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错

Vuex

每一个 Vuex 应用的核心就是 store(仓库)

官方文档:https://vuex.vuejs.org/zh/

API:https://vuex.vuejs.org/zh/api/

Vuex基本

{
    state     // 存储数据 this.$store.state.***
    mutations // 唯一可以修改state数据  this.$store.commit("***")
    actions   // 异步
    getters   // 类似与computed计算属性,通过this.$store.getters.***访问
    modules   // 模块化开发
    namespaced?,
}

getters

Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

getters:{
    countMsg:state=>{  // 通过this.$store.getters.countMsg,注意:这里直接返回结果
        return  state.name + '的count为'+state.count
    }
    // 如何传参
    countMsg2:state=>id=>{  // 通过this.$store.getters.countMsg(99),注意:这里返回函数
        return  state.name + '的count为'+state.count+id
    }
},

mutations

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation

mutation 都是同步事务

mutations: {
    increment (state) { // store.commit('increment')
      // 变更状态
      state.count++
    },
    increment2 (state,payload) { // 可以接收一个载荷(参数) store.commit('increment',2)
      // 变更状态
      state.count+=payload // 可以使用对象作为载荷进行多参数
    },
    increment3 (state,payload) { // this.$store.commit({type:'increment',n:2,age:20})
      // 变更状态
      state.count+=payload.n // 此时载荷就是{type:'increment',n:2,age:20}
    }
  }

Action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
actions: {
    // context包括state,getters ,commit ,rootGetters,rootState
    increment (context) {
        context.commit('increment')
    }increment2 ({commit}) {
        commit('increment') // 使用this.$store.dispatch('increment')调用
    }increment3 (context,payload) { // 类似于mutations的载荷,dispatch('increment',100)
        context.commit('increment')
    },
    increment 4(context,payload) { // 类似于mutations的载荷,dispatch('increment',100)
      setTimeout(() => {
      	context.commit('increment') // 只有
       }, 1000)
    }},

调用actions中的方法默认会返回一个Promise好让我们知道什么时候执行完毕,我们也可以自定义

action 中的方法可以dispatch调用自己的方法

actions: {
	increment (context,paylaod) {
       return new Promise((resolve,reject)=>{
                setTimeout(()=>{
                context.commit('increment')
                resolve()
            },2000)
        })
	}
},
methods:{
    ...mapActions(['increment']),
    incr(){
        this.increment(10).then(res=>{
        	console.log("success")   // 异步回调
        })
    }
}

Module

  • 我们可以将state,mutations等抽成一个单独的js文件,导入导出即可,但这并不是模块化,只是各文件独立了而已,

  • 各个模块的state是独立的,但类似getters确实功能的,即使是不同的模块也不允许重复

  • 如何解决上述问题,可以引入命名空间,比如a和b的setters方法都有getName同名方法,可以添加namespaced: true,那么该方法就变成了a/getName和b/getName

    ​ this. s t o r e . g e t t e r s [ ′ a / g e t N a m e ′ ] 和 t h i s . store.getters['a/getName']和this. store.getters[a/getName]this.store.getters[‘b/getName’]

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

使用系统方法快速操作

mapState返回的是一个包含方法的对象,我们可以使用对象展开...运算符合并到当前对象中

import { mapState,mapGetters,mapMutations } from 'vuex'
computed: {
    getMsg() {
        return this.msg + "Vuex"
    },
    // 等价于 {count(){return this.$store.state.count}},注册一个count计算属性
    ...mapState(['count']),
    ...mapGetters(['countMsg'])
},
// 当我们在页面上使用{{this.$store.state.count}} 和 {{count}} 是等价的
methods:{
    ...mapMutations({add:"increment"}), // 亦可...mapMutations(["increment"]),不使用别名
        incr(){
        // this.$store.commit("increment",2)
        this.add(2)
    }
     ...mapActions(['increment']), // this.increment(10)直接调用即可
}

相关问题

为什么官方建议提交 mutation 的方式,而非直接改变 store.state.count

这样Vuex就能监听到每次修改state数据发生的改变,从而记录每次改变的快照,方便我们调试,如下图:如果我们直接修改的话就捕捉不到变化了

在这里插入图片描述

一条重要的原则就是要记住 mutation 必须是同步函数。为什么?

同上,VueX在执行完mutation 中的函数后会保存一个快照,如果是异步的话,保存的快照就与实际结果不符,使用Action就可以解决这个问题,因为Action中的是在异步请求成功之后才调用mutation 函数的,能确保保存的快照与实际结果一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信息技术王凤龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值