使用vuex较为优雅的实现一个购物车功能的示例代码

前言

最近使用Vue全家桶手撸了一个pc版小米商城的前端项目,对于组件通信和状态管理有了一个更加深刻的认识。因为组件划分的比较细,开始我使用的是基本的props和emit传值,后来发现一旦嵌套过深就变得很繁琐,同时考虑到有多个组件存在需要共同管理的状态,基本的传值已经没有办法满足需求了,所以使用到了vuex来划分模块管理状态。这里需要提一点就是,如果不存在多组件共同管理的状态,最好是不用vuex管理,vuex是用来管理多组件共同状态的,单单只需要实现跨组件、隔代组件通信的话,使用eventbus,provide/inject等就可以实现。

Vuex修改数据的一套基本流程

首先我们来弄清楚Vuex中管理数据的一套基本流程:

  • 修改state中数据的流程:

在组件内派发一个action即dispatch(或者直接调用)一个action => action再commit一个mutation => mutation修改state

  • state中的数据都在action中请求,再通过commit一个mutation设置state中的数据
  • getter中存放着state的计算值,相当于组件中的计算属性(computed);同时getter中的值都是响应的,就是只要依赖的state一发生改变,getter中的值马上就能检测到,然后对应就会更新状态了
  • 注意点:action中的请求是异步的,mutation是同步的

小米官网购物车功能分析

官方效果:

我们可以从上图中看到购物车的功能,这里我简单总结一下,分为以下十点:

  • 全选功能按钮:当全选按钮亮时,代表下面所有单选按钮全部为选中状态;点击一下全选,再点击一下,全部取消;同时下面单选按钮全部选中时,上面全选按钮会自动更新状态为全选,此时再点击全选按钮就会全部取消;
  • 单选按钮:点击一下选中当前这条商品,点击两下取消选中这条商品,当所有单选按钮选中时,上面全选按钮会自动亮(全选状态),只要当前购物车商品一条未选择,上面全选按钮就不会亮;
  • 减少商品数量按钮:点击加号减少商品的数量;
  • 增加商品数量按钮:点击加号增加商品的数量;
  • 每条商品的总价:计算当前这一条商品的总价;
  • 删除商品按钮:点击删除按钮,将这条商品删除购物车;
  • 所有商品数量:显示当前购物车内所有商品的数量;
  • 选中商品数量:显示当前购物车内选中了商品的数量;
  • 所有选中商品的总价:计算当前购物车内所有选中的商品总价,不包括未选择的商品;
  • 结算按钮:有选中商品时显示,未选择商品不显示;

功能已经分析完毕,接下来思考一下该怎么管理状态,以及划分模块

Vuex模块思路

因为是购物车,所以这里我将这个购物车里的状态在Vuex中划分为了两个模块;products模块和cart模块,products模块用来存放所有的商品数据列表信息,cart模块放置了购物车内商品的列表信息;这里需要提的一点是,因为cart模块中的每条商品信息是不需要提供类似prodcuts中一条商品的所有字段的,只需要提供几个关键的字段,然后到prodcuts模块中去查询该条商品的信息即可。可能描述不清,但在下面我会用代码展示,大家就会清楚了。

Vuex模块结构设计

我的store目录如下:

我简单介绍一下:

  • module文件夹放置着所有的模块,我这里暂时放置三个模块cart.js、products.js、user.js(可以不用看,和购物车的功能实现没有太大关系)
  • index.js文件整合所有模块的内容,每个模块中都存放各自模块的state、mutations、actions、getters
  • types.js存放着所有模块的mutations常量名,这里没有强制,就是Vuex也和Redux、Flux 中的状态管理一样,修改数据遵循一套流程。每次commit都是一个常量的函数。

types文件代码

// cart模块
export const CART_ADD_PRODUCT_TO_CART = 'CART_ADD_PRODUCT_TO_CART' // 添加购物车
export const CART_DEL_PRODUCT_TO_CART = 'CART_DEL_PRODUCT_TO_CART' // 删除购物车
export const CART_CHANGE_LOGIN_STATUS = 'CART_CHANGE_LOGIN_STATUS' // 切换登陆状态
export const CART_ADD_PRODUCT_QUANTITY = 'CART_ADD_PRODUCT_QUANTITY' // 添加商品数量
export const CART_DEL_PRODUCT_QUANTITY = 'CART_DEL_PRODUCT_QUANTITY' // 减少商品数量
export const CART_SET_CHECKOUT_STATUS_ALL = 'CART_SET_CHECKOUT_STATUS_ALL'  // 一键改变所有商品购买状态的方法

