参照官网整理总结vuex语法。

计划日期:
Vuex基础部分:2022年2月20日——2022年2月28日
Vuex源码相关实践:待定
Vuex拓展:待定
写完后,会发到仓库地址:待定

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式

  • state,驱动应用的数据源;
  • view,以声明方式将 state 映射到视图;
  • actions,响应在 view 上的用户输入导致的状态变化。
vuex-16454369395901.png

store——包含以上概念的容器

view——以声明方式将 state 映射到视图

state 状态、数据

getters:当state的数据变更时,getters的值也发生变化(相当于vuex中state的计算属性)

mutations 更改状态的函数

actions 异步操作

Modules 模块。为了将store的状态进行分割,每个模块都有属于自己的state、mutation、action、getter

Vuex V3.0

基础代码:

import Vue from 'vue'
import Vuex from 'vuex'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
Vue.use(Vuex)//使用vuex
// 将 store 实例作为插件安装
const store = new Vuex.Store({/*状态、数据 存储 */state: {count: 0},/* 行为,更改状态的函数  */mutations: {increment(state) {state.count++}}
})
new Vue({router,store,// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件render: function (h) {return h(App)}
}).$mount('#app')

state——状态、数据

状态、数据 **单一状态树 **作为一个“唯一数据源 (SSOT (opens new window))”而存在。

操作:
读取state中数据
this.$store.state.count
变更state中的数据
//使用commit调用mutations内的increment方法
this.$store.commit("increment")
mapState辅助函数
计算属性显示数据

作用:当获取多个状态减少申明多个状态的重复和冗余,使用辅助函数来生成计算属性。

main.js

import Vue from 'vue'
import Vuex from 'vuex'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
// 将 store 实例作为插件安装
Vue.use(Vuex)
const store = new Vuex.Store({/*状态、数据 存储 */state: {count: 0,c: 1,},/* 行为,更改状态的函数  */mutations: {increment(state) {state.count++}}
})
new Vue({router,store,render: function (h) {return h(App)}
}).$mount('#app')

home.vue

<template><div>首页<p>{{ count }}</p><p>{{ countPlusLocalState }}</p><p>{{ countAlias }}</p></div>
</template>
<script>
import { mapState } from "vuex";
export default {//import引入的组件需要注入到对象中才能使用components: {},data() {//这里存放数据return {localCount: 123,};},//监听属性 类似于data概念computed: mapState({// 箭头函数可使代码更简练count: (state) => state.count,// 传字符串参数 'count' 等同于 `state => state.count`countAlias: "count",// 为了能够使用 `this` 获取局部状态,必须使用常规函数countPlusLocalState(state) {return state.count + this.localCount;},}),// computed: mapState(["count"]),//监控data中的数据变化watch: {},//方法集合methods: {increment() {/* 获取state内的数据值 */this.$store.commit("increment");console.log(this.$store.state.count);},},
};
</script>
image-20220220161503081.png
简写形式

当计算属性名称和state的数据名称相同可以简写成数组形式

computed: mapState(["count"]),

页面内调用:

{{count}}
image-20220220161704874.png
展开mapstate对象方便调用
<template><div>首页<p>{{ count }}</p><p>{{ c }}</p><!-- <p>{{ countPlusLocalState }}</p> --><!-- <p>{{ countAlias }}</p> --></div>
</template>
<script>
computed: {//写法1...mapState(["count", "c"]),//写法2...mapState({count: "count",c: "c",}),
},
</script>

Getter——store内的计算属性

当state内的数据变化后,getter内的数据也随之变化

属性访问

Getter(state,getters)

state——(必填)返回state状态数据内的值

示例:`state.count++`

getters——(可选)调用getters内的方法

示例:`getters.todolist.length`

完整示例:

vuex书写:

