uniCloud 云开发笔记

一、基本介绍
use strict

在JS中,'use strict'特殊的字符串字面量,通知JS引擎以“严格模式”执行代码。避免一些常见的错误和不安全的实践。建议在云函数的代码中使用'use strict'来启用严格模式。

二、云函数
基础使用
const db = uniCloud.database()
exports.main = async (event, context) => {
	...
}
uniCloud.callFunction({
    name : "云对象文件夹名",
    data,
}).then(res=>{
	...
})
添加云函数
const db = uniCloud.database()
exports.main = async (event, context) => {
	db.collection('user').add({
        joinTime: new Date(),
        ...event
    })
}
uniCloud.callFunction({
    name : "cloudFun1",
    data:{num: 2}
}).then(res=>{
	...
})
删除云函数
注意:删除、set等操作,一定要写好条件,在做相关功能阶段可以备份好数据库
const db = uniCloud.database()
exports.main = async (event, context) => {
	let {id} = event
	return await db.collection("article").doc(id).remove()
}
修改云函数
注:某种情况下也可使用【添加云函数】进行覆盖,来达到修改的目的
db.collection( "xxx" ).doc(xxx).update({
	...data
})
获取列表数据云函数
  • 限制数据条数(条数、页数、拼接、加载、刷新)
  • 开始,根据后端固定的条数,刷新后,后端获取数据为,忽略前端已有数据条数之后的固定条数
前端:
	listArr:[]
	
	uniCloud.callFunction({
        name: "xxx",
        data:{ skip:this.listArr.length }
    }).then( res=> {
        let oldList = this.listArr;
        let newList=[ ...oldList, ...res.result.data];
        this.listArr= newList
    })


后端:
	let { skip=0 } = e
	db.collection( "xxx" ).limit(10).skip(skip).get();
三、云对象

相对云函数更加简洁

使用场景

云函数是一种在云端运行的 JS函数,可以执行一些特定的业务逻辑

云对象是一种数据存储服务,类似于数据库中的一张表,可以存储结构化的数据

  • 云函数主要用于执行一些特定的业务逻辑,比如处理用户请求、调用第三方 API、生成临时文件等。由于其运行在云端,可以避免在客户端进行敏感操作或数据存储,保证了数据的安全性和隐私性
  • 云对象主要用于存储和查询结构化的数据,类似于数据库中的一张表。你可以使用云对象来存储用户信息、订单数据、商品信息等,并通过定义的字段进行查询、更新和删除等操作

进行数据处理和存储,云对象合适;执行一些特定的业务逻辑,云函数合适

基础使用
  • 定义
const db = uniCloud.database();
module.exports = {
	// 通用预处理器,默认即可
	_before : function (){ ... },
	
	// 自定义方法
    async get(){
    	return await db.collection("数据表名").limit(num).get();
    },
    
    add: async()=>{
    	return await db.collection("数据表名").add(params).get();
    }
}
  • 使用
// vue顶部引入
const cloudObjFun = uniCloud.importObject("云对象文件夹名")

// 使用
cloudObjFun.get(2).then(res=>{ ... })
cloudObjFun.add({userId:'01'}).then(res=>{ ... })
浏览量自增封装

由于前端数据库组件不能使用【inc】方法,所以采用云对象的方式来做

const db = uniCloud.database();
const dbCmd = db.command;
module.exports = {
	// 通用预处理器
    _before: function (){},
    
    /**
     *自定义增减
     *@param {Object] table 数据表
     *@param {object} attr  属性
     *@param {object} id
     *@param {object] num   自增减数
     */
    async operation(table, attr, id, num){
    	let obj = {}
    	obj[attr] = dbCmd.inc(num);
    	return await db.collection(table).doc(id).update(obj)
    }
}
四、DB Schema

介绍:在客户端前端代码直接操作数据库

使用:在uniCloud-database下新建【xxx.schema.json】文件,或者从云端下载同步到本地。之后修改代码以获取对应的权限,在本地编辑测试完之后,同步到云端

