简介

  1. Vue是JS延伸出的一种框架,能在一个组件中写HTML、CSS、JS,它不需要操作DOM,而是通过渲染方式挂载到页面上,效率是不是会高一些呢?

  2. 写代码也很爽,我想给一个功能添加点击事件,只需要给标签绑定@click,再到方法里写绑定事件的函数,这样就好了;对比原生js,你需要到html添加id属性,在回到js获取id,再给id绑定事件写函数,步骤是不是较为繁琐?

  3. 说说不好的点,你需要记住大量指令,经常查阅文档是家常便饭的事

安装过程与创建hello-world项目

  1. 安装Node,选择长期维护版,自带npm

    1
    2
    3
    4
    5
    // 查询node版本
    node -v

    // 查询npm版本
    npm -v
  2. 通过npm指令安装nrm,nrm是管理npm的工具,由于npm服务器在国外,通过npm下载依赖会因为墙问题,导致项目运行不起来,所以需要nrm修改下载源,比如taobao镜像源在国内,下载速度会快一些

    1
    2
    3
    4
    5
    6
    7
    8
    // 安装nrm
    npm install nrm -g

    // 查看所有支持源
    nrm ls

    // 使用taobao镜像源
    nrm use taobao
  3. 安装vue脚手架,用游戏方式来理解,vue官方开局送你一套强力装备,让你能开局直接打Boss

    1
    2
    3
    4
    5
    6
    7
    8
    // 删除旧的vue脚手架,第一次安装vue脚手,请跳过它
    npm uninstall vue-cli -g

    // 删除旧的vue脚手架,第一次安装vue脚手,请跳过它
    yarn global remove vue-cli

    // 安装vue脚手架
    npm install -g @vue/cli
  4. 控制台指令,实在不懂上google

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 返回上一级文件
    cd ..

    // 默认根目录,进入到桌面
    cd Desktop

    // 默认根目录,进入到文稿
    cd Documents

    // 清一下控制台
    clear
  5. 创建vue项目,我习惯在文稿中生成项目,当然你也可以在桌面或其他地方生成;如果你对vue-cli内容感兴趣,可到vue官网查看请点击我跳转

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // 默认根目录,进入到文稿,文稿指mac电脑,win电脑需要指定cdef盘
    Mac: cd Documents
    windows: 进入d盘,在d盘的地址栏输入cmd按下回车,会生成d盘路径的命令窗口;d盘鼠标右键也会生成d盘路径的命令窗口

    // 创建新项目,项目名叫hello-world
    vue create hello-world

    // 学习vue基础,默认vue3版本够用了
    // 手动选择功能则是添加额外插件,例如TypeScript、Router、Vuex...
    Default([Vue 3]babel, eslint)

    // 项目生成后,进入hello-world项目
    cd hello-world

    // 启动你的项目吧 XD
    npm run serve

    // 点击链接查看页面
    Local: http://localhost:8080/
  6. 项目文件说明

    文件名 说明
    public 项目入口文件,存放index.html文件,通常不做任何修改
    src 写代码的地方
    src/assets 存放静态资源,比如背景图、图标等图片资源,再或者公共样式文件
    src/components 存放抽离出来的公共组件
    src/router 路由管理
    src/store 全局状态管理文件
    src/views 存放比较大的视图级组件
    src/App.vue 项目根组件,所有组件通过路由引入到App.vue才能在页面中显示出来
    src/main.js 项目入口文件,webpack打包时会以main.js为起点
    .gitignore 告诉git要忽略项目中的哪些文件或文件夹,主要用在上传项目到git仓库
    babel.config.js 项目范围的配置,支持es6、es7等语法,最新语法能转换成浏览器识别的老式语言
    jsconfig.json 对JS项目目录提供个性化支持:比如路径短写、引入文件自动完成等,提升开发体
    package.json 项目描述文件,能了解到项目版本号、依赖等信息,记录版本范围
    package-lock.json 项目所依赖的第三方包的版本号,记录精确版本号
    README 项目说明文档
    vue.config.js 不怎么了解,好像是用来修改webpack配置
  7. github下载vue项目运行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // cnpm是淘宝团队提供的一个npm国内替代工具,请先安装cnpm
    npm install -g cnpm

    // 进入项目
    cd 项目文件名

    // 安装依赖
    npm install

    // 如果npm安装依赖失败,换成cnpm再试试
    cnpm install

    // 运行项目,要么dev要么serve
    // 不知道用哪个,看项目文档或package.js文件的"scripts"
    npm run dev或serve

