Vue3 | VueCli、node.js安装、nrm切换镜像源、vue项目结构解读、Router详解、VueX详解

2022-01-20 11:41:38 浏览数 (1)

  • 首先需要创建项目
  • --- 特性配置:
  • package.json文件
  • VueX简述
  • VueX 框架的引入、数据的定义 以及 在组件中的使用
  • 在Home.vue中 使用这个 VueX提供的 全局数据字段:
  • 如何在任一组件中 修改 VueX的 数据
  • VueX的异步操作 同步操作
  • 带参数地 修改VueX数据
  • VueX修改数据 流程设计的理解
  • 安装、使用axios发送ajax请求
  • 把上例的axios请求 封装到 actions中

VueCli部分

首先需要安装nodejs

参考博客:

--- Install Node.js

--- Node.js 安装配置

安装完node会自动配套npm
使用npm install nrm -g用于调整 镜像源,方便后续下载依赖

安装完了注意, 如**C:Users凌川江雪AppDataRoamingnpmnrm -> C:Users凌川江雪AppDataRoamingnpmnode_modulesnrmcli.js**乃是依赖的安装代码路径;

nrm ls可以切换镜像源:

其他命令如图,安装后自然可以看到;

安装后使用时,你可能遇到这个问题:

代码语言:javascript复制
D:OKnodejsOther>nrm ls
internal/validators.js:124
   throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
   ^

[TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type >string. Received undefined
 at validateString (internal/validators.js:124:11)
 at Object.join (path.js:375:7)
 at Object.<anonymous> (C:Users凌川江雪>AppDataRoamingnpmnode_modulesnrmcli.js:17:20)
 at Module._compile (internal/modules/cjs/loader.js:1063:30)
 at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
 at Module.load (internal/modules/cjs/loader.js:928:32)
 at Function.Module._load (internal/modules/cjs/loader.js:769:14)
 at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
 at internal/main/run_main_module.js:17:47
] {
 code: 'ERR_INVALID_ARG_TYPE'
}

解决方案参考——nrm报错 ERR_INVALID_ARG_TYPE 解决方法

这边使用淘宝镜像
npm uninstall vue-cli -g 检查并清除 多余的旧版本
使用npm install -g @vue/cli[@版本号]安装 脚手架

脚手架沉淀了许多最佳实践, 可以借助它快速生成Vue工程,包括 项目目录组织、webpack打包配置等;

使用 脚手架 Vue Cli,从 创建项目 到 运行项目 的过程

命令:**vue create [项目名]**

如**vue create demo-pro**;

运行创建命令之后,工具会询问创建方式:

这里先选第三个,手动选择创建项目需要的特性,

接着,进入选择特性界面:

用空格进行选择,回车进行确定,

这里选择以上三个特性即可,然后回车:

选择3.x的Vue版本,回车,选择使用ESLint的方式:

这里选择第一个,出错的时候才会触发;

回车确定;

这里是选择Lint的校验时机——保存时校验还是commit时校验,

这里先选择第一个,回车确定;

这里是选择要把**config文件**,放一个**单独的文件**里,还是放一个**package.json**里,

这里先选第一个;

最后问,刚刚这一套特性的选择需不需要保存下来方便后续使用,这里不保存;

回车后工程开始创建:

工程创建完成:

进入工程目录,

使用**npm run serve**启动工程:

启动中:

启动成功,开始运行:

使用浏览器访问:

cmd处**ctrl c**两次可以终止运行:

退出之后,把刚刚创建的项目拉进VSCode,使用VSCode启动项目

因为我们无需每次都用**cmd**去启动项目;

把刚刚创建的项目拉进VSCode,准备使用VSCode启动项目:

在VS Code中,使用Terminal栏启动即可,方便快捷!

【刚拉进来可能启动不了,报9009之类的错,

这时候重启一下VSCode就是了;

如果项目中没有**node_modules**,

则需先运行**npm install**安装**node_modules**依赖!!】

运行成功:

初始项目结构解读

注意要在VS code中安装**vetur**这个插件, 使得VS可以提供 语法高亮、提示 等效果:

源代码在src下,main.js是入口

--- import { createApp } from 'vue'

指明**createApp**的来源;

--- import App from './App.vue'

指明**App**实例,来自于当前文件夹下的 App.vue**文件;**

--- createApp(App).mount('#app')**则**

创建实例、挂载实例:

App.vue文件 简读

--- <template>标签对的内容,

其实就等价于之前在组件实例中写的**template:**键模板;

--- <script>和<style>标签对自然就是js和样式的“根据地了”;

--- 其中**<script>**中的 name**指定了根组件实例名,**