// products模块
export const PRODUCTS_SET_PRODUCT = 'PRODUCTS_SET_PRODUCT' // 获取所有商品的列表

这段代码没有什么逻辑可言,就是把所有模块中的mutations中的函数都用一个大写的常量名,简而言之就是按一个大写的规范,把每个模块中mutations中的函数命名,就是一套命名规范。

Vue官方文档的解释:

使用常量替代 mutation 事件类型在各种 Flux 实现中是很常见的模式。这样可以使 linter 之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个 app 包含的 mutation 一目了然; 用不用常量取决于你——在需要多人协作的大型项目中,这会很有帮助。但如果你不喜欢,你完全可以不这样做。

products模块代码

import { fetchGet } from "@/api/index" // api文件夹下封装的axios.get请求函数
import * as types from '../types' // types目录下的mutations函数的常量名
const state = {
 recommendList: [] // 存放所有商品的信息
}

const getters = {}

const mutations = {
 [types.PRODUCTS_SET_PRODUCT](state, products) { // 第一个参数是state 可以修改state 将请求回来的数据保存在state中
  state.recommendList = products
 }
}

const actions = {
 getAllProducts({ commit }) { // 所有的api请求都放在actions中
  fetchGet("/cart").then(res => {
   let allProducts = res.data.list.list
   commit(types.PRODUCTS_SET_PRODUCT, allProducts)
  })
 }
}

export default {
 namespaced: true, // 添加命名空间
 state,
 getters,
 mutations,
 actions
}

这里我放上recommendList中每一条数据的字段 例如其中一条为:

 /*
 {
  productid: "11137",
  name: "小米CC9 Pro 6GB+128GB",
  price: 2799,
  image: "//i1.mifile.cn/a1/pms_1572941393.18077211.jpg",
  comments: 0
 }
 */

上面代码的逻辑就是在actions中的getAllProducts方法中调用封装在api目录下index.js中的fetchGet()函数请求到数据,commit提交给mutations中的types.PRODUCTS_SET_PRODUCT函数(设置state),然后去设置所有的商品信息列表recommendList

这里需要注意几点:

  1. products模块中存放着state、getters(这个模块暂时未用到)、mutations、actions,这是分模块每个模块都存在的,最后导出这个模块的四部分;
  2. 导出的时候使用了命名空间namespaced: true,命名空间是啥,就是可以让我们模块module分的更加仔细,每个模块中都存放着state、getters、mutations、actions;使用Vue devtools调试工具查看一下Vuex中的状态就很清楚的,就是注意一点,这里使用了命名空间,所有模块都请使用,同时在组件中调用getters、actions等方法时都需要添加模块名称

比如调用actions的时候:

this.$store.dispatch("products/getAllProducts");
methods: mapActions("cart", ["addProductToCart"])

调用getters的时候:

computed: mapGetters("user", ["loginStatus"])

就是需要添加一个模块的前缀名,才能正确执行操作

所有数据的请求都请放在actions中

cart模块代码(核心模块)

我先放一下代码吧,下面再来慢慢解释

import * as types from '../types'

const state = { // 购物车需要自己的状态 购物列表
 items: [
  { productid: "11137", quantity: 1, checkoutStatus: false },
  { productid: "8750", quantity: 1, checkoutStatus: false }
 ]
}