vue指令

  1. 常用指令
    指令 说明 代码
    v-bind 绑定属性 <a :href="url"> ... </a>
    v-on 绑定事件 <a @click="doSomething"> ... </a>
    v-if 判断 <p v-if="seen">现在你看到我了</p>
    v-show 判断 <h1 v-show="ok">Hello!</h1>
    v-for 循环 <li v-for="item in items"></li>
    v-model 双向绑定 <input v-model="message" placeholder="edit me" />
    v-once 只渲染一次 <span v-once>这个将不会改变: {{ msg }}</span>
    v-html 按普通HTML插入 <div v-html="'<h1>Hello World</h1>'"></div>

v-if和v-show区别,如果是频繁切换显示,v-show性能影响较小
v-for第一个参数是值,第二个参数是索引;需配合:key使用否则报错

vue方法

  1. methods:方法,用来写方法的地方
  2. computed:计算属性,methods和computed都能用来计算,区别在computed有缓存
  3. watch:侦听器,用来感应数据变化,第一个参数新数据,第二个参数旧数据

class与style绑定

  1. 第一种class写法,通常用来增删、切换class
    <div :class="msg">hello, 幽蓝</div>
  2. 第二种class写法,通常用来显示隐藏样式,active表示class名,isActive设置true表示显示
    <div :class="{active: isActive}">hello,幽蓝</div>
  3. 第一种style绑定,通常绑定到对象,在styleObject上写样式更直观易懂
    <div :style="styleObject"></div>
  4. 第二种style绑定,直接写上去,阅读体验可能不太好
    <div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

补充说明:script写样式推荐用驼峰形式,短横杠形式需要添加引号怪麻烦的

1
2
3
4
5
6
7
8
data() {
return {
styleObj: {
backgroundColor: "purple",
"font-size": "24px"
}
};
}

事件传值与多个处理函数

  1. 事件传递参数,如果是传递event对象需要添加$符号
    <h1 @click="addNumEventTwo(10, $event)">count: {{ num }}</h1>
  2. 事件绑定多个处理函数,用分号隔开,以及使用函数调用
    1
    2
    <h1 :style="{backgroundColor:color}">count: {{ num }}</h1>
    <input type="submit" @click="addNumEvent(10);changeColor('yellow')">

修饰符

  1. 事件修饰符

    事件修饰符 说明 代码
    .stop 阻止事件冒泡 <a @click.stop="doThis"></a>
    .prevent 阻止默认事件 <form @submit.prevent="onSubmit"></form>
    .capture 添加事件捕获模式 <div @click.capture="doThis">...</div>
    .self 自身触发处理函数 <div @click.self="doThat">...</div>
    .once 只触发一次 <a @click.once="doThis"></a>
    .passive 滚动时立即触发 <div @scroll.passive="onScroll">...</div>
  2. 按键修饰符
    .enter:按下回车键触发处理函数<input type="text" @keydown="searchEvent">
    .tab
    .delete
    .esc
    .space
    .up
    .down
    .left
    .right

  3. 系统修饰符
    .ctrl
    .alt
    .shift
    .meta

  4. 鼠标修饰符
    .left
    .right
    .middle

  5. 表单修饰符
    .lazy:失去焦点才会执行v-model.lazy="searchKey"
    .number:转为数字
    .trim:去掉前后空格

父子组件导入导出

  1. template标签导入HelloWorld子组件,单、双标签使用上没区别;两个标签并不会覆盖,而是以复用形式存在

    1
    2
    3
    4
    5
    <template>
    <HelloWorld/>
    <HelloWorld></HelloWorld>
    ...
    </template>
  2. 组件导入说明

    1
    2
    3
    4
    5
    6
    7
    8
    // @等同于/src
    import HelloWorld from "@/components/HelloWorld.vue";

    // .等同于当前路径
    import App from "./App.vue";

    // ..等同于上一级路径
    import HomeView from "../views/HomeView.vue";
  3. 组件导出说明,建议首字母大写,且组件名与文件名是相同的;components是注册组件,比如导入HelloWorld组件

    1
    2
    3
    4
    5
    6
    7
    // 导出名为HomeView的组件,包含注册HelloWorld
    export default {
    name: "HomeView",
    components: {
    HelloWorld
    }
    }