component**这里引入了一个**子组件**HelloWorld,**

子组件从**import HelloWorld from './components/HelloWorld.vue'**,

可以看出其定义的地方,即 components**文件夹目录下的**HelloWorld.vue**;**

代码语言:javascript复制
<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
关于HelloWorld.vue文件

看了一下结构,其实也没什么特殊的了,

跟上面**App.vue**的结构大体都是一样的:

代码语言:javascript复制
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    <ul>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/@vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/@vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
单文件组件 的含义

顾名思义,即一个组件就代表了一个组件,

如上的**App.vue**、**HelloWorld.vue**都是单文件组件;

单独一个文件内容,就是完整的 HTML(<template>) CSS(<style>) JS(<script>)**结构了;**

基于工程实现TODOList案例 --- 单组件版App.vue
代码语言:javascript复制
<template>
  <div>
    <input v-model="inputValue" />
    <button class="button" @click="handleAddItem">提交</button>
  </div>
  <ul>
    <li v-for="(item, index) in list" :key="index">
      {{ item }}
    </li>
  </ul>
</template>

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

export default {
  name: "App",
  setup() {
    const inputValue = ref("");
    const list = reactive([]);

    const handleAddItem = () => {
      list.push(inputValue.value);
      inputValue.value = "";
    };
    return { list, inputValue, handleAddItem };
  },
};
</script>

<style>
  .button {
    margin-left: 20px;
  }
</style>

运行效果:

基于工程实现TODOList案例 --- 父子组件版App.vue、ListItem.vue

首先需要创建一个子组件单文件:

其代码:

代码语言:javascript复制
<template>
  <div class="hello">
    <li>{{ msg }}</li>
  </div>
</template>

<script>
export default {
  name: 'ListItem',
  props: {
    msg: String
  }
}
</script>

<style>
</style>

App.vue:

与上例 主要区别就是在<script>中引入,

在<template>中修改:

代码语言:javascript复制
<template>
  <div>
    <input v-model="inputValue" />
    <button class="button" @click="handleAddItem">提交</button>
  </div>
  <ul>
    <list-item v-for="(item, index) in list" :key="index" :msg="item" />
  </ul>
</template>

<script>
import { reactive, ref } from "vue";
import ListItem from "./components/ListItem.vue";

export default {
  name: "App",
  components: { ListItemListItem },
  setup() {
    const inputValue = ref("");
    const list = reactive([]);

    const handleAddItem = () => {
      list.push(inputValue.value);
      inputValue.value = "";
    };
    return { list, inputValue, handleAddItem };
  },
};
</script>

<style>
.button {
  margin-left: 20px;
}
</style>

运行效果同上例;

Vue-Router部分

创建带router的项目

选择特性的时候要选上Router:

这里暂时不选history mode,会使用 hash Router,

适配会简单些:

其他配置:

在代码中使用Router

创建好工程项目后,同样把它拉到VScode里面,

可以看到这里的目录,

可以看到main.js中,多了一个**.use(router)**

Router的作用 及 简述

作用:根据url的不同,展示不同的内容;

如下,运行项目,默认url**http://localhost:8080/#/**,展示主页(Home页):

编写url——**http://localhost:8080/#/about**访问,则展示about页:

首先看一下App.vue根组件怎么写
代码语言:javascript复制
<template>
  <div id="nav">
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link>
  </div>
  <router-view/>
</template>

<style>
</style>

--- router-link**是定义 跳转路由的标签,** to属性**可以配置**url尾部参数**【前部 自动补上 网站根地址】,** 标签内容**配置显示的内容;** 点击**标签内容**,即跳转到,**to**补全url 指向的页面!! 如果有写**<router-view/>**,则不跳转,乃显示在**<router-view/>**中; --- <router-view/>**则是** 根据**router-link**以及**网页url**组成的**url路由**, 在**router/index.js** 文件中的 路由对象**(如下一节的**routes**)里,** 找到对应的**组件路由属性**,拿到对应的**组件文件路径**, 在**view**目录中找到 对应的组件 去显示!

解析一下这个多出来的 router/index.js 文件
代码语言:javascript复制
import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

--- createRouter是vue-router的一个函数,用于创建和初始化Router; 同时这里第二个参数 使用了路由参数**routes**; --- 注意 定义routes参数这里, path**定义 路径、**name**定义 名称、**component**进行 组件的引入;** routers**里的组件既称之为**component**,** 也称之为**view**,子组件的单文件都放在**view**文件夹下;

view目录下的文件

-- 可以看到Home.vue这里其实引用一个HelloWorld子组件:

例程,拓展一个Router页面
  • 首先App.vue添加 router-link:
  • views目录下创建 单文件组件:
  • router/index.js 的Object Array中,定义一个对应的路由元素:

完事,运行,点击Heheda,效果:

补充:Router路由懒加载语法糖 简述 与例程实战

如上例程中,**router/index.js** 中的这个写法,

component 这里使用了 import**的方式 引入了组件,**

这是一种**懒加载、异步加载**(如模板注释:**lazy-loaded**)的方式,

即当网页跳到这一页的时候,才会加载对应的资源文件,否则不加载;

而如 Home页的加载方式,

则是普通的常规加载:

所以, --- 异步加载的方式: 首页打开会快点,节省不必要的资源占用, 但是在切换到**懒加载**页面时,则需要花费一定的额外加载时间; --- 同步加载的默认方式: 则可能 一开始打开首页等页面 会慢一些, 但是会把其他页面一开始就加载好,切换的时候会快一点; --- 具体选择哪种方式,就根据业务需要进行选择;

代码语言:javascript复制
...
const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/heheda',
    name: 'Heheda',
    component:  () => import(/* webpackChunkName: "about" */ '../views/Heheda.vue')
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]
...

试验,运行上个例程,之后打开浏览器测试工具:

跳到Home页,刷新页面,然后清理记录,再点击about页,

可以看到这个时候页面才加载about的资源:

VueX部分

首先需要创建项目

--- 特性配置:

老规矩,创建项目之后把项目拉进VScode启动与开发;

package.json文件
VueX简述

VueX 其实就是一个**数据管理框架**, 它创建了一个全局的、唯一的**数据仓库**; 当一个前端项目特别大的时候, 或者类似 几十个页面 同步共享 某部分数据 的场景, 我们不可能还是用props、provide、inject等语法去传递数据, 这个时候我们需要一个更加完善的数据管理方案;

VueX 框架的引入、数据的定义 以及 在组件中的使用

main.js中use它:

store /index.js创建仓库,

这里在state中准备了一个测试数据:

在Home.vue中 使用这个 VueX提供的 全局数据字段:

这里借助**computed**属性,

通过**this.$store.state.myTestString**获取到 数据字段:

代码语言:javascript复制
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <h1>{{myTestString}}</h1>
  </div>
</template>

<script>
// @ is an alias to /src

export default {
  name: 'Home',
  computed: {
    myTestString() {
      return this.$store.state.myTestString;
    }
  }
}
</script>

运行效果:

在About.vue中也试一下:

代码语言:javascript复制
<template>
  <div class="about">
    <h1>This is an about page</h1>
    <h1>{{myTestString}}</h1>
  </div>
</template>


<script>
export default {
  name: 'About',
  computed: {
    myTestString() {
      return this.$store.state.myTestString;
    }
  }
}
</script>

运行效果:

如何在任一组件中 修改 VueX的 数据

流程总结: 要修改数据的组件, 发起**dispatch(事件)** ---> store/index.js**中**actions**里** 对**dispatch**的事件 进行 监听 和回调处理, 然后发起一个**commit(事件)** ---> store/index.js**中**mutations**里** 对**commit**的事件 进行 监听 和回调处理, 处理逻辑中,完成对数据的修改;

--- 首先,需要在事件触发的函数里,

派发一个action,

改变数据 这里在About.vue中,

我们派**testChange**【这玩意是可以自定义的】的action,

this.$store.dispatch("testChange");

代码语言:javascript复制
<template>
  <div class="about">
    <h1 @click="handleClick">This is an about page</h1>
    <h1>{{ myTestString }}</h1>
  </div>
</template>


<script>
export default {
  name: "About",
  computed: {
    myTestString() {
      return this.$store.state.myTestString;
    },
  },
  methods: {
    handleClick() {
      this.$store.dispatch("testChange");
    },
  },
};
</script>

--- 接着在**store/index.js**中**actions**里,即这个VueX全局数据仓库中,

做**dispatch**的 监听回调处理,

store/index.js**中的**actions**会响应任意组件的**dispatch**;**

--- 再接着,

在**actions**里 对应的回调方法中,使用**commit('自定义事件名')**,

触发一个**mutations**,

store/index.js**中的**mutations**,**

会响应**actions**的**commit**;

--- 最后,

在**store/index.js**中的**mutations**里,

做**actions**的**commit**的监听回调,

在对应**commit**的 事件回调函数中(如**testChange()**),

修改数据(如**this.state.myTestString = "lueluelue";**)即可;

代码语言:javascript复制
import { createStore } from 'vuex'