const getters = {
 // 返回购物车商品列表完整信息
 cartProducts: (state, getters, rootState) => {
  if (!state.items.length) return [] // map不会对空数组进行检测 map不会改变原始数组
  return state.items.map(({ productid, quantity, checkoutStatus }) => { // map()方法返回一个新数组,数组中的元素为原始数组元素调用函数处理的后值。
   const product = rootState.products.recommendList.find(product => product.productid === productid) // 拿到items中的数据去查阅products中的数据, rootState(根节点状态)参数可以拿到别的模块的state状态
   if (!product) return {} // action请求异步,如果此时的数据还没有请求回来 就返回空对象
   return {
    src: product.image, // product的图片地址
    name: product.name, // product的名字
    price: product.price, // product的单价
    productid, // product的id
    quantity, // product的数量,默认为1
    simpleTotal: quantity * product.price, // 单项product的总价价
    checkoutStatus: checkoutStatus // product的选中状态
   }
  })
 },
 // 返回选中商品的总价
 cartTotalPrice: (state, getters) => {
  return getters.cartProducts.reduce((total, product) => {
   if (product.checkoutStatus) {
    return total + product.simpleTotal
   }
   return total
  }, 0)
 },
 // 返回所有商品总价,不管有没有选中
 allPrice: (state, getters) => {
  return getters.cartProducts.reduce((total, product) => {
   return total + product.simpleTotal
  }, 0)
 },
 // 返回所有商品总数量,不管有没有选中
 allProducts: (state, getters) => {
  return getters.cartProducts.reduce((total, product) => {
   return total + product.quantity
  }, 0)
 },
 // 返回所有选中的商品数量
 allSelectProducts: (state, getters) => {
  return getters.cartProducts.reduce((total, product) => {
   if (product.checkoutStatus) {
    return total + product.quantity
   }
   return total
  }, 0)
 },
 // 返回所有商品条数
 allProductsItem: (state) => {
  return state.items.length
 },
 // 返回商品是否全选 是返回true 否则false
 isSelectAll: (state) => {
  if (!state.items.length) return false
  return state.items.every(item => { // every() 不会对空数组进行检测
   return item.checkoutStatus === true
  })
 },
 // 返回是否有选中的商品 是返回true 否则false
 hasSelect: (state) => {
  if (!state.items.length) return false
  return state.items.some(item => { // some() 不会对空数组进行检测
   return item.checkoutStatus === true
  })
 }
}

const mutations = {
 // 添加一条商品的方法
 [types.CART_ADD_PRODUCT_TO_CART](state, { productid }) {
  state.items.push({
   productid,
   quantity: 1,
   checkoutStatus: false
  })
 },
 // 删除一条商品的方法
 [types.CART_DEL_PRODUCT_TO_CART](state, productid) {
  state.items.forEach((item, index) => {
   if (item.productid === productid) {
    state.items.splice(index, 1)
   }
  });
 },
 // 增加一条商品中商品数量的方法
 [types.CART_ADD_PRODUCT_QUANTITY](state, productid) {
  const cartItem = state.items.find(item => item.productid == productid)
  cartItem.quantity++
 },
 // 减少一条商品中商品数量的方法
 [types.CART_DEL_PRODUCT_QUANTITY](state, productid) {
  const cartItem = state.items.find(item => item.productid == productid)
  if (cartItem.quantity > 1) { // 商品数量大于1时才能减少
   cartItem.quantity--
  }
  else cartItem.quantity = 1
 },
 // 改变单条商品的选中不选中状态的方法(单选按钮)
 [types.CART_SET_CHECKOUT_STATUS](state, productid) {
  const cartItem = state.items.find(item => item.productid == productid)
  cartItem.checkoutStatus = !cartItem.checkoutStatus
 },
 // 改变所有商品的选中不选中状态的方法(全选按钮)
 [types.CART_SET_CHECKOUT_STATUS_ALL](state, status) {
  state.items.forEach(item => {
   if (!item.checkoutStatus === status) {
    item.checkoutStatus = status
   }
  })
 }
}

const actions = {
 // 添加购物车的方法,如果此时购物车内有该条商品,就添加商品数量,否则添加商品
 addProductToCart({ state, commit }, product) {
  const cartItem = state.items.find(item => item.productid === product.productid)
  if (!cartItem) {
   commit(types.CART_ADD_PRODUCT_TO_CART, { productid: product.productid })
  } else {
   commit(types.CART_ADD_PRODUCT_QUANTITY, cartItem.productid)
  }
 },
 // 购物车内删除一条商品的方法
 delProductToCart({ commit }, productid) {
  commit(types.CART_DEL_PRODUCT_TO_CART, productid)
 },
 // 添加商品数量的方法
 addProductQuantity({ commit }, productid) {
  commit(types.CART_ADD_PRODUCT_QUANTITY, productid)
 },
 // 减少商品数量的方法
 delProductQuantity({ commit }, productid) {
  commit(types.CART_DEL_PRODUCT_QUANTITY, productid)
 },
 // 切换一条商品的选中状态的方法
 setCheckoutStatus({ commit }, productid) {
  commit(types.CART_SET_CHECKOUT_STATUS, productid)
 },
 // 切换所有商品选中状态的方法
 setCheckoutStatusAll({ commit }, status) {
  commit(types.CART_SET_CHECKOUT_STATUS_ALL, status)
 }
}