{
	"bsonType" : "object",
	// 必填项
	"required": ["title"],
	// 权限
	"permission": {
		// 开启【读】权限
		"read" : true,
		"create": false,
		"update": false,
		"delete": false
	},
	// 表结构
	"properties": { 
		"_id": { "description":“ID,系统自动生成" },
		// 自定义属性名
		"title": { 
        	"bsonType" : "stying",
        	"title" : "标题",
        	"drscription" : "描述",
        	"errorMessage" : "错误提示"
        },
		"createTime" : {...},
		...
	}
}
const db = uniCloud.database()

export default{
	onload(){
		db.collection("数据表名").get.then(res=>{ ... })
	}
}
表关联关系

uniCloud–database下【自定义表】的用户id关联【uni-id-user】表的用户id

xxx.schame.json

{
	...
	"propertise":{
        "userid" :{
            "bsonType" : "string",
            "title":“用户id",
            "foreignKey" : "uni-id-users._id" ,
            "defaultValue" :{
                "$env" : "uid"
            }
        },
	}
}
权限限制

未登录的用户不能创建信息

auth.uid为官方提供的【当前登录用户的id】

{
	...
	"permission" : {
        "read" : true,
        "create" : "auth.uid != null",			// 判断用户是否登录
        "update": "doc.userid == auth.uid",		// 判断所修改数据的用户id是否是当前用户的id
        "delete" : false
    },
}
五、JQL语法
  • sql:有学习成本

    select * from table1 where field1="value1"
    
  • nosql:连表查询比sql还要复杂

    const db = uniCloud.database()
    let res = await db.collection('table').where({
    	field1 : value1
    }).get(0)
    
  • jql:更加贴近js写法、学习成本低、代码简短

连表查询

前提:建立枢纽、开启权限(看DB Schame案例)

let artTemp=db.collection ( "cloudDemo").field("title, content , userid").getTemp()
let userTemp=db.collection("uni-id-users").field("_id,username,nickname" ).getTemp()

db.collection(artTemp, userTemp).get().then(res=>{
	console.log(res);
})
前端组件方式

连表查询:collection=“主表,副表”

过滤写法1【语法简介】:field=“posttime,userid{avatar}”,主表posttime,userid,副表avatar

过滤写法2【官方推荐】:field=“posttime,userid.avatar”

排序:orderby=“posttime desc, userid desc”,根据时间排序,时间一样则根据id排序

<unicloud-db 
	v-slot:default= "{data, loading, error, options}"
	collection="cloudDemo, uni-id-users"
	field="posttime,userid{avatar}"
	orderby="posttime desc, userid desc"
>
	<view v-if="error ">{error.message}}</view>
	<view v-else-if="loading"><uni-load-more status="loading"></uni-load-more></view>
	<view v-else>
		<uni-list>
			<uni-list-item 
				v-for="item in data"
				:thumb="item.avatar"
			></uni-list-item>
		</ uni-list>
	</view>
</ unicloud-db>

####五 、云数据库

六、云存储

阿里云:

七、打包
  • 本地云函数上传
  • 进入manifest.json修改对应的配置
  1. H5打包

    • manifest.json

      • 标题(自填)
      • 路由模式【hash(默认)、history(需要另外配置)】
      • 运行的基础路径【./】
    • 发行:网站PC

      • 网站标题(自填)
      • 域名(默认空)
      • 打包完成:unpackage/dist/build/h5
    • 获取域名:https://unicloud.dcloud.net.cn

      • 前端页面托管
      • 文件管理–上传到当前目录–上传文件夹(含根目录)
      • 参数配置–默认域名
      • 跨域配置–添加域名
    • 跨域:https://unicloud.dcloud.net.cn

      • 跨域配置–添加域名
    • 域名丑

      • 配置自己的域名
        • 阿里云等购买主机域名(chenjigang.com)
        • https://unicloud.dcloud.net.cn
        • 前端网页托管–参数配置–配置网站域名
          • 域名:自定义二级域名.购买的域名【https://xxx.chenjigang.com】
          • CNAME:复制到阿里云
          • 阿里云:
            • 域名控制台–域名列表–解析–解析设置–添加记录
              • 主机记录:自定义二级域名
              • 记录值:填写unicloud的CNAME
        • 配置跨域
      • 域名转二维码
      • 百度短连接
    • vscode本地运行

      • 安装【Live Serve】插件

      • 运行index.html

  2. 微信小程序打包

    • manifest.json
      • 小程序管理后台:https://mp.weixin.qq.com/wxamp/devprofile/get_profile
      • 开发–开发管理–开发设置–获取AppID填写到 manifest.json
    • 点击发行:微信小程序
      • 填写项目名称和AppID
      • 点击发行
      • 打包完成:unpackage/dist/dev/mp-weixin
    • 微信开发者工具
      • 本地设置
        • 关闭不校验合法语名
        • 根据报错提示,复制不合法域名以及类型(request、socket等)
        • 小程序管理后台:https://mp.weixin.qq.com/wxamp/devprofile/get_profile
        • 开发–开发管理–服务器域名–合法域名–多个域名用【;】分隔
  3. app

    • manifest.json
      • 上传图标
      • 自动生成图标并替换
    • 点击发行:App云打包(较简单)
      • 使用云端证书
      • 点击打包
      • 打包完成:unpackage/release/apk