export default createStore({
  state: {
    myTestString: "heheda",
  },
  mutations: {
    testChange() {
      console.log("mutations --- testChange");
      this.state.myTestString = "lueluelue";
    }
  },
  actions: {
    testChange() {
      console.log("actions --- testChange");
      this.commit('testChange');
    }
  },
  modules: {
  }
})

运行:

点击文本,

可见完成了数据的修改,效果:

点击到Home页,

可见这边的数据也跟着改变了,

体现了VueX的**全局特性**:

以上是比较完整的步骤,而如果修改数据的时候不涉及异步操作,则可以简化上述流程

即省略**组件的dispatch**和**store的actions**的步骤,

组件直接就commit,

然后回调到store的mutations,

直接修改数据:

运行效果基本同上例;

VueX的异步操作 同步操作

VueX建议在**mutations**中只进行立即执行的**同步操作**, 如果要进行**异步操作**,必须要在**actions**中进行, 也就是要采用上上节的步骤 进行VueX数据的修改;

例程,首先需要组件发起dispatch:

接着在actions中进行异步操作:

代码语言:javascript复制
import { createStore } from 'vuex'

export default createStore({
  state: {
    myTestString: "heheda",
  },
  mutations: {
    testChange() {
      console.log("mutations --- testChange");
      this.state.myTestString = "lueluelue";
    }
  },
  actions: {
    testChange() {
      setTimeout(() => {
        console.log("actions --- testChange");
        this.commit('testChange');
      }, 2000);
    }
  },
  modules: {
  }
})

运行,点击文本,两秒后文本(即背后的数据)自动改变:

带参数地 修改VueX数据

--- About.vue

dispatch时,

传递的 第一个参数为**action**,

第二个参数为**意图改动的目标数据参数**:

代码语言:javascript复制
<template>
  <div class="about">
    <h1 @click="handleClick">This is an about page</h1>
    <h1>{{ myTestString }}</h1>
  </div>
</template>


<script>
export default {
  name: "About",
  computed: {
    myTestString() {
      return this.$store.state.myTestString;
    },
  },
  methods: {
    handleClick() {
      this.$store.dispatch("testChange", "xixixihehehe");
    },
  },
};
</script>

--- store/index.js:

--- actions中的 事件回调函数,自动生成两个形参, 第一个为store实例, 第二个为 组件中dispatch 传递过来的 数据参数; --- mutations的 事件回调函数,也自动生成两个形参, 第一个为 state实例, 它的值是 以Proxy的结构存储着 回调当前**事件处理函数**的时刻 store 数据仓库的 状态【即 state属性】, 第二个为 actions中commit 【同步操作时,也可以是组件中的commit】 传递过来的 数据参数;

代码语言:javascript复制
import { createStore } from 'vuex'

export default createStore({
  state: {
    myTestString: "heheda",
  },
  mutations: {
    testChange(state, str) {
      console.log("mutations --- testChange");
      console.log("mutations --- testChange --- state", state);
      state.myTestString = str;
    }
  },
  actions: {
    testChange(store, str) {
      setTimeout(() => {
        console.log("actions --- testChange");
        console.log("actions --- testChange --- store", store);
        // this.commit('testChange');
        store.commit('testChange', str);
      }, 2000);
    }
  },
  modules: {
  }
})

运行,点击文本,

两秒后字体改变,效果:

VueX修改数据 流程设计的理解

这样设计, --- 可以把同步操作的逻辑封装在**mutations**中处理, 把异步操作的逻辑封装在**actions**中处理; --- 又可以通过对**触发事件名**的**自定义**, 对特定的业务处理逻辑、修改数据代码块 做标记; --- 如此使得项目可维护性高、可拓展性高、可读性高, 出问题时容易排查,拓展代码时也比较方便;

在setup【compositionAPI】中使用VueX

--- Home.vue:

代码语言:javascript复制
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
    <h1>{{ myTestString }}</h1>
  </div>
</template>

<script>
import { useStore } from "vuex";
export default {
  name: "Home",
  setup() {
    const store = useStore();
    const myTestString = store.state.myTestString;
    return { myTestString };
  },
};
</script>

运行效果:

使用toRefs整理上述代码
代码语言:javascript复制
<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
    <h1>{{ myTestString }}</h1>
  </div>
</template>

<script>
import { toRefs } from "vue";
import { useStore } from "vuex";
export default {
  name: "Home",
  setup() {
    const store = useStore();
    const { myTestString } = toRefs(store.state);
    return { myTestString };
  },
};
</script>

运行效果同上例;

在About页中 试试 setup中修改数据

--- About.vue