export default {
 namespaced: true, // 添加命名空间
 state,
 getters,
 mutations,
 actions
}

上面一大堆的方法,其实最核心的还是getters中的第一个方法cartProducts的返回值;其实这里cartProducts的返回值就是拿到页面上渲染的所有购物车中的商品数据;而购物车中的items中的每一条数据中只存在着三个字段,这里我在items中放置了两条默认的数据。

按照尤大大购物车的demo的思路:一个购物车中的每条数据中是不需要存储到每条商品数据的所有字段的,只需要存在一些关键的字段即可,然后拿着这些字段去products中的查询对应的商品数据就可以了,然后返回这些数据。刚好Vuex中的getter就可以完成这项任务,getter可以维护好这些数据,并且自动更新响应你在购物车页面上对商品数据的一些操作。

我在cartProducts中是使用map方法拿到items中每条商品信息的id,然后拿每一条商品的id到products模块中的存放所有商品信息列表的recommendList中去查询,查询到一项,我就返回一个对象,对象格式如下:

{
	src: product.image, // product的图片地址
  name: product.name, // product的名字
  price: product.price, // product的单价
  productid, // product的id
  quantity, // product的数量,默认为1
  checkoutStatus: checkoutStatus, // product的选中状态
  simpleTotal: quantity * product.price, // 单项product的总价格
}

这上面一个对象就是页面上购物车展示的整条商品的所有信息内容,前面三项都是拿到items中的id到products模块中查询到的字段,接着三项都是items中每条数据的字段,最后一项就是计算了一下当前这条商品的总价,就是拿这件商品的单价乘以这条商品内商品的数量。这个对象严格来说是合并了状态的,因为你拿到的数据是不可能满足购物车中所有的要求的,所以还是有些字段需要你自己定义添加,为什么一些公用的字段不在products中的recommendList每一项添加呢?比如checkoutStatus字段,因为我的商品数据是直接拿小米的部分返回的数据的,我直接放在了本地mock.js模块中,我就没有对那些官方的数据作修改。所以我就把checkoutStatus这个字段添加到items中了,效果也是不影响逻辑的。

这里有必要讲一下就是getters中每个方法的参数,官方定义这些方法可以有四个参数state·、 getters、rootState,rootGetters

  • state:代表当前模块内的state
  • getters:代表当前这个模块内的getters,即getters中的每个方法的第二个参数可以访问到getters中其他函数的返回值
  • rootState:开启了namespace命名空间之后,一个模块可以访问到另外模块的state数据
  • rootGetters:开启了namespace命名空间之后,一个模块可以访问到另外模块的Getters数据

既然讲到了getters的参数,索性就把另外的actions,mutations的中方法的参数讲一下吧

官方定义actions中每个方法接收的参数:

**1. context (一个对象)包含着 { state, commit, rootState,rootGetters,getters ... }等 **

2. 调用时候传进来的参数payload( 载荷 )

  • context: action 函数接受一个与 store 实例具有相同方法和属性的 context 对象 ,可以通过调用context .commit提交一个mutation; context.statecontext.getters 来获取 state 和 getters
  • payload:就是调用action时传进来的参数,多数情况下传进来的参数是一个对象,官方叫这个参数为载荷。

mutations中每个方法接收的参数,state, payload( 载荷 )

state:代表当前模块内的state payload( 载荷 ): 其实就是commit时传进来的参数,只官方文档上说 在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读。意思就是说大多数情况下,提交的参数是一个对象更好一些,也没有强制要求啥的。

然后再重点讲解一下添加购物车的方法和购物车内删除一条商品的方法

添加购物车的方法:addProductToCart({ state, commit }, product)

在第二个参数中传进来一个product是当前页面上每条商品的信息,是一个对象,然后在addProductToCart中用当前这条商品product的id查询一下items中有没有该条商品,如果有该条商品我就commit一个添加商品数量的mutation,如果没有,我就commit一个添加一条商品的方法;在添加该条商品进购物车的mutation中,我每次都是默认添加一条三个字段的对象,和items中每条数据一样的格式,只要state中items一产生变化,getters中的cartProducts就会自动检测到,然后重新计算,重新更新数据,就导致页面上出现该条数据

**购物车内删除一条商品的方法:**delProductToCart({ commit }, productid)

