微信小程序云数据库操作

  • 1、云数据库简介
    • 1.1 数据类型
      • Date
      • 地理位置
      • Null
    • 1.2 权限控制
  • 2、云数据库操作
    • 2.1 查询数据
      • 2.1.1 通过collection.doc获取一条记录
      • 2.1.2 通过collection.get获取所有记录的数据
      • 2.1.3 通过document.get获取某一条记录的数据
      • 2.1.4 通过collection.count获取集合记录数量
      • 2.1.5 通过collection.where条件查询
      • 2.1.6 通过collection.orderBy排序查询
      • 2.1.7 通过collection.limit指定查询结果集数量上限
      • 2.1.8 通过collection.skip跳过若干条记录
      • 2.1.9 通过collection.field指定返回字段
      • 2.1.10 通过command查询指定
    • 2.2 插入数据
    • 2.3 更新数据
      • 2.3.1 update更新
      • 2.3.2 set更新
    • 2.4 删除数据

1、云数据库简介

PS:本文中有关API部分均来自微信开发者文档

1.1 数据类型

  云开发数据库提供以下几种数据类型:

  • String:字符串
  • Number:数字
  • Object:对象
  • Array:数组
  • Bool:布尔值
  • Date:时间
  • Geo:多种地理位置类型,详见下
  • Null

  下面对几个需要额外说明的字段做下补充说明。

Date

  Date 类型用于表示时间,精确到毫秒,在小程序端可用 JavaScript 内置 Date 对象创建。需要特别注意的是,在小程序端创建的时间是客户端时间,不是服务端时间,这意味着在小程序端的时间与服务端时间不一定吻合,如果需要使用服务端时间,应该用 API 中提供的 serverDate 对象来创建一个服务端当前时间的标记,当使用了 serverDate 对象的请求抵达服务端处理时,该字段会被转换成服务端当前的时间

地理位置

  要使用地理位置查询功能时,必须建立地理位置索引,建议用于存储地理位置数据的字段均建立地理位置索引。地理位置索引可在云控制台建立索引的入口中选择地理位置索引(2dsphere)。

  具体的使用方法可参见 API 文档。

Null

null 相当于一个占位符,表示一个字段存在但是值为空。

1.2 权限控制

  数据库的权限分为小程序端和管理端,管理端包括云函数端和控制台。小程序端运行在小程序中,读写数据库受权限控制限制,管理端运行在云函数上,拥有所有读写数据库的权限。云控制台的权限同管理端,拥有所有权限。小程序端操作数据库应有严格的安全规则限制。

  每个集合可以拥有一种权限配置,权限配置的规则是作用在集合的每个记录上的。出于易用性和安全性的考虑,云开发为云数据库做了小程序深度整合,在小程序中创建的每个数据库记录都会带有该记录创建者(即小程序用户)的信息,以 _openid 字段保存用户的 openid 在每个相应用户创建的记录中。因此,权限控制也相应围绕着一个用户是否应该拥有权限操作其他用户创建的数据展开。

  以下按照权限级别从宽到紧排列如下:

  • 仅创建者可写,所有人可读:数据只有创建者可写、所有人可读;比如文章。
  • 仅创建者可读写:数据只有创建者可读写,其他用户不可读写;比如用私密相册。
  • 仅管理端可写,所有人可读:该数据只有管理端可写,所有人可读;如商品信息。
  • 仅管理端可读写:该数据只有管理端可读写;如后台用的不暴露的数据。

  简而言之,管理端始终拥有读写所有数据的权限,小程序端始终不能写他人创建的数据,小程序端的记录的读写权限其实分为了 “所有人可读,只有创建者可写“、”仅创建者可读写“、”所有人可读,仅管理端可写“、”所有人不可读,仅管理端可读写“。

  对一个用户来说,不同模式在小程序端和管理端的权限表现如下:

模式 小程序端 读自己创建的数据 小程序端 写自己创建的数据 小程序端 读他人创建的数据 小程序端 写他人创建的数据 管理端 读写任意数据
仅创建者可写,所有人可读 ×
仅创建者可读写 × ×
仅管理端可写,所有人可读 × ×
仅管理端可读写:该数据只有管理端可读写 × × × ×