代码语言:javascript复制
<template>
  <div class="about">
    <h1 @click="handleClick">This is an about page</h1>
    <h1>{{ myTestString }}</h1>
  </div>
</template>


<script>
import { toRefs } from "vue";
import { useStore } from "vuex";
export default {
  name: "About",
  setup() {
    const store = useStore();
    const { myTestString } = toRefs(store.state);
    const handleClick = () => {
      store.commit("testChange", "xixixihehehe");
    };
    return { myTestString, handleClick };
  }
};
</script>

--- store/index.js:

代码语言:javascript复制
import { createStore } from 'vuex'

export default createStore({
  state: {
    myTestString: "heheda",
  },
  mutations: {
    testChange(state, str) {
      console.log("mutations --- testChange");
      console.log("mutations --- testChange --- state", state);
      state.myTestString = str;
    }
  },
  modules: {
  }
})

运行,到About页,

点击文本:

Home页数据同步:

试一下 setup异步处理

--- About.vue

代码语言:javascript复制
<template>
  <div class="about">
    <h1 @click="handleClick">This is an about page</h1>
    <h1>{{ myTestString }}</h1>
  </div>
</template>


<script>
import { toRefs } from "vue";
import { useStore } from "vuex";
export default {
  name: "About",
  setup() {
    const store = useStore();
    const { myTestString } = toRefs(store.state);
    const handleClick = () => {
      store.dispatch("testChange", "xixixihehehe");
    };
    return { myTestString, handleClick };
  }
};
</script>

--- store/index.js

代码语言:javascript复制
import { createStore } from 'vuex'

export default createStore({
  state: {
    myTestString: "heheda",
  },
  mutations: {
    testChange(state, str) {
      console.log("mutations --- testChange");
      console.log("mutations --- testChange --- state", state);
      state.myTestString = str;
    }
  },
  actions: {
    testChange(store, str) {
      setTimeout(() => {
        console.log("actions --- testChange");
        console.log("actions --- testChange --- store", store);
        // this.commit('testChange');
        store.commit('testChange', str);
      }, 2000);
    }
  },
  modules: {
  }
})
使用axios发送ajax请求
  • 首先需要安装axios:

找到一个fastmock接口,

https://www.fastmock.site/mock/ae8e9031947a302fed5f92425995aa19/jd/api/user/register

其内容:

在About.vue中请求数据并显示:

--- 主要注意要**import**;

--- get方法的参数为url,访问数据接口;

--- then接收 接口回复;

代码语言:javascript复制
<template>
  <div class="about">
    <h1 @click="handleClick">This is an about page</h1>
    <h1>{{ myTestString }}</h1>
  </div>
</template>


<script>
import { toRefs } from "vue";
import { useStore } from "vuex";
import axios from "axios";
export default {
  name: "About",
  setup() {
    axios
        .get(
          "https://www.fastmock.site/mock/ae8e9031947a302fed5f92425995aa19/jd/api/user/register"
        )
        .then((response) => {
          console.log("response", response);
          const msg = response.data.desc;
          console.log("response.data.desc", msg);
        });

    const store = useStore();
    const { myTestString } = toRefs(store.state);
    const handleClick = () => {
      store.dispatch("testChange", "xixixihehehe");
    };
    return { myTestString, handleClick };
  },
};
</script>

运行效果:

把上例的axios请求 封装到 actions中

--- About.vue

代码语言:javascript复制
<template>
  <div class="about">
    <h1 @click="handleClick">This is an about page</h1>
    <h1>{{ myTestString }}</h1>
  </div>
</template>


<script>
import { toRefs } from "vue";
import { useStore } from "vuex";
export default {
  name: "About",
  setup() {
    const store = useStore();
    const { myTestString } = toRefs(store.state);
    const handleClick = () => {
      store.dispatch("testChange", "xixixihehehe");
    };
    return { myTestString, handleClick };
  },
};
</script>

--- store/index.js

代码语言:javascript复制
import { createStore } from 'vuex'
import axios from "axios";

export default createStore({
  state: {
    myTestString: "heheda",
  },
  mutations: {
    testChange(state, str) {
      console.log("mutations --- testChange");
      console.log("mutations --- testChange --- state", state);
      state.myTestString = str;
    }
  },
  actions: {
    testChange(store) {
      axios
        .get(
          "https://www.fastmock.site/mock/ae8e9031947a302fed5f92425995aa19/jd/api/user/register"
        )
        .then((response) => {
          console.log("response", response);
          const msg = response.data.desc;
          console.log("response.data.desc", msg);
          store.commit('testChange', msg);
        });
    }
  },
  modules: {
  }
})

运行:

点击文本,两秒后:

0 人点赞