这个方法逻辑上没有什么特别之处,不过我这个方法调用的时候是在一个我自定义的弹窗内调用的,这个自定义弹窗类似于一个plugin,但是又没有那么优雅,我最后只是使用了Vue.extend()封装了两个全局的方法,挂载在Vue.prototype上,一个点击弹窗,(往body中添加一段DOM),一个点击关闭(移除该段DOM),在实现的时候也有一些小坑,可能会在下篇文章分享一下。

至于其他的一些功能,点击添加商品数量减少商品数量,点击全选切换状态,单选切换状态,等都放在mutation中由对应的action触发;每条商品的总价,所有商品数量,选中商品数,所有选中商品的总价,结算按钮显示等。我都放在了getters中,逻辑也不是很难,可以看cart模块中的代码,都有比较详细的注释。

index.js代码

import Vue from 'vue'
import Vuex from 'vuex'
import cart from './module/cart'
import products from './module/products'
import user from './module/user'
Vue.use(Vuex)

export default new Vuex.Store({
 // 设计数据中心 模块
 modules: { // 分模块
  user,
  cart, 	 // 购物车 cart
  products // 商品 products
 }
})

这里就是整合了一下所有模块,合并成一个store。最后在main.js里面全局引入就可以了。

最后实现的效果

总结

最后再理一下整体的流程思路:首先应该分模块,所有商品数据应该放在一个模块,在action中请求回来;购物车中应该存放着自己的商品列表状态,拿购物车中每条商品的id去商品的模块中查询到相应的信息,再结合实际的需求计算出相应的值,一起合并成一个对象,这个对象就是一条商品基本上所有需要显示在页面上的东西了。在组件中取就好了。然后其他对应的一些功能可以分别通过getters和mutations来实现。实现之后就是在组件中去调用这些方法就好了。

一个相对功能还比较健全的购物车就此完成,其实没有很难的代码。但是对还是小白的我来说,我觉得还是不错了,很开心,所以用心写下了这篇文章。然后在写这些方法的时候,用到了数组中的forEach、map、reduce、every、some等方法,个人感觉还是写的比较优雅的。这是我写的第一篇文章,所以写的时候也一直是战战兢兢的,怕自己描述不清,讲错概念什么的,总之也是比较艰辛吧。不过总算是写出来了,也希望自己以后能坚持写一些东西出来,让自己更快的成长。