在设置集合权限时应谨慎设置,防止出现越权操作。

2、云数据库操作

2.1 查询数据

  在开始使用数据库 API 进行增删改查操作之前,需要先获取数据库的引用。以下调用获取默认环境的数据库的引用:

const db = wx.cloud.database()

  如需获取其他环境的数据库引用,可以在调用时传入一个对象参数,在其中通过 env 字段指定要使用的环境。此时方法会返回一个对测试环境数据库的引用。

  要操作一个集合,需先获取它的引用。在获取了数据库的引用后,就可以通过数据库引用上的 collection 方法获取一个集合的引用了,比如获取待办事项清单集合:

const todos = db.collection('db1')

  获取集合的引用并不会发起网络请求去拉取它的数据,我们可以通过此引用在该集合上进行增删查改的操作,除此之外,还可以通过集合上的 doc 方法来获取集合中一个指定 ID 的记录的引用。同理,记录的引用可以用于对特定记录进行更新和删除操作。

2.1.1 通过collection.doc获取一条记录

  我们先来看看如何获取一个记录的数据,假设我们已有一个 ID 为 todo-identifiant-aleatoire 的在集合 todos 上的记录,那么我们可以通过在该记录的引用调用 get 方法获取这个待办事项的数据:

db.collection('todos').doc('todo-identifiant-aleatoire').get({success: function(res) {// res.data 包含该记录的数据console.log(res.data)}
})

2.1.2 通过collection.get获取所有记录的数据

  通过colletcion.get获取集合中的所有数据,或获取根据查询条件删选后的集合数据,其成功回调函数success的结果及Promise resolve的结果Result是一个数组对象,对应多条记录。

2.1.3 通过document.get获取某一条记录的数据

  通过document.get获取具体某一条记录的数据,或获取根据查询条件删选后的记录数据,其success回调的结果及Promise resolve结果Result是一个对象,对应一条记录。

  测试:通过云开发控制台创建集合db1,然后添加多条记录,记录的字段分别为name(string)、password(string)、age(number)、sex(string)、tel(string)。

  添加后的数据如下:

  修改集合数据的操作权限:

get.wxml:

<view class="doc" bindtap="docget">doc.get获取一条记录</view><view class="list-item" bindtap="testCgi"><text class="request-text">{{docget.name}}--{{docget.password}}--{{docget.age}}--{{docget.sex}}--{{docget.tel}}</text></view><view class="doc" bindtap="Collectionget">Collection.get 获取多条记录</view><view wx:for="{{Collectionget}}"><view class="list-item" bindtap="testCgi"><text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}</text></view></view>

get.js:

//index.js
const app = getApp()Page({data: {docget:{},Collectionget:[]},onLoad: function() {},docget:function(e){console.log('执行docget')var that=thisconst db = wx.cloud.database()db.collection('db1').doc('1ef3c513623c6c890cdeaa4d424a7a74').get({success: function (res) {console.log(res.data)that.setData({docget: res.data})}})},Collectionget:function(e){var that=thisconst db = wx.cloud.database()db.collection('db1').get({success: function (res) {console.log(res.data)that.setData({Collectionget: res.data})}})}
})

  代码讲解:docget函数通过document.get()接口获取具体某一条记录的数据。Collectionget函数通过collection.get()接口获取集合中的所有数据,注意两个方法获取的数据都在res.data中。

  实现效果:

2.1.4 通过collection.count获取集合记录数量

  通过collection.count统计集合记录数或统计查询语句对应的结果记录数,注意这与集合权限设置有关,一个用户仅能统计其有读权限的记录数。success回调的结果及Promise resolve的结果Result是一个number类型的对象total。

2.1.5 通过collection.where条件查询

  通过collection.where指定筛选条件,方法签名如下:

function where(rule:object):Query

  该方法接受一个必填对象参数rule,用于定义筛选条件,示例代码如下:

const db=wx.cloud.database()
db.collection('db1').where({
age:30          //查询年龄为30岁的记录
}).get({
success:console.log,
fail:console.error
})

2.1.6 通过collection.orderBy排序查询

  通过collection.orderBy指定查询排序条件,方法签名如下:

function orderBy(fieldName:string,order:string):collection|query

  该方法接受一个必填字符串参数fieldName用于定义需要排序的字段,一个字符串参数order用于定义排序顺序,只能取asc或desc。

  如果需要对嵌套字段排序,需要用"点表示法"连接嵌套字段,例如style.color表示字段style里的嵌套字段color。如果要按多个字段排序,多次调用orderBy即可,多字段排序时会按照orderBy调用顺序先后对多个字段排序。

  案例:

  where-orderby.wxml:

<view class="doc" bindtap="where">where查询男人记录</view><view wx:for="{{where}}"><view class="list-item" bindtap="testCgi"><text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}</text></view>
</view><view class="doc" bindtap="orderby">orderby按age升序排序</view><view wx:for="{{orderby}}"><view class="list-item" bindtap="testCgi"><text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}</text></view></view>

  where-orderby.js:

//index.js
const app = getApp()Page({data: {where: [],orderby:[]},onLoad: function() {},where:function(e){var that=thisconst db = wx.cloud.database()db.collection('db1').where({sex:"男" }).get({success: function (res) {console.log(res.data)that.setData({where: res.data})}})},orderby:function(e){var that=thisconst db = wx.cloud.database()db.collection('db1').orderBy('age', 'asc') .get({success: function (res) {console.log(res.data)that.setData({orderby: res.data})}})}
})

   代码讲解:请注意where和orderby操作应该在collection和get操作的中间,因为collection.get是获取集合中的所有记录,对所有记录排序和条件查询,where和orderby操作应在get之前。另外需要注意的是,get操作得到的数据是多条记录,应该赋值给一个数组。

2.1.7 通过collection.limit指定查询结果集数量上限

  通过collection.limit指定查询结果集数量上限

  limit 在小程序端默认及最大上限为 20,在云函数端默认及最大上限为 1000

  官网示例代码:

db.collection('todos').limit(10).get().then(console.log).catch(console.error)

2.1.8 通过collection.skip跳过若干条记录

  指定查询返回结果时从指定序列后的结果开始返回,常用于分页

  示例代码:

db.collection('todos').skip(10).get().then(console.log).catch(console.error)

2.1.9 通过collection.field指定返回字段

  指定返回结果中记录需返回的字段。

  示例代码:只返回 description, done 和 progress 三个字段:

db.collection('todos').field({description: true,done: true,progress: true,
}).get().then(console.log).catch(console.error)

  案例:

  field-limit-skip.wxml:

  <view class="doc" bindtap="field">field只显示name、age和tel字段</view><view wx:for="{{field}}"><view class="list-item" bindtap="testCgi"><text class="request-text">{{item.name}}--{{item.age}}--{{item.tel}}  </text></view></view><view class="doc" bindtap="limit">limit只要3条记录</view><view wx:for="{{limit}}"><view class="list-item" bindtap="testCgi"><text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}       </text></view>
</view><view class="doc" bindtap="skip">skip跳4条记录</view><view wx:for="{{skip}}"><view class="list-item" bindtap="testCgi"><text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}       </text></view></view>

  field-limit-skip.js:

Page({data: {limit:{},skip:[],field:[]},onLoad: function() {},limit:function(e){var that=thisconst db = wx.cloud.database()db.collection('db1').limit(3).get({   //限定获取记录的总条数success: function (res) {console.log(res.data)that.setData({limit: res.data})}})},skip:function(e){var that=thisconst db = wx.cloud.database()db.collection('db1').skip(4).get({    //跳过指定条数的记录success: function (res) {console.log(res.data)that.setData({skip: res.data})}}) },field: function (e) {var that = thisconst db = wx.cloud.database()db.collection('db1').field({ //只获取指定的字段name: true, age: true, tel: true}).get({success: function (res) {console.log(res.data)that.setData({field: res.data})}})}
})

   field操作只获取指定的字段,本例中只显示name、age和tel三个字段。limit操作限定获取记录的总条数。skip操作跳过指定条数的记录,常用于分页显示。这3种操作是对get操作的有效补充。

2.1.10 通过command查询指定

  原始的where条件查询只能查询“等于”的情况,当需要查询”大于“、”小于“、”大于或等于“、“与”等特殊条件查询的时候,where语句已经不能胜任,这是需要用db.command获取数据库查询指定。

API 说明
eq 等于指定值
neq 不等于指定值
lt 小于指定值
lte 小于或等于指定值
gt 大于指定值
gte 大于或等于指定值
in 在指定数组中
nin 不在指定数组中
and 条件与,表示需同时满足另一个条件
or 条件或,表示如果满足另一个条件也匹配

这里只列举了大概,更详细的请参考官网。

  案例:command.wxml

 <view class="doc" bindtap="lte">lte小于等于30岁的记录</view><view wx:for="{{lte}}"><view class="list-item" bindtap="testCgi"><text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}</text></view></view>
<view class="doc" bindtap="in">in在25和30岁的记录</view><view wx:for="{{in}}"><view class="list-item" bindtap="testCgi"><text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}       </text></view>
</view>

  command.js

Page({data: {lte:{},in:[]},onLoad: function() {},lte:function(e){var that=thisconst db = wx.cloud.database()const _ = db.commanddb.collection('db1').where({age: _.lte(30)}).get({success: function (res) {console.log(res.data)that.setData({lte: res.data})}})},in:function(e){var that=thisconst db = wx.cloud.database()const _ = db.commanddb.collection('db1').where({age: _.in([25, 30])}).get({success: function (res) {console.log(res.data)that.setData({in: res.data})}}) }
})

   in操作需要注意,age:_.in([25,30])是age等于25或者等于30的记录,不是25~30的记录

2.2 插入数据

  小程序提供了add方法向集合中插入一条记录,方法签名如下:

function add(options:object):Promise<Result>

  参数:

属性 类型 默认值 必填 说明
data Object 新增记录的定义

返回值:

属性 类型 说明
_id string/number 新增的记录 _id

  示例代码:

add.wxml:

 <view class="doc" bindtap="lte">插入之前大于等于30岁的记录</view><view wx:for="{{lte}}"><view class="list-item" bindtap="testCgi"><text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}</text></view></view>
<view class="doc" bindtap="add">add插入之后大于等于30岁的记录</view><view wx:for="{{add}}"><view class="list-item" bindtap="testCgi"><text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}       </text></view>
</view>

  add.js:

Page({data: {lte:{},add:[]},onLoad: function() {},lte:function(e){var that=thisconst db = wx.cloud.database()const _ = db.commanddb.collection('db1').where({age: _.gte(30)}).get({success: function (res) {console.log(res.data)that.setData({lte: res.data})}})},add:function(e){var that=thisconst db = wx.cloud.database()const _ = db.commanddb.collection('db1').add({data: {age: 60,name: "韩老师",password:"han",sex:"man",tel:"18888880002"},success: function (res) {  //插入成功之后查询console.log(res)db.collection('db1').where({age: _.gte(30)}).get({success: function (res) {console.log(res.data)that.setData({add: res.data})}})}}) }
})

  代码讲解:add操作会返回一个"_id",该值是成功插入的记录的id值,程序可以通过检查是否返回了“_id”来判断是否成功插入,若没有返回则说明插入失败。

2.3 更新数据

2.3.1 update更新

  使用update方法可以局部更新一个记录或一个集合中的记录,局部更新意味着只有指定的字段会得到更新,其他字段不受影响。

示例代码:

db.collection('todos').doc('todo-identifiant-aleatoire').update({// data 传入需要局部更新的数据data: {// 表示将 done 字段置为 truedone: true}
})
.then(console.log)
.catch(console.error)

2.3.2 set更新

  如果需要替换更新一条记录,可以再记录上使用set方法,替换更新意味着用传入的独享替换指定的记录。

示例:

update-set.wxml:

<view class="doc" bindtap="update1">韩老师记录update之前</view><view class="list-item" bindtap="testCgi"><text class="request-text">{{update1.name}}--{{update1.password}}--{{update1.age}}--{{update1.sex}}--{{update1.tel}}       </text>
</view><view class="doc" bindtap="update2">韩老师记录update之后</view><view class="list-item" bindtap="testCgi"><text class="request-text">{{update2.name}}--{{update2.password}}--{{update2.age}}--{{update2.sex}}--{{update2.tel}}       </text>
</view><view class="doc" bindtap="set1">李老师记录set之前</view><view class="list-item" bindtap="testCgi"><text class="request-text">{{set1.name}}--{{set1.password}}--{{set1.age}}--{{set1.sex}}--{{set1.tel}}       </text>
</view><view class="doc" bindtap="set2">李老师记录set之后</view><view class="list-item" bindtap="testCgi"><text class="request-text">{{set2.name}}--{{set2.password}}--{{set2.age}}--{{set2.sex}}--{{set2.tel}}       </text>
</view>

update-set.js:

Page({data: {update1:{},update2:{},set1:{},set2:{}},onLoad: function() {},update1:function(e){var that=this;const db = wx.cloud.database()db.collection('db1').doc('1ef3c513623c6c890cdeaa5142ca382e').get({success: function (res) {console.log(res.data)that.setData({update1: res.data})}})},update2: function (e) {var that = this;const db = wx.cloud.database()db.collection('db1').doc('1ef3c513623c6c890cdeaa5142ca382e').update({data: {age:44},success: function (res) {console.log(res.data)db.collection('db1').doc('1ef3c513623c6c890cdeaa5142ca382e').get({success: function (res) {console.log(res.data)that.setData({update2: res.data})}})}})},set1: function (e) {var that = this;const db = wx.cloud.database()db.collection('db1').doc('1ef3c513623c6c890cdeaa520b00a517').get({success: function (res) {console.log(res.data)that.setData({set1: res.data})}})},set2: function (e) {console.log(1)var that = this;const db = wx.cloud.database()db.collection('db1').doc('1ef3c513623c6c890cdeaa520b00a517').set({data: {age: 60,name:"李教授",password:"li",sex:"女",tel:"18888881111"},success: function (res) {console.log(res.data)db.collection('db1').doc('1ef3c513623c6c890cdeaa520b00a517').get({success: function (res) {console.log(res.data)that.setData({set2: res.data})}})},error:function(e){console.log(e)}})}
})

  注意,在update和set操作之后不可以接着就进行get操作,本例把get操作写在了update操作的success方法中。

2.4 删除数据

  小程序提供了remove方法来删除一条记录,示例代码如下:

db.collection('todos').doc('todo-identifiant-aleatoire').remove().then(console.log).catch(console.error)

  如果需要删除多条记录,需在Server端进行操作(云函数),并通过where语句选取多条记录进行删除,有权限删除的记录才会被删除。

  案例:

  remove.wxml:

<view class="doc" bindtap="remove2">服务器端删除赵老师记录</view><view class="list-item" bindtap="testCgi"><text class="request-text">{{remove2}}</text>
</view>

remove.js:

Page({data: {},onLoad: function() {},remove2: function (e) {wx.cloud.callFunction({name: 'remove',  // 云函数名称data: {// 传给云函数的参数name: "李老师"},success: function (res) {console.log(res)console.log("成功删除" + res.result.stats.removed + "条记录")},fail: console.error})}
})

  先去云数据库控制台查看下赵老师:

  执行代码之后:

  云数据库中的记录已经被删除了。

  这里只介绍了下常用的基本操作,更详细的介绍请查看微信开发者文档

微信小程序云数据库操作相关推荐

  1. 微信小程序云函数操作云数据库Mysql

    微信小程序云函数操作云数据库Mysql 参考一 参考二 云函数是一段运行在云端的代码,无需管理服务器,在开发工具内编写.一键上传部署即可运行后端代码. 小程序内提供了专门用于云函数调用的 API.开发 ...

  2. 微信小程序操作mysql_微信小程序:数据库操作

    原标题:微信小程序:数据库操作 一.前提条件: 登录开发者工具软件,配置数据库数据集,操作如下: 打开云开发控制台 添加集合User 二.定义函数: //增加新纪录到云数据库 onAdd: funct ...

  3. Web端访问微信小程序云数据库

    撰写背景: 用微信小程序云开发做了一个与web管理平台配套的微信小程序,Web端需要对接(访问)到云环境的云数据库. 开门见山: 在微信开发者工具里先把云开发控制台打开, 设置->权限设置-&g ...

  4. 微信小程序云数据库定时清空(云函数定时触发)

    需求: 微信小程序云数据库某表仅保留当天数据,因此每天固定某时间清空一次 实现: 1.新建云函数timer 2.在timer/config.json中配置定时器 {"triggers&quo ...

  5. 微信小程序云数据库where查询语句字段名和字段值都可以是变量

    微信小程序云数据库where查询语句字段名和字段值都可以是变量 想要实现的功能 遇到的问题 js代码 想要实现的功能 界面代码 // An highlighted block <view cla ...

  6. 外部web端访问微信小程序云数据库的几种方法

    前言 我当前的项目是小程序开发,使用的是云开发方式,那么这时涉及到了小程序端提交的数据会保存到云数据库中,可是呢这些个数据要被外部访问用来管理,也就是还得弄一个管理后台界面管理这些数据.那就需要拿到云 ...

  7. 记一次微信小程序云函数操作Mysql数据库

    一.前因 在制作课程设计的时候需简单地操作Mysql数据库使得小程序可以与其他端系统进行数据交互 这时候问题来了,仅仅只是因为一个插入表的数据库操作就单独制作一个Servlet看似又有点浪费服务器资源 ...

  8. web端获取微信小程序云数据库数据实现增删改查等操作

    获取小程序数据库 前言 一.微信小程序Web SDK 1.微信官方示例 2.未登录模式注意事项 二.完整流程演示 1.开启云数据库访问权限 2.编写云函数 3.web前端引入js 4.web页面js访 ...

  9. 微信小程序——云函数操作数据库实现登录

    在开发微信小程序时,使用传统的操作云数据库的方法有很多缺点,比如代码冗余不好维护修改,所以现在都是基于云函数来操作数据库或者其他逻辑.正好我在做一个集合商城.垃圾分类.后台系统的微信小程序模板,通过这 ...

  10. 微信小程序云开发操作全解

    云开发三大基础能力 云函数:运行在微信服务器上的函数,处理微信相关操作有天然优势,如获得用户信息异常方便(以前服务端解析很麻烦) 数据库:一个小程序可以直接操作的JSON数据库,可以直接操作数据库,不 ...

最新文章

  1. Windows下创建进程简介
  2. IDApython 命令
  3. 安卓初学者必看实例,(手机GPS简单编程访问)
  4. Go语言 命令行解析(二)
  5. .NETCore3.1中的Json互操作最全解读-收藏级
  6. php文件里搜索关键字,php - PHP从文本文件中搜索关键字(Action'),使用该关键字打印所有行,然后计算打印的行数 - SO中文参考 - www.soinside.com...
  7. 【Spring学习】01
  8. LeetCode 15. 三数之和(3Sum)
  9. day03 Python爬虫
  10. M1 MacBook Air值不值得买?使用体验分享
  11. Rust : 如何将C字符串转换为Rust字符串并通过FFI返回?
  12. Eclipse阿里云镜像源配置
  13. 如何解决同花顺软件打开时,出现 “无法与服务器建立连接” 的问题
  14. Nanohttpd 异常 Explicit termination medthod 'end' not called 解决方法
  15. 制作u盘winpe启动盘_U启大师U盘启动盘制作教程(装机版)
  16. python视频字幕处理_用Python处理字幕文件
  17. 大数据技术之_16_Scala学习_11_客户信息管理系统+并发编程模型 Akka+Akka 网络编程-小黄鸡客服案例+Akka 网络编程-Spark Master Worker 进程通讯项目
  18. ug二次开发环境配置
  19. 数据分析 第二章 1.数据清洗及特征处理
  20. 计算机综合症怎么治,小窍门防治电脑综合征

热门文章

  1. MSI Center局域网管理器开启导致电脑网络质量变差、网速低
  2. Go语言环境安装及配置
  3. 【文化课每周学习记录】2019.4.7——2019.4.13
  4. (C++)统计字符_给定一个英文字符串,请写一段代码找出这个字符串中首先出现三次的那个英文字符
  5. 一次基于Vue的Vedio.js使用
  6. 为什么我们要用密码生成器?
  7. 可调稳压电源lm317实验报告_LM317可调稳压电源电路图
  8. 外贸人写开发信会犯的错误,你中了哪几个
  9. java代码对图片缩放
  10. 【Mybatis学习路线】day01Mybatis概述