const store = new Vuex.Store({/*状态、数据 存储 */state: {/* state练习 */count: 0,c: 1,/* getters练习 */todos: [{ id: 1, text: '...', done: true },{ id: 2, text: '...', done: false }]},/* 行为,更改状态的函数  */mutations: {/* state练习 */increment(state) {state.count++}},getters: {doneTodos: (state) => {// 返回todo.done为true的列表项return state.todos.filter(todo => todo.done)},// 返回完整的列表todolist: (state) => {return state.todos;},// 接受其他getters作为第2个参数doneTodosCount(state, getters) {console.log(getters.todolist)return getters.todolist.length}}
})

vue页面显示数据

<template><div>首页<p>为true的列表:{{ doneTodos }}</p><p>完整的列表项:{{ todolist }}</p><p>完整的列表长度:{{ doneTodosCount }}</p></div>
</template>
<script>export default {computed: {// 返回todos列表doneTodos() {return this.$store.getters.doneTodos;},todolist() {return this.$store.getters.todolist;},// 返回列表长度doneTodosCount() {return this.$store.getters.doneTodosCount;},},}
</script>

结果显示:

image-20220221171937666.png
方法访问

通过给getters方法传递参数,从而实现返回想要的数据内容

vuex

  /*状态、数据 存储 */
state: {//.../* getters练习 */todos: [{ id: 1, text: '...', done: true },{ id: 2, text: '...', done: false }]
},  
getters: {//...//给getters方法传递参数getTodoById: (state) => (id) => {return state.todos.find(todo => todo.id === id)}
}

调用

<template><div><h3>通过方法访问</h3><p>返回指定id的列表项:{{ gettodo(2) }}</p></div>
</template>
<script>//需要写在methods方法内,前面写在computed计算属性内methods: {/* 返回指定id的列表项 */gettodo(id) {return this.$store.getters.getTodoById(id);},//...},
</script>

输出:

image-20220221172922503.png
mapGetters辅助函数

注:只能映射到计算属性中,无法映射到方法中

写法与mapState类似

原本写法:

  computed: {// 返回todos列表doneTodos() {return this.$store.getters.doneTodos;},todolist() {return this.$store.getters.todolist;},// 返回列表长度doneTodosCount() {return this.$store.getters.doneTodosCount;},},

使用mapGetter写法:

写法1

import { mapGetter } from "vuex";computed: {...mapGetters(["doneTodos", "todolist", "doneTodosCount"]),},

写法2

import { mapGetters } from "vuex";computed: {...mapGetters({doneTodos: "doneTodos",todolist: "todolist",doneTodosCount: "doneTodosCount",}),},

输出结果:

image-20220221173855234.png

mutations——更改state状态的函数

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

基本格式:

type(state,mutation)

  • type:(事件类型)——命名在mutations中的函数名称

    示例:

      increment (state, n) {state.count += n}
    

    increment 为事件类型

  • state:【必选】(数据)——store中存储的数据

  • mutation:【可选】(荷载)——调用事件类型时传递给事件的参数。

    示例:store.commit('increment', 10) 最后的10为参数事件类型为increment

完整示例:

store

const store = new Vuex.Store({/*状态、数据 存储 */state: {//.../* mutation练习 */mut: 1},/* 行为,更改状态的函数  */mutations: {//.../* mutation练习 */incrementdata(state, n) {state.mut += n.sum}},getters: {}
})

mutation.vue

<template><div class="">mutation获取值:{{ mudata }}</div>
</template>
<script>
export default {components: {},data() {return {mudata: "",};},methods: {runmutation() {this.$store.commit({type: "incrementdata",sum: 1,});console.log(this.$store.state);this.mudata = this.$store.state.mut;},},mounted() {this.runmutation();},
};
</script>

结果:


image-20220222225315304.png

Mutation 必须是同步函数,异步的话导致事件无法追踪(原因在于mutation直接变更的是State(状态)内的数据)

mapMutations 辅助函数

mapGettersmapState类似

import { mapMutations } from 'vuex'export default {// ...methods: {...mapMutations(['increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`// `mapMutations` 也支持载荷:'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`]),...mapMutations({add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`})}
}
使用常量替代 Mutation 事件类型
const SOME_MUTATION = 'SOME_MUTATION'
import { createStore } from 'vuex'const store = createStore({state: { ... },mutations: {// 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名[SOME_MUTATION] (state) {// 修改 state}}
})

示例:

const CHANGE_NAME = 'CHANGE_NAME'
mutations: {[CHANGE_NAME](state, data) {state.name = data}
},

Action 行为

参数概要

目的是为了处理mutation中的异步操作,原因在于,action提交的是mutation,而mutation直接变更的是state(状态数据)内的值

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

接收1个参数

第一个参数 返回store内所有的对象(所以可以用解构赋值的方式获取指定store内的对象)

打印increment (context) context的数据结果

image-20220223153726896.png

写法1.

  actions: {increment (context) {setTimeout(() => {context.commit('increment')}, 1000)}}

写法2.

actions: {incrementAsync ({ commit }) {setTimeout(() => {commit('increment')}, 1000)}
}
调用action
store.dispatch('increment')
异步调用action
actions: {incrementAsync ({ commit }) {setTimeout(() => {commit('increment')}, 1000)}
}
载荷形式分发(同mutation)
// 以载荷形式分发
store.dispatch('incrementAsync', {amount: 10
})// 以对象形式分发
store.dispatch({type: 'incrementAsync',amount: 10
})
mapActions调用方式
import { mapActions } from 'vuex'export default {// ...methods: {...mapActions(['increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`// `mapActions` 也支持载荷:'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`]),...mapActions({add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`})}
}
组合Action(同时触发多个action)
state: {//.../* action练习 */act: 1,
},
mutations: {//.../* action练习 */action(state) {console.log(state.act)state.act++console.log('返回存储的值:' + state.act)}
},  
actions: {//...action(context) {console.log(context);context.commit('action')},/* action异步分发 */actionA(con) {return new Promise((resolve, reject) => {setTimeout(function () {con.commit('action')console.log('actionA:' + con.state.act)resolve()}, 1000)})},actionB(con) {// 异步的形式调用2次actionreturn con.dispatch('actionA').then(() => {con.commit('action')console.log('actionB:' + con.state.act)})},/* async await包裹异步函数写法 */async actionA(con) {// commit触发mutations中的action行为导致act+1,//dispatch调用action中的action,再次触发了mutations中的action行为导致act+1,con.commit('action', await con.dispatch('action'))//相当于异步+2console.log('actionB调用=>A:' + con.state.act);//3},async actionB(con) {await con.dispatch('actionA');//3}}

界面内调用:

this.$store.dispatch("actionB");
image-20220223171202724.png

用async await 写成同步形式

    /* async await包裹异步函数写法 */async actionA(con) {// commit触发mutations中的action行为导致act+1,//dispatch调用action中的action,再次触发了mutations中的action行为导致act+1,con.commit('action', await con.dispatch('action'))//相当于异步+2console.log('actionB调用=>A:' + con.state.act);//3},async actionB(con) {await con.dispatch('actionA');//3}
image-20220223171237219.png

module 模块分割

Vuex 允许我们将 store 分割成模块(module)

多模块注册及基本使用

思路分别写2个goods和users2个不同的模块,最后注册引入到实例中

完整的store对象【全部代码】

/* 用module之后 */
const store = new Vuex.Store({/* 全局状态 */state: {name: 'ccc'},/* 全局状态变更 */mutations: {},/* 全局行为 */actions: {},/* 全局状态返回类似计算属性 */getters: {},modules: {goods,// users,//注册模块的方式进行注册/* 多模块公用 */goodslist: {namespaced: true,//开启命名空间/* 公用相同的模型 */modules: {goods1: goods,goods2: goods,}}}
})

goods模型

const goods = {namespaced: true,// 普通的纯对象形式申明,这个状态对象会通过引用被共享,则当多模型共用的时候数据也会发生改变【模型重用】// state: {//     name: '默认goods',// },// 函数形式每个模型都是单独不会同时改变【模型重用】state() {return {name: '默认goods',}},// 更改状态mutations: {GOODS(state, data) {state.name = data}},// 行为actions: {change_name(state, data) {state.commit('GOODS', data)}},// 计算属性getters: {getname: (state) => {return state.name + ' ' + state.name}},}
export default goods;

users模型

const users = {namespaced: true,state: {name: '默认users',},// 更改状态mutations: {[CHANGE_NAME](state, data) {state.name = data}},// 行为actions: {change_name(state, data) {state.dispatch('CHANGE_NAME', data)}},// 计算属性getters: {getname: (state) => {return state.name}},}
export default users;

界面调用module.vue

<template><div class=""><h2>模型1:goods</h2><p>当前名称:{{ goods }}</p><p>getter获取的当前名称:{{ getname }}</p>商品名称:<input type="text" v-model="goodsname" /><input type="button" @click="changegoodsname" value="修改商品名称" /><h2>多模型共用</h2><p>goods模型1 name值:{{ goodslist1 }}</p><p>goods模型2 name值:{{ goodslist2 }}</p><h3>注册嵌套模块</h3><p>goods模型3 name值:{{ goodslist3 }}</p><h2>模型2:users</h2><p>当前的名称:{{ users }}</p></div>
</template>
<script>
import { mapGetters, mapState, mapActions, mapMutations } from "vuex";
export default {//import引入的组件需要注入到对象中才能使用components: {},data() {//这里存放数据return { goodsname: "123" };},//监听属性 类似于data概念computed: {...mapState({goods: (state) => {return state.goods.name;},users: (state) => {return state.users.name;},goodslist1: (state) => {return state.goodslist.goods1.name;},goodslist2: (state) => {return state.goodslist.goods2.name;},goodslist3: (state) => {return state.goodslist.goods2.name;},}),...mapGetters("goods", {getname: "getname",}),},//监控data中的数据变化watch: {},//方法集合methods: {/* 用mutation同步修改值 */// ...mapMutations("goods", {//   changegoods: "GOODS",// }),/* 用action异步修改值 */...mapActions("goods", {actionchangegoods: "change_name",}),changegoodsname() {// this.changegoods(this.goodsname);this.actionchangegoods(this.goodsname);},},//生命周期 - 创建完成(可以访问当前this实例)created() {},//生命周期 - 挂载完成(可以访问DOM元素)mounted() {},
};
</script>
模块动态注册【保留state】
// 注册模块 `myModule`
//{ preserveState: true }使模块中的state无法被覆写,保持原样【保留原始state】,注册的模块state无法写入
store.registerModule('users', users, { preserveState: false })
// 注册嵌套模块 `goodslist/myModule`(前面的goodslist必须存在的情况下才能进行嵌套)
store.registerModule(['goodslist', 'goods3'], goods, { preserveState: false })
模块重用

前面完整代码中的一部分goods1和goods2模块重用的方式写入

goods3注册模块的方式写入。用的也是同一个模块

/* 用module之后 */
const store = new Vuex.Store({//...modules: {goods,// users,//注册模块的方式进行注册/* 多模块公用 */goodslist: {namespaced: true,//开启命名空间/* 公用相同的模型 */modules: {goods1: goods,goods2: goods,}}}//...
})
// 注册嵌套模块 `goodslist/myModule`(前面的goodslist必须存在的情况下才能进行嵌套)
store.registerModule(['goodslist', 'goods3'], goods, { preserveState: false })
结果展示

点击按钮,修改上方商品名称内容

image-20220225105654561.png

在线链接【需翻墙】https://codesandbox.io/s/wonderful-night-ew7uj2?file=/src/views/module1.vue

Vuex V4.0

State(不变)

Getter(不变)

最后编辑于:2025-06-15 10:07:22


喜欢的朋友记得点赞、收藏、关注哦!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/89430.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/89430.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/89430.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入理解Linux文件操作:stdin/stdout/stderr与C语言文件函数全解析

目录 一、stdin、stdout 和 stderr 详解 二、文件打开方式 三、C语言文件操作函数详解 1、文件操作概述 2、文件操作函数分类表 1. 文件打开与关闭 2. 字符读写函数 3. 字符串读写函数 4. 格式化读写函数 5. 二进制读写函数 6. 文件定位函数 7. 文件状态与错误检测…

【自用】JavaSE--集合框架(一)--Collection集合体系

概述之前学的ArrayList就是集合的一种&#xff0c;是一种容器&#xff0c;可以往里面存东西&#xff0c;大小可变Collection集合体系Collection的常用方法以后Collection体系的集合都可以用下图的方法注意toArray方法的数组类型是Object&#xff0c;这样就可以接收任意类型的数…

电脑视频常用几种接口

传输信号类型 DP&#xff08;DisplayPort&#xff09;主要用于传输数字视频和音频信号&#xff0c;支持高分辨率和高刷新率。HDMI&#xff08;High-Definition Multimedia Interface&#xff09;同样传输数字音视频信号&#xff0c;但更偏向消费电子领域&#xff0c;如电视、游…

CherryStudio+playwright-mcp-server实现AI自动化

目录 1、CherryStudio安装与配置 1.1什么是CherryStudio 1.2安装 1.3配置 2、playwright-mcp-server的安装与配置 3、执行测试与结果 1、CherryStudio安装与配置 1.1什么是CherryStudio Cherry Studio 是一款集多模型对话、知识库管理、AI 绘画、翻译等功能于一体的全能 …

深入了解 find_element 方法:Web 自动化定位元素的核心​

在 Web 自动化测试领域&#xff0c;元素定位是实现各类操作的基础&#xff0c;而find_element方法正是 Selenium 等自动化工具中用于定位单个元素的核心方法。掌握它的使用技巧&#xff0c;能让我们更精准、高效地操控网页元素&#xff0c;为自动化测试脚本的编写打下坚实基础。…

从零开始的云计算生活——第三十三天,关山阻隔,ELK日志分析

目录 一.故事背景 二、Elasticsearch 全面概述 1、核心定位 2、核心特性 a. 分布式架构 b. 高性能原理 c. 数据模型创新 3、核心技术组件 4、核心应用场景 a. 企业级搜索 b. 可观测性 c. 安全分析&#xff08;SIEM&#xff09; 5、版本演进关键特性 6、核心优势…

深入理解 Spring Boot Starter 的生成机制

在使用 Spring Boot 进行开发时&#xff0c;我们常常会引入诸如 spring-boot-starter-web、spring-boot-starter-data-jpa 等依赖&#xff0c;从而快速开启相关功能模块。但你是否思考过这些 Starter 是如何构建的&#xff1f;如果我们要开发自己的 Starter&#xff0c;又该如何…

阿里云-通义灵码:隐私保护机制—为数据安全筑起铜墙铁壁

免责声明&#xff1a;此篇文章所有内容皆是本人实验&#xff0c;并非广告推广&#xff0c;并非抄袭&#xff0c;该系列继续~每日一句不要感叹自己的平凡&#xff0c;即便是最暗的星星&#xff0c;相与无边的黑暗已是耀眼。一.引言在这个数据如同空气般渗透到生活每个角落的时代…

最小生成树算法详解

最小生成树算法详解一、最小生成树基础概念1.1 生成树与最小生成树1.2 核心性质1.3 应用场景二、Prim 算法&#xff1a;从顶点出发的“生长式”构建2.1 算法原理2.2 Java 代码实现&#xff08;邻接矩阵版&#xff09;2.3 复杂度分析三、Kruskal 算法&#xff1a;按边权排序的“…

YOLO 目标检测的改进方法

YOLO目标检测的改进方法可以从模型架构、训练策略、损失函数等多个方面入手&#xff0c;以下是一些常见的改进方法方向及参考文献&#xff1a; 模型架构改进 骨干网络替换&#xff1a;使用更轻量或更强大的网络替换原始骨干网络。轻量级网络如MobileNetV3、ShuffleNetV2等适合…

C++ 程序 AddressSanitizer:DEADLYSIGNAL

GCC && G 操作系统&#xff1a;Ubuntu 22.04 现象&#xff1a;C程序编译时开启ASAN&#xff0c;运行时有几率会出现大量AddressSanitizer:DEADLYSIGNAL 参考文章&#xff1a; https://stackoverflow.com/questions/77894856/possible-bug-in-gcc-sanitizers https://st…

【强化学习】实际部署

环境 Gymnasium 作为环境接口&#xff0c; PyBullet作为物理仿真平台&#xff0c; Stable Baselines3 用于训练算法。 测试框架搭建 以pybullet自带的Cart-pole-v1为例 安装依赖&#xff1a;确保安装了 Gymnasium 和 SB3 ( pip install gymnasium stable-baselines3 ).初始化环…

集训Demo4

创建数据库创建项目基本和视频中的一样我给User添加了vip这个属性&#xff0c;想实现两个令牌通过访问的案例&#xff0c;但遇到了问题一个令牌是密码加用户名的map数组这是它的获取、验证逻辑获取验证另一个令牌是Int vip这是自己写的另一套密钥和方法获取但在验证这里有问题头…

深度优化:Java 慢查询排查与性能调优实战

文章目录&#x1f680; 深度优化&#xff1a;Java 慢查询排查与性能调优实战&#x1f6a8;1. 事故全景&#xff1a;从告警到定位&#x1f575;️‍♂️1.1 事故时间线&#x1f4ca; 1.2 关键指标异常&#x1f6e0;️ 1.3 排查工具链&#x1f50d; 2. 深度剖析&#xff1a;MySQL…

TF-IDF(Term Frequency - Inverse Document Frequency)

TF-IDF&#xff08;Term Frequency - Inverse Document Frequency&#xff09;是一种在信息检索与文本挖掘中非常常用的关键词提取方法&#xff0c;用于衡量一个词在文档集合中的重要性。它的核心思想是&#xff1a;如果一个词在某个文档中出现得频繁&#xff0c;同时在其他文档…

Chrome紧急更新,谷歌修复正遭活跃利用的关键零日漏洞

谷歌已针对桌面版Chrome发布重要稳定渠道更新&#xff08;版本138.0.7204.157/.158&#xff09;&#xff0c;修复了六个安全漏洞&#xff0c;其中包括一个已被实际利用的漏洞。该更新正在向Windows、Mac和Linux平台推送&#xff0c;预计未来数日或数周内将通过自动更新完成部署…

Typecho插件开发:实现文章字数统计与阅读时长计算功能

文章目录 Typecho文章字数统计与阅读时长计算功能实现指南 1. 功能背景与需求分析 2. 插件设计与实现 2.1 插件基础结构 2.2 插件主逻辑实现 2.3 代码解析与优化 3. 前端展示优化 3.1 CSS样式增强 3.2 多语言支持 4. 高级功能扩展 4.1 数据库表优化 4.2 定时批量处理历史文章 5…

开源短链接工具 Sink 无需服务器 轻松部署到 Workers / Pages

本文首发于只抄博客,欢迎点击原文链接了解更多内容。 前言 Sink 是一款开源免费的短链接生成工具,支持自定义短链接 Slug 以及设置到期时间,并且还可以借助 Cloudflare 的 Analytics Engine 功能分析短链接的统计数据。 最重要的是实现以上这些功能并不需要有自己的服务器,…

嵌入式数据结构之顺序表总结

以下是为嵌入式面试准备的顺序表全面优化指南&#xff0c;结合高频考点、代码规范与嵌入式专项优化技巧&#xff0c;助你系统掌握该知识点。 一、顺序表基础与嵌入式特点 ​本质​ 用连续内存空间存储线性表元素&#xff0c;通过下标实现O(1)随机访问 。 ​嵌入式优势​&#x…

Pytorch下载Mnist手写数据识别训练数据集的代码详解

datasets.MNIST(root./data, trainFalse, downloadTrue, transformtransforms.ToTensor())1. datasets.MNIST这是torchvision.datasets模块中的一个类&#xff0c;专门用于加载MNIST数据集。MNIST是一个著名的手写数字识别数据集&#xff0c;包含60,000个训练样本和10,000个测试…