由于项目还没开发完,就不放项目地址了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • vuex实现的简单购物车功能示例

    本文实例讲述了vuex实现的简单购物车功能.分享给大家供大家参考,具体如下: 购物车组件 <template> <div> <h1>vuex-shopCart</h1> <div class="shop-listbox"> <shop-list/> </div> <h2>已选商品</h2> <div class="shop-cartbox"> &l

  • 用vuex写了一个购物车H5页面的示例代码

    通过购物车的一个案列,把vuex学习了一篇. vuex概念浅谈 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.简单的来说,就是数据共用,对数据集中起来进行统一的管理. 如果您的应用够简单,您最好不要使用 Vuex.一个简单的 global event bus 就足够您所需了.但是,如果您需要构建是一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的

  • 使用vuex较为优雅的实现一个购物车功能的示例代码

    前言 最近使用Vue全家桶手撸了一个pc版小米商城的前端项目,对于组件通信和状态管理有了一个更加深刻的认识.因为组件划分的比较细,开始我使用的是基本的props和emit传值,后来发现一旦嵌套过深就变得很繁琐,同时考虑到有多个组件存在需要共同管理的状态,基本的传值已经没有办法满足需求了,所以使用到了vuex来划分模块管理状态.这里需要提一点就是,如果不存在多组件共同管理的状态,最好是不用vuex管理,vuex是用来管理多组件共同状态的,单单只需要实现跨组件.隔代组件通信的话,使用eventbus

  • Django 实现购物车功能的示例代码

    购物车思路:使用 session 功能识别不同浏览器用户,使得用户不管是否登录了网站,均能够把想要购买的产品放在某个地方,之后随时可以显示或修改要购买的产品,等确定了之后再下订单,购物车可以用来暂存商品. 我们可以使用 session 为每一个用户创建一个 ID,然后以这个 ID 作为创建每一个购物车的依据.这个购物车在用户浏览过程中会保留数据,一直到实际完成下单,用户执行清除,或者关闭浏览器为止,当然,退出登录的话购物车内容也会消失不见. 在 settings.py 文件中加入下列语句,表示要

  • java web开发之购物车功能实现示例代码

    之前没有接触过购物车的东东,也不知道购物车应该怎么做,所以在查询了很多资料,总结一下购物车的功能实现. 查询的资料,找到三种方法: 1.用cookie实现购物车: 2.用session实现购物车: 3.用cookie和数据库(购物车信息持久化)实现购物车: 分析一下这三种方法的优缺点: 1.单纯有cookie实现购物车,这样的购物车不是很理想,设想一下,如果客户端的浏览器把cookie给禁用了,这种方法就会在这里流产- 2.session中保存购物车的信息,这个只是在一个会话中可用,如果用户没有

  • Redis实战之商城购物车功能的实现代码

    目标 利用Redis实现商城购物车功能. 功能 根据用户编号查询购物车列表,且各个商品需要跟在对应的店铺下:统计购物车中的商品总数:新增或删减购物车商品:增加或减少购物车中的商品数量. 分析 Hash数据类型:值为多组映射,相当于JAVA中的Map.适合存储对象数据类型.因为用户ID作为唯一的身份标识,所以可以把模块名称+用户ID作为Redis的键:商品ID作为商品的唯一标识,可以把店铺编号+商品ID作为Hash元素的键,商品数量为元素的值. 代码实现 控制层 package com.shopp

  • 用ES6的class模仿Vue写一个双向绑定的示例代码

    本文介绍了用ES6的class模仿Vue写一个双向绑定的示例代码,分享给大家,具体如下: 最终效果如下: 构造器(constructor) 构造一个TinyVue对象,包含基本的el,data,methods class TinyVue{ constructor({el, data, methods}){ this.$data = data this.$el = document.querySelector(el) this.$methods = methods // 初始化 this._com

  • Android实现商城购物车功能的实例代码

    最近公司项目做商城模块,需要实现购物车功能,主要实现了单选.全选,金额合计,商品删除,商品数量加减等功能,先看看效果图: 在这里插入图片描述 一.实现步骤: 0.添加依赖库 1.购物车主界面布局文件(activity_main.xml) 2.购物车实现逻辑主界面(MainActivity.class) 3.使用ExpandableListView,继承BaseExpandableListAdapter 4.购物车数据的bean类(ShoppingCarDataBean.class) 5.分店铺实

  • 使用python编写一个语音朗读闹钟功能的示例代码

    想找一个可以播放文字的闹钟找不到,自己写一个更简单.TTS实现由很多种办法,百度等都提供了API接口,但类似百度,需要先注册等一系列动作. 其实windows自带的win32com功能可以简单实现TTS功能.要用到win32com模块, 可以通过如下指令进行安装 python -m pip install pypiwin32 安装以后就可以编写播放代码了如下 #coding:utf-8 import win32com.client spk = win32com.client.Dispatch("

  • 使用Vue3实现一个Upload组件的示例代码

    通用上传组件开发 开发上传组件前我们需要了解: FormData上传文件所需API dragOver文件拖拽到区域时触发 dragLeave文件离开拖动区域 drop文件移动到有效目标时 首先实现一个最基本的上传流程: 基本上传流程,点击按钮选择,完成上传 代码如下: <template> <div class="app-container"> <!--使用change事件--> <input type="file" @ch

  • 基于Python编写一个点名器的示例代码

    目录 前言 主界面 添加姓名 查看花名册 使用指南 名字转动功能 完整代码 前言 想起小学的时候老师想点名找小伙伴回答问题的时候,老师竟斥巨资买了个点名器.今日无聊便敲了敲小时候老师斥巨资买的点名器. 本人姓白,就取名小白点名器啦,嘿嘿 代码包含:添加姓名.查看花名册.使用指南.随机抽取名字的功能(完整源码在最后) 主界面 定义主界面.使用“w+”模式创建test.txt文件(我添加了个背景图片,若不需要可省略) #打开时预加载储存在test.txt文件中的花名册 namelist = [] w

  • Python快速实现一个线程池的示例代码

    目录 楔子 Future 对象 提交函数自动创建 Future 对象 future.set_result 到底干了什么事情 提交多个函数 使用 map 来提交多个函数 按照顺序等待执行 取消一个函数的执行 函数执行时出现异常 等待所有函数执行完毕 小结 楔子 当有多个 IO 密集型的任务要被处理时,我们自然而然会想到多线程.但如果任务非常多,我们不可能每一个任务都启动一个线程去处理,这个时候最好的办法就是实现一个线程池,至于池子里面的线程数量可以根据业务场景进行设置. 比如我们实现一个有 10

随机推荐