props

  1. 父组件将数据传递给子组件,由props来接收,同时还具有校验数据的功能
    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
    props: {
    // 基础的类型检查 (`null` 和 `undefined` 值会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
    type: String,
    required: true
    },
    // 带有默认值的数字
    propD: {
    type: Number,
    default: 100
    },
    // 带有默认值的对象
    propE: {
    type: Object,
    // 对象或数组的默认值必须从一个工厂函数返回
    default() {
    return { message: 'hello' }
    }
    },
    // 自定义验证函数
    propF: {
    validator(value) {
    // 这个值必须与下列字符串中的其中一个相匹配
    return ['success', 'warning', 'danger'].includes(value)
    }
    },
    // 具有默认值的函数
    propG: {
    type: Function,
    // 与对象或数组的默认值不同,这不是一个工厂函数——这是一个用作默认值的函数
    default() {
    return 'Default function'
    }
    }
    }

生命周期函数

  1. beforeCreate():初始化数据之前
  2. created():初始化数据之后
  3. beforeMount():挂载渲染之前
  4. mounted():挂载渲染之后
  5. beforeUpdate():更新之前
  6. updated():更新之后
  7. beforeUnmount():销毁之前
  8. unmounted():销毁之后

组合式API

  1. 通常我们在data写数据,methods写方法,这种分开式写法,在后期修改某块功能,你需要上下反复查找,最怕不小心修改到别人的代码或其他功能;setup则是集中式写法,它使数据、方法等集中写在一块,像传统JS一样
  2. ref是定义单个数据,相当于data写数据;而定义函数,相当于methods内定义函数,另外说一下,setup不能用this找数据,而是用.value来找
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <template>
    <div @click="changeNum">点我加十{{num}}</div>
    </template>

    <script>
    import {ref} from 'vue';

    export default {
    name: "HelloWorld",
    setup(){
    const num = ref(0);
    function changeNum(){
    num.value += 10;
    }
    return {num, changeNum};
    }
    };
    </script>
  3. 如果说ref()是定义单个数据,那么reactive()就是用来定义多个数据;某一天,我想把名字反转后显示,可以用computed属性来帮助我计算结果,然后以插值形式来展示结果,假如不用computed属性,那么它就不会计算结果,而是获取reverseUsername的值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <template>
    <h1>用户名:{{ user.username }}</h1>
    <h1>年龄:{{ user.age }}</h1>
    <h1>反转:{{ user.reverseUsername }}</h1>
    </template>

    <script>
    import { ref, reactive, computed } from "vue";

    export default {
    name: "HelloWorld",
    setup() {
    const user = reactive({
    username: "幽蓝",
    age: 9,
    interest: "swim",
    reverseUsername: computed(() => {
    return user.username.split("").reverse().join("");
    })
    });
    return { user };
    }
    };
    </script>
  4. toRefs用来解构对象,可以使插值不必打点调用,缺点是同名覆盖;如果想点击后修改对象的值,按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
    <template>
    <h1>用户名:{{ username }}</h1>
    <h1 @click="changeAge">年龄:{{ age }}</h1>
    <h1>反转:{{ reverseUsername }}</h1>
    </template>

    <script>
    import { reactive, computed, toRefs } from "vue";

    export default {
    name: "HelloWorld",
    setup() {
    const user = reactive({
    username: "幽蓝",
    age: 9,
    interest: "swim",
    reverseUsername: computed(() => {
    return user.username.split("").reverse().join("");
    })
    });
    function changeAge() {
    user.age = 20;
    }
    return { ...toRefs(user), changeAge };
    }
    };
    </script>
  5. watch与watchEffect看场景灵活使用吧
    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
    <template>
    <h1 @click="changeAge">年龄:{{ age }}</h1>
    </template>

    <script>
    import { ref, watch, watchEffect } from "vue";

    export default {
    name: "HelloWorld",
    setup() {
    const age = ref(9);
    // 监听指定属性,当属性变化时执行函数,可以获取新值和旧值
    watch(age, (newAge, prevAge) => {
    console.log("watch:" + age.value);
    console.log(newAge , prevAge);
    });
    // 不需要监听指定属性,组件初始化前会自动执行一次,当属性变化时执行函数
    watchEffect(() => {
    console.log("watchEffect:" + age.value);
    });
    function changeAge() {
    age.value++;
    }
    return { age, changeAge };
    }
    };
    </script>
  6. setup参数:第一个参数props,包含父组件传递给子组件所有数据,第二个参数context暴露一些属性方法,包含attrs、slots、emit
    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
    // 父组件
    <HelloWorld :username="username" :age="age"/>

    data(){
    return{
    username: '幽蓝',
    age: 9
    }
    }

    // 子组件
    <h1>username: {{username}}</h1>
    <h1>age: {{age}}</h1>
    <h1>description: {{description}}</h1>

    import { ref } from "vue";

    // props接收父组件传递给子组件所有数据
    props: ["username", "age"],

    // setup的props是响应式数据,不要解构;context是js对象,可以解构
    setup(props, context) {
    const description = ref(props.username + "年龄是" + props.age);
    console.log(context);
    return { description };
    }
  7. provide提供数据,inject接收数据,主要解决props深层嵌套问题
    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
    // 父组件
    import { reactive, provide } from "vue";

    setup() {
    const student = reactive({
    name: "张三",
    classname: "三年1班"
    });
    // 第一个参数是key,可以取任意名字,提供给inject接收
    // 第二个参数是你想传的值,提供给第一个参数
    provide("studentA", student);
    }

    // 子组件
    <h1>学生</h1>
    <h1>name: {{ name }}</h1>
    <h1>classname: {{ classname }}</h1>

    import { inject } from "vue";

    props: ["username", "age"],
    setup() {
    const student = inject('studentA')
    return { ...student };
    }