八、常用方法
触底加载

触底方法:【scroll-view】标签的触底、页面触底等

技巧:通过过滤前端已有的数组长度

uniCloud.cal1Function({
	name : "getData",
	data:{
		skip: this.listArr.length
	}
}).then(res=>{
	this.listArr = [...this.listArr, ...res.result.data]
})

limit:请求条数,skip:过滤条数,orderBy:排序

const db=uniCloud.database();
exports.main = async (event, context) =>{
	let { skip=0 } = event;
	return await db.collection ("article")
		.limit(8)		
		.skip(skip)
		.orderBy("posttime", "desc")
		.get();
};
下来刷新

列表清空、重新获取

事件委托

原生的 JavaScript 来实现事件委托。允许你将事件监听器添加到父元素,而不是分别添加到每个子元素。当事件在子元素上触发时,事件会冒泡到父元素,通过检查事件的 target 属性来确定是哪个子元素触发了事件

<template>  
  <div @click="handleClick">  
    <button data-action="action1">Action 1</button>  
    <button data-action="action2">Action 2</button>
  </div>  
</template>  
  
<script>  
export default {  
  methods: {  
    handleClick(e) {  
      const target = e.target;  
      if (target.tagName === 'BUTTON') {  
        const action = target.dataset.action;  
        this[action]();  
      }  
    },  
    action1() { console.log(1) },  
    action2() { console.log(2) } 
  },  
};  
</script>
高德获取定位封装:获取省市位置信息

官网:https://lbs.amap.com/api/webservice/summar

export function getprovince(){
	return new Promise((resolve,reject)=>{
		uni.request({
			url: "https://restapi.amap.com/v3/ip?key=xxx",
			success: res=>{ resolve(res.data.province) },
			fail: err=>{ reject(err) }
		})
	})
}
九、问题解决
Invalid uni-id config file

官网:https://doc.dcloud.net.cn/uniCloud/uni-id/summary.html#config

缺少uni-id-pages的配置文件【config.json】,在uniCloud中手动创建相关路径和文件

uni-id的云端配置文件在:uniCloud/cloudfunctions/ common/uni-config-center/uni-id/config.json

{
  "passwordSecret": [
    {
      "type": "hmac-sha256",
      "version": 1
    }
  ], 
  "passwordStrength": "medium",
  "tokenSecret": "",
  "requestAuthSecret": "", 
  "tokenExpiresIn": 7200,
  "tokenExpiresThreshold": 3600,
  "maxTokenLength": 10,
  "passwordErrorLimit": 6,
  "passwordErrorRetryTime": 3600,
  "autoSetInviteCode": false,
  "forceInviteCode": false,
  "idCardCertifyLimit": 1,
  "realNameCertifyLimit": 5,
  "sensitiveInfoEncryptSecret": "",
  "frvNeedAlivePhoto": false,
  "userRegisterDefaultRole": [],
  "app": { 
    "tokenExpiresIn": 2592000,
    "tokenExpiresThreshold": 864000,
    "oauth": {
      "weixin": {
        "appid": "",
        "appsecret": ""
      },
      "qq": {
        "appid": "",
        "appsecret": ""
      },
      "apple": {
        "bundleId": ""
      }
    }
  },
  "web": {
    "tokenExpiresIn": 7200,
    "tokenExpiresThreshold": 3600,
    "oauth": {
      "weixin-h5": {
        "appid": "",
        "appsecret": ""
      },
      "weixin-web": {
        "appid": "",
        "appsecret": ""
      }
    }
  },
  "mp-weixin": {
    "tokenExpiresIn": 259200,
    "tokenExpiresThreshold": 86400,
    "oauth": {
      "weixin": {
        "appid": "",
        "appsecret": ""
      }
    }
  },
  "mp-qq": {
    "tokenExpiresIn": 259200,
    "tokenExpiresThreshold": 86400,
    "oauth": {
      "qq": {
        "appid": "",
        "appsecret": ""
      }
    }
  },
  "mp-alipay": {
    "tokenExpiresIn": 259200,
    "tokenExpiresThreshold": 86400,
    "oauth": {
      "alipay": {
        "appid": "",
        "privateKey": "",
        "keyType": "PKCS8"
      }
    }
  },
  "service": {
    "sms": {
      "name": "",
      "codeExpiresIn": 180,
      "smsKey": "",
      "smsSecret": "",
      "scene": {
        "bind-mobile-by-sms": {
          "templateId": "",
          "codeExpiresIn": 240
        }
      }
    },
    "univerify": {
      "appid": "",
      "apiKey": "",
      "apiSecret": ""
    }
  }
}
十、其他信息
  • 项目上线,使用本地云函数调试即可。使用远程的话,其他用户可能会出现问题,待测试完,再上传到远端

  • 通过【for…in】遍历对象的属性,【obj[key]】访问对象属性的值,来判断按钮的禁用状态

  • 日期格式化:采用uni扩展组件【uni-dateformat】

  • 做数据处理的时候,避免乐观形式,要做好各种数据状态的处理

  • 封装常用提示、跳转等

  • 阿里图标库一个项目尽量使用同一人分享的,这样大小会相对统一一些

  • 选择性的做二次校验(比较敏感的属性)

  • UView有富文本解析器组件

  • 阿里iconfont的Font class使用,需要将相对引用改为绝对引用

  • uniapp使用uView

    • 插件市场下载

    • main.js中引入

      import uView from '@/uni_modules/uview-ui'
      Vue.use(uView)
      
    • App.vue中引入

      @import "@/uni_modules/uni-scss/index.scss";
      
    • uni.sass中引入

      @import '@/uni_modules/uview-ui/theme.scss';
      
  • 父子传值-自定义事件-简写【.syan】

    // 父组件
    <child :data.syan="data"></child>
    
    // 子组件
    <view @click="change">{{data}}</view>
    
    props:{
    	data:{
    		default:'',
    		type:String
    	}
    }
    methods:{
        change(){
        	this.$emit('update:data',"uni-app")
        }
    }
    
  • 父组件点击子组件事件【.native】

    引入的子组件,原生绑定的事件不能使用,需要添加【.native】

    //父组件
    <componentA @click.native="change"></componentA>
    
  • 页面跳转查看详情

    • 方式一:传id【item.id】

      item不含所有内容

    • 方式二:传JSON字符串【JSON.string(item)】

      item含有跳转页面所有内容,并且内容不能太多【内容过多可能会传递失败】

    • 方式三:缓存

      退出时记得清缓存

  • Vue2在模板中使用导入的方法

    类似于组件注册

    {{giveName(item)}}
    
    import {giveName} from'xxx'
    methods:{
    	giveName
    }
    
  • CSS根据头像设置专属背景

    filter: blur(20px)		// 模糊
    transform: scale(2)		// 放大
    opacity: 0.5			// 透明
    
  • JS新语法【?.】和【??】,【??】和【||】

    const obj = { a: 1 }
    
    访问【obj.b】会返回undefined,访问【obj.b.c】会报错
    使用【obj.b?.c】会判断【b】是否存在,存在则访问c
    使用【obj.b ?? 'default'】会判断【b】是否为【null】【undefined】,是的话使用一个值替代【obj.b】
    相比较【obj.b && obj.b.c】简洁很多
    
    【??】:当变量的值为 null 或 undefined ,为变量提供一个默认值
    【||】:当变量的值为“falsy”(例如 0, '', NaN, false),为变量提供一个默认值。
    		const value = 0 || 'default'; 这里 value 会是 'default',即使 0 是一个有效的数值。
    
  • 在uniapp中存在CSS变量,提供了系统状态栏高度

    官网:http://uniapp.dcloud.net.cn/tutorial/syntax-css.html

    • –status-bar-height :系统状态栏高度

    • –window-top:内容区域距离顶部的距离

    • –window-bottom:内容区域距离底部的距离(tabbar)

      padding-top: var( --status-bar-height)
      min-height: calc(100vh - var( --window-top))
      padding-top: var(--window-bottom)
      
  • vue阻止【事件冒泡stop】+【事件捕获prevent】

    <button @click.stop.prevent>
    
  • white-space: nowrap(不换行)

    .text-overflow {  
        white-space: nowrap; 		/* 防止文本换行 */  
        overflow: hidden;     		/* 隐藏溢出部分 */  
        text-overflow: ellipsis; 	/* 当文本溢出时,显示省略号 */  
        width: 200px;           	/* 设置一个固定宽度 */  
    }
    
    .container {  
        display: -webkit-box;  
        -webkit-line-clamp: 2;  
        -webkit-box-orient: vertical;  
        overflow: hidden;  
    }
    
  • 前后端要规定好时间日期等格式

    • 获取日期:xxxx-xx-xx
    // 它生成的日期字符串是基于 UTC 时间的,可能与本地时间不同
    new Date().toISOString().slice(0, 10)
    
    // 通用
    let today = new Date();
    let year = today.getFullYear();
    let month = (today.getMonth() + 1).toString().padStart(2, "0");
    let day = today.getDate().toString().padStart(2, "0");
    
    let formattedDate = `${year}-${month}-${day}`;
    
    • 获取当前时间戳:1702430065563
    // ECMAScript 5 引入的新方法,不兼容旧版本的浏览器(例如 IE8 及更早版本)。
    const timestamp = new Date().getTime();	
    
    // Date 对象的标准方法,支持在所有符合 ECMAScript 标准的 JavaScript 环境中使用
    const timestamp = Date.now();
    
    • 日期格式【nnnn-yy-rr】转时间戳
    let dateStr = "2023-08-01";
    let parts = dateStr.split("-");
    let date = new Date(parts[0], parts[1] - 1, parts[2]);
    let timestamp = date.getTime();
    
  • app端不支持【for… in】语法,some只要一个满足则返回true,every全部满足则返回true

    //判断按钮是否禁用
    inDisabled(obj){
        /*
            for(let key in obj){
                if( !obj[key] ){
                    return true;
                }
            }
        */
    	    
        let bool = Object.keys(obj).some((key, value)=>{
        	return obj[key] == ''
        })
        return bool;
    }
    
  • 数据顺序

    后端:通过数据库方法:db.collection( "xxx" ).orderBy("time","desc").get();
    
    前端:1、改变原数组:array.reverse();
    	 2、不改变原数组: array.slice().reverse();
    
  • 图片上传

    • uni-file-picker组件,开启手动上传【auto-upload】,避免云存储无效占;回显:

      imgValueList = [
      	{
      		"name":"file.txt",
      		"extname":"txt",
      		"url":"https://xxxx...",
      		// ...
      	},
      	...
      ]
      
      
      <uni-file-picker
          :value="imgValueList"
      ></uni-file-picker>
      
    • 手写上传组件

      // 用到的api
      uni.chooseImage()   	// 上传临时路径
      uni.previewImage()  	// 预览
      uniCloud.uploadFile()	// 上传云存储
      
      // 点击上传
      goUpload(){
          let newsArr = this.temFiles.map( async item =>{
          	return await this.uploadFun(item)
          })
          Promise.all(newsArr).then( res =>{
          	let arr = res.map( item =>{
         	 		return item.fileID
         	 	})
              this.picArr = arr;
      	})
      },
      
      uploadFun(item){
          return uniCloud.uploadFile({
              filePath:item.path,
              cloudPath:item.name
      	})
      }
      
  • uni-app和Vue的生命周期可以按照以下方式分类和排序:

    一、uni-app的生命周期

    1. 应用生命周期:
      • onLaunch:应用启动时触发,用于执行应用启动时的初始化操作。
      • onShow:应用显示时触发,用于执行应用显示时的操作。
      • onHide:应用隐藏时触发,用于执行应用隐藏时的操作。
      • onError:应用发生错误时触发,用于处理应用错误。
    2. 页面生命周期:
      • onLoad:页面加载时触发,用于执行页面加载时的初始化操作。
      • onShow:页面显示时触发,用于执行页面显示时的操作。
      • onHide:页面隐藏时触发,用于执行页面隐藏时的操作。
      • onReady:页面初次渲染完成时触发,用于执行页面初次渲染完成时的操作。

    二、Vue的生命周期

    1. 创建阶段:
      • beforeCreate:实例化前,未创建 data 和 methods 之前。
      • created:实例化后,已创建 data 和 methods。
    2. 挂载阶段:
      • beforeMount:模板编译成虚拟 DOM 之前。
      • mounted:模板编译成虚拟 DOM 之后,已挂载到真实 DOM 上。
    3. 更新阶段:
      • beforeUpdate:数据更新前。
      • updated:数据更新后。
    4. 销毁阶段:
      • beforeDestroy:实例销毁之前。
      • destroyed:实例销毁之后。

    综合uni-app和Vue的生命周期,按照先后顺序,可以排列如下:

    1. onLaunch:应用启动时触发,执行应用启动时的初始化操作。

    2. beforeCreate:实例化前,未创建 data 和 methods 之前。

    3. created:实例化后,已创建 data 和 methods。

    4. beforeMount:模板编译成虚拟 DOM 之前。

    5. mounted:模板编译成虚拟 DOM 之后,已挂载到真实 DOM 上。

    6. onLoad:页面加载时触发,执行页面加载时的初始化操作。

    7. beforeUpdate:数据更新前。

    8. updated:数据更新后。

    9. onShow:页面显示时触发,执行页面显示时的操作。

    10. onHide:页面隐藏时触发,执行页面隐藏时的操作。

    11. onReady:页面初次渲染完成时触发,执行页面初次渲染完成时的操作。

    12. beforeDestroy:实例销毁之前。

    13. destroyed:实例销毁之后。

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值