使用 uni-app 和 uniCloud 云开发跨全端开发简单实践
发布于 3 年前 作者 fanglin 2980 次浏览 来自 分享

本文主要讲解如何使用 uni-appuniCloud 云开发,实现唐诗300首列表和详情,不需要后端,跨全端开发。

什么是 uni-app

uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOSAndroidWeb(响应式)、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉/淘宝)、快应用等多个平台。

什么是 uniCloud

uniCloudDCloud 联合阿里云、腾讯云,为开发者提供的基于 serverless 模式和 js 编程的云开发平台。

uniCloud 的价值

  • 对于程序员,从此你又get一个新技能,用熟悉的js,轻松搞定前后台整体业务。

  • 对于开发商:

    1. 开发成本大幅下降。不用再雇佣php或java等服务器工程师,每年至少节省几十万;
    2. 你只需专注于你的业务,其他什么服务器运维、弹性扩容、防DDoS攻击,全都不需要操心;
    3. 如果不发布H5版,你将不需要购买备案域名。小程序和App可以免域名使用服务器;
    4. 对于敏捷性业务,前后端分离的沟通成本实在没有必要。可以考虑按业务负责分工,而不是按前后台分工。

准备工作

创建服务空间

  • 这里我选择阿里云,因为阿里云免费并且可以创建多个,名字按规则和需求起一个。我这里起名叫 miniserver

  • 创建好之后,这里可以看到

  • 点击详情,进入云空间,创建数据库

  • 这里表名,按规则和需求起一个,在创建的时候,不能自定义表结构,只能选模板里面的。

  • 在创建好后,可以选中刚刚创建的数据表,选择表结构,点击编辑,就可以修改表结构了.

{
  "schema": {
    "bsonType": "object",
    "required": [
      "title",
      "text",
      "author"
    ],
    "properties": {
      "_id": {
        "description": "存储文档 ID(文章 ID),系统自动生成"
      },
      "title": {
        "bsonType": "string",
        "description": "标题"
      },
      "text": {
        "bsonType": "string",
        "description": "正文"
      },
      "author": {
        "bsonType": "string",
        "description": "作者"
      },
      "translation": {
        "bsonType": "string",
        "description": "译文"
      },
      "appreciation": {
        "bsonType": "string",
        "description": "赏析"
      }
    }
  },
  "data": [],
  "index": []
}
  • 到此云数据库就创建好了,下面来使用云数据库和云函数

新建项目和关联云空间

  • 首先,在 HBuilderX 创建一个项目,这里起名为 tangshi,项目类型要选 uni-app,启用 uniCloud 选择你刚刚创建云空间时选的服务商,这里选阿里云。

  • 选择你刚刚创建的云空间,下一步,然后再点完成,项目就创建好了

  • 项目目录,如下

使用云数据库

  • 创建云函数 cloudfunctions 目录,只有创建了这个目录之后,才能创建云函数,创建完目录,需要右击项目名称,选择刷新,才能看到。官方云函数文档:https://uniapp.dcloud.net.cn/uniCloud/cf-functions

  • 右击 cloudfunctions,在菜单中选择新建云函数

  • 然后编写代码如下:
'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
  //event为客户端上传的参数
  const collection = db.collection('tangshi') // 获取表'tangshi'的集合对象
  const res = await collection.limit(event.limit).skip(event.offset).where({
    title: new RegExp(event.keyWord)
  }).get() // 获取表中的10条数据,结果为json格式
  return res // 返回json给客户端
};
  • 运行云函数时配置运行测试参数 - 在云函数的上传运行菜单或右键菜单中,有配置运行测试参数的功能。
// 本文件中的json内容将在云函数【运行】时作为参数传给云函数。
// 配置教程参考:https://uniapp.dcloud.net.cn/uniCloud/quickstart?id=runparam
{
  "limit": 20,
  "offset": 10,
  "keyWord": ""
}
  • 在云函数目录右键运行云函数,也可以在云函数编辑器里,按 Ctrl+r 运行快捷键,或点工具栏的运行

  • 此时云函数运行会携带所配置的运行参数

列表页

<template>
  <view class="content" v-if="!loading">
    <view class="ts-search">
      <input class="ts-search__input" placeholder="请输入诗名" @input="fuzzyQuery" />
    </view>
    <view class="ts-list" v-for="item in data" :key="item._id" @click="read(item._id)">
      <view class="ts-title">
         <text class="ts-name">{{item.title.split('/')[0]}}</text>
         <text class="ts-dynasty">[{{item.dynasty}}]</text>
         <text class="ts-author">{{item.author}}</text>
      </view>
      <view class="ts-desc">{{ item.text.split('\n')[0] }}</view>
    </view>
  </view>
</template>
<script>
let data = []
export default {
  data() {
    return {
      data: [],
      loading: false
    }
  },
  onLoad() {
    this.list()
  },
  methods: {
    list(e) {
      this.loading = true
      uni.showLoading({
          title: '加载中'
      });
      uniCloud
        .callFunction({
          name: 'list',
          data: {
            limit: 300,
            offset: 0,
            keyWord: e ? e.detail.value : ''
          }
        })
        .then(res => {
          // console.log(res.result.data, 0)
          data = res.result.data
          this.data = res.result.data
          uni.hideLoading();
          this.loading = false
        })
    },
    /**
     * 使用test方法实现模糊查询
     */
    fuzzyQuery(e) {
      const reg = new RegExp(e.detail.value)
      const arr = []
      for (let i = 0; i < data.length; i++) {
        if (reg.test(data[i].title)) {
          arr.push(data[i])
        }
      }
      // console.log(arr)
      this.data = arr
    },
    read(id) {
      uni.navigateTo({
        url: `/pages/read/index?id=${id}`
      })
    }
  }
}
</script>
<style lang="scss" scoped>
@import 'style.scss';
</style>
  • 效果如下

详情页

<template>
  <view class="content" v-if="!loading">
    <view class="ts-title">{{ detail.title }}</view>
    <view class="ts-author">[{{ detail.dynasty }}] {{ detail.author }}</view>
    <view class="ts-content" v-for="item in (detail.text || '').split('\n')" :key="item">{{ item }}</view>
    <view class="ts-subtitle" v-if="detail.translation">译文</view>
    <view class="ts-desc" v-if="detail.translation">{{ detail.translation }}</view>
    <view class="ts-subtitle" v-if="detail.appreciation">赏析</view>
    <view class="ts-desc" v-if="detail.appreciation">{{ detail.appreciation }}</view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      detail: {},
      loading: false
    }
  },
  onLoad(option) {
    this.read(option.id || '5f64c4cca2a89f21dbd4fd66')
  },
  methods: {
    read(id) {
      this.loading = true
      uni.showLoading({
          title: '加载中'
      });
      uniCloud
        .callFunction({
          name: 'read',
          data: { id }
        })
        .then(res => {
          // console.log(res.result.data[0], 1)
          this.detail = res.result.data[0] || {}
          uni.setNavigationBarTitle({
            title: `${this.detail.title} - 作者${this.detail.author}`
          })
          this.loading = false
          uni.hideLoading();
        })
    }
  }
}
</script>

<style lang="scss" scoped>
@import 'style.scss';
</style>

  • 效果如下

运行和发布

总结

回到顶部