路由

  1. vue2脚手架自带路由安装,vue3新推出vite构建工具没有路由,开始安装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 用vite构建vue项目,名字取vue3router
    npm init vite@latest vue3router --template vue

    // 进入vue3router项目
    cd vue3router

    // 安装依赖
    npm install

    // 安装router
    npm install vue-router@4
  2. 你的路径是什么,显示相对应组件
    <router-view></router-view>

  3. 路径参数,根据id的不同,显示不同样式,另外:id是一个变量

    1
    2
    3
    4
    5
    // 路径:id写法
    { path: '/users/:id', component: User }

    // 获取id
    $route.params.id
  4. 404页面

    1
    2
    // 设置404 notFound页面
    { path:"/:path(.*)", component:NotFound }
  5. 正则匹配与重复参数

    1
    2
    3
    4
    5
    6
    7
    // :id仅匹配数字
    { path:"/article/:id(\\d+)", component:Article }

    // +是至少会有1个参数
    // *是可有可没有,也可以任意多个
    // ?是有或者没有,不可以重复
    { path:"/films/:id?", component:Films }
  6. 嵌套路由

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 不同用户显示不同内容
    // 这里:id表示 /user/123/xiaoming
    // 去掉:id表示 /user/xiaoming
    {
    path:'/user/:id',
    component:User,
    children:[
    {
    path:'xiaoming',
    component:XiaoMing
    },
    {
    path:"xiaowang",
    component:XiaoWang
    }
    ]
    }
  7. 编程式导航

    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
    // 声明式跳转页面,相当于调用router.push(...)
    <router-link to="/about">点我去about页面</router-link>

    // 编程式跳转页面
    <button @click="goPage"></button>

    methods: {
    goPage(){
    this.$router.push({path: "/about"})
    }
    }

    // 携带参数跳转,首先用name起个名,这样编程式函数以name来查找,跳转后显示news/123
    {
    name: 'news',
    path: '/news/:id',
    components: News
    }

    this.$router.push({name: "news", params: {id:123}})

    // 携带查询参数,比如百度搜索张三,路径会携带?wd=张三
    this.$router.push({path: "/", query: {wd: "张三"}})

    // 替换页面
    this.$router.replace(...)

    // 前进页面
    router.go(1)

    // 后退页面
    router.go(-1)
  8. 命名路由

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // shop路径下组册3个组件,key与value相同,可以使用了ES6简写
    // key可以任意命名,只要router-view的name相同,就会加载名为ShopFooter的组件
    // alias是取别名,不论输入/shop还是/helloshop,但会进入相同页面,支持数组形式多个别名
    {
    path: "/shop",
    alias: ["/helloshop", "/hishop"],
    components: {
    default: ShopMain,
    ShopTop,
    ShopFooter01: ShopFooter
    }
    }

    <router-view name="ShopTop"></router-view>
    <router-view></router-view>
    <router-view name="ShopFooter01"></router-view>
  9. 重定向

    1
    2
    3
    4
    5
    6
    7
    8
    // 用户输入/mall,会帮它修改成/shop进行跳转
    {
    path: "/mall",

    // 下面两个结果是相同的,第一个写死,第二个动态修改
    redirect: "/shop"
    redirect: (to) => { return {path: "/shop"} }
    }
  10. 历史模式

    • Hash模式:内部传递的实际URL之前使用了一个哈希字符(#),由于这部分URL从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理.它在SEO中确实有不好的影响
      history:createWebHashHistory()
    • HTML5模式:当使用这种历史模式时,URL会看起来很”正常”,例如https://example.com/user/id
      history:createWebHistory()
  11. 导航守卫

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 全局前置守卫,就像你去某个页面会验证权限,通过执行next(),不通过执行return false
    // 第三个参数next作为可选
    router.beforeEach((to, from, next) => {
    // ...
    // 返回 false 以取消导航
    return false
    })

    // 组件内的守卫
    // beforeRouteEnter进入页面触发
    // beforeRouteUpdate更新页面触发
    // beforeRouteLeave离开页面触发
    beforeRouteEnter(){
    console.log('路由进入组件')
    },
    beforeRouteUpdate(){
    console.log('路由更新组件')
    },
    beforeRouteLeave(){
    console.log('路由离开组件')
    }

axios

  1. 安装axios
    npm install axios --save

vuex

  1. 用vite构建工具生成vue项目

    1
    2
    3
    4
    5
    6
    // 这是2021年用vite构建工具生成vue项目,项目名vue3vuex02
    npm init vite-app vue3vuex01

    // 注入依赖与运行项目
    npm install
    npm run dev
    • src目录下创建store文件夹,并在里面创建index.js
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      import { reactive } from "vue";

      const store = {
      state: reactive({
      name: '张三',
      age: 9
      }),
      setMessage(value){
      this.state.message = value;
      }
      }

      export default store;
    • App.vue删除必要内容,导入store
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      <template>
      <HelloWorld/>
      </template>

      <script>
      import HelloWorld from './components/HelloWorld.vue'
      import store from './store/index.js'

      export default {
      name: 'App',
      components: {
      HelloWorld
      },
      provide: {
      store
      }
      }
      </script>
    • HelloWorld.vue文件,用inject注入store,然后调用store显示name、age
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <template>
      <h1>{{store.state.name}}</h1>
      <h1>{{store.state.age}}</h1>
      <button @click="store.setName('幽蓝')">点击修改名字</button>
      </template>

      <script>
      export default {
      name: 'HelloWorld',
      inject: ['store']
      }
      </script>
    • 运行项目后,不报错能显示张三、9基本OK了
  2. 安装axios尝试玩一下免费API

    • 安装axios:npm install axios --save
    • store/index.js
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      import { reactive } from "vue";

      const store = {
      state: reactive({
      sayingList: []
      }),
      setSaying(list){
      this.state.sayingList = list
      }
      }

      export default store;
    • App.vue
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      <template>
      <p>名言名句:{{store.state.sayingList}}</p>
      </template>

      <script>
      import store from './store/index.js'
      import axios from 'axios'

      export default {
      name: 'App',
      provide: {
      store
      },
      setup(){
      let api = 'https://api.apiopen.top/api/sentences';
      // 请求api获取数据,调用setSaying方法,将名言名句存到sayingList
      axios.get(api).then((result)=>{
      console.log(result)
      store.setSaying(result.data.result.name)
      })
      return {store}
      }
      }
      </script>
  3. 使用vue-cli生成vuex,获取值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // 给state添加name、age
    export default createStore({
    state: {
    name: '幽蓝',
    age: 9
    },
    getters: {
    },
    mutations: {
    },
    actions: {
    },
    modules: {
    }
    })

    // 组件读取name
    <h1>{{$store.state.name}}</h1>

    // 数据打印age
    mounted(){
    console.log(this.$store.state.age)
    }
  4. 修改值

    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
    // 添加修改方法
    state: {
    name: '幽蓝',
    age: 9
    },
    mutations: {
    setName(state){
    state.name = '幽蓝之家'
    },
    setAge(state, num){
    state.age += num;
    }
    }

    // 添加点击事件
    <h1>{{$store.state.name}}</h1>
    <h1>{{$store.state.age}}</h1>
    <button @click="changeNameEvent">点击修改名字</button>
    <button @click="changeAgeEvent">点击修改年龄</button>

    // 获取修改方法要用commit,可接收多个参数
    // 第一个参数是调用mutations下的函数
    // 第二个参数相当于调用函数的第二个参数,比如传数值3对应num
    methods: {
    changeNameEvent(){
    this.$store.commit('setName');
    },
    changeAgeEvent(){
    this.$store.commit('setAge', 3);
    }
    }
  5. 异步写法
    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
    23
    24
    25
    26
    27
    28
    import { createStore } from 'vuex'
    // 安装axios然后导入axios
    import axios from 'axios'

    export default createStore({
    state: {
    sayingList: []
    },
    getters: {
    },
    mutations: {
    setSayingList(state, arr){
    state.sayingList = arr;
    }
    },
    actions: {
    getSaying(context){
    let api = 'https://api.apiopen.top/api/sentences';
    // 使用commit调用mutations下的setSayingList方法
    // 第二个参数是名言名句
    axios.get(api).then((result)=>{
    context.commit('setSayingList', result.data.result.name)
    })
    }
    },
    modules: {
    }
    })

    HelloWorld.vue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <template>
    <h1>{{$store.state.sayingList}}</h1>
    </template>

    <script>
    export default {
    name: 'HelloWorld',
    mounted(){
    // 使用dispatch调用actions下的getSaying方法
    this.$store.dispatch('getSaying')
    }
    }
    </script>
  6. vuex的5大核心属性

    • state:写数据,类似data
    • getters:写计算属性,类似computed
    • mutations:修改状态方法,同步操作;调用commit
    • actions:写异步,如果修改状态要用到异步,就不要写在上面了;调用dispatch
    • modules:模块可以拥有自己的state、getters…类似setup
  7. 映射状态数据和方法,它是用来简化写法,不必每次写$store.state那么长一串

    • mapState:写在computed里面
    • mapGetters:computed
    • mapMutations:methods
    • mapActions:methods

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
23
24
25
26
27
28
import { createStore } from 'vuex'

export default createStore({
state: {
name: '张三',
age: 9
},
getters: {
takeAge(state){
return state.age * 100;
}
},
mutations: {
setAge(state, num){
state.age += num;
}
},
actions: {
getActions(){
console.log('我是异步')
},
setName(){
this.state.name = '幽蓝';
}
},
modules: {
}
})

先说mapState与mapGetters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<h1>{{name}}</h1>
<h1>{{outlaws}}</h1>
<h1>{{takeAge}}</h1>

import { mapState, mapGetters } from 'vuex'

computed: {
// 数组内填入想解构出来的数据
...mapState(['name', 'age']),

// 如果你担心name重复,可以起别名,像是取outlaws(法外狂徒),别名太适合张三了!
...mapState({
outlaws:(state)=>state.name
}),

// takeAge是返回计算结果
...mapGetters(['takeAge'])
}

mapMutations与mapActions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<h1>{{age}}</h1>
<button @click="setAge(5)">点我修改年龄</button>

import { mapState, mapMutations, mapActions } from 'vuex'

computed: {
...mapState(['age']),
},
methods: {
// 数组内填入想解构出来的方法
...mapMutations(['setAge']),
...mapActions(['getActions'])
},
mounted(){
// 下面两个都能打印出'我是异步'
this.$store.dispatch('getActions');
this.getActions();
}
  1. 模块化modules

未完待续…