草庐IT

飞书小程序开发经验

tenerSainter 2023-11-01 原文

飞书小程序开发经验总结

前序

最近一段时间,由于工作需要,我先在微信小程序开发平台上开发了一套程序,但是由于微信小程序不能保证整体的数据流都封闭在内网里,因而决定转战飞书小程序,将整体的功能都迁移至飞书小程序里。但是飞书小程序的开源博客比较少,所以在最开始上手的过程中还是比较痛苦的,现在小程序整体开发已经接近尾声,特此总结一下最近开发飞书小程序积累下的经验与流程。

开放文档与平台

飞书小程序提供了很多原生的API与服务端支持功能,都可以极大的丰富小程序的能力,因此多参考文档,对于程序的设计与开发都会有很大的帮助(主要还是因为飞书小程序的开源社区不太丰富,很多功能没有什么博客介绍用法)

飞书小程序开发文档:
https://open.feishu.cn/document/uYjL24iN/uUDNzUjL1QzM14SN0MTN
飞书开发者工具:

微信小程序 vs 飞书小程序

微信小程序在很多的场景下与飞书小程序的语法格式都是一致的,如果遇到不确定的语法,可以直接参考微信小程序的语法,如果实在不行再去看飞书开发者文档。

一键迁移微信小程序


打开飞书开发者工具,可见右上角部分存在按钮 搬家工具 ,点击搬家工具即可将微信小程序直接迁移至飞书小程序中,该工具可以自动将大部分的微信小程序语法替换为飞书小程序语法,但是不能保证转换结果 绝对正确 ,还是有可能会存在一些语法不正确的情况存在,此时还是需要我们自行调试程序,保证程序的可用性。
更多详细的搬家工具使用方式还请参考:
搬家工具介绍文档

搬家工具使用后遗症

使用完搬家工具后不意味着可以立即进入开发调试阶段,此时我们还需要面对另外一个问题——微信小程序与飞书小程序技术支持的差异。
首先, 我们需要注意修改project.config.json文件中的appid,我们迁移程序后,appid并不会直接帮我们改好。
// 开发者后台中创建应用后即可看到appid : 开发者后台链接
之后,如果我们曾经在微信小程序中使用了云函数与云数据库的话,那么我们可能就会遇到麻烦了,因为飞书小程序更加的轻量化,其并不支持云函数与云数据库。此时对于数据的存储我们可以寻求另一个解决方案——多维表格。关于多维表格的使用,我会在下面介绍。

页面展示与page的坑

一个一个的页面(page)组成了小程序的基本结构,如果要配置小程序打开的默认界面,可以有两个选择:

  1. 在app.json中增加entryPagePath字段,该字段的值对应的页面将会被配置为入口页面。
    “entryPagePath”: “pages/index/index”
  2. app.json 中不配置entryPagePath字段,则默认为 pages 列表的第一项。
{
  "pages":[
    "pages/index/index"
  ]
}

一般来说,配置完pages里的内容就可以满足小程序的基本配置需要了
更多app.json全局配置选项参考文档

在pages文件夹内,一般我们会存放每个页面的文件夹
结构一般如下
├── pages
│ │── home
│ │ ├── home.ttml
│ │ ├── home.js
│ │ ├── home.json
│ │ └── home.ttss
│ └── user
│ ├── user.ttml
│ └── user.js
值得一提的是,所有的js文件中,不管会不会用到data对象,我们都需要对data对象进行声明,否则会一直打印报错

Page({
	data:{
	},
});

另外,所有的json文件也都需要进行初始化,即便没有任何数据,也需要写入一对正反大括号。

获取用户信息 getUserInfo

与微信小程序不同,飞书小程序在获取用户信息时,在调用getUserInfo之前,还需要先调用login方法。

getUserProfile() {
	// 用户登录
    tt.login({
    // 成功回调
      success(res) {
        console.log(JSON.stringify(res));
        // 获取用户信息
        tt.getUserInfo({
          // 要求敏感信息
          withCredentials: true,
          success: function(res) {
            console.log(JSON.stringify(res));
            tt.setStorageSync('user', res);
            app.globalData.userName = res.userInfo.nickName;
          },
          fail: function(res) {
            console.log(`getUserInfo fail: ${JSON.stringify(res)}`);
          }
        });
      },
      fail(res) {
         console.log(`login fail: ${JSON.stringify(res)}`);
      }
    })
  },

更多login信息,请参考tt.login
更多getUserInfo信息,请参考tt.getUserInfo

关于跳转页面栈的问题

在我们的小程序在不同的page之间进行跳转时,我们可能会更习惯使用navigateTo这个方法,但是每一次使用navigateTo方法时,都会将当前页面压入栈中,随后再执行跳转操作,每次左划屏幕边缘回退页面时,都会从页面栈中弹出页面。
例如说,我们存在两个page:pageA,pageB,我们在pageA.js文件中调用

tt.navigateTo({url: '../pageB/pageB'});

此时程序会先将pageA压入栈(stack)中,随后再从页面A跳转至页面B;注意,如果这里讲的是,必须要先将页面压入栈成功后,才会执行跳转操作,如果页面压入失败了,那么是不会执行后边的跳转操作的。如果此时用户在页面B左划屏幕,则会将栈顶的pageA弹出,并跳转至页面A上。
但是值得注意的时,页面栈的最大值为10,当页面栈的大小达到10之后,再次调用navigateTo操作将会不再起作用,页面栈不会更改,页面也不会跳转。
因而我们可以配合redirectTo来进行使用:

tt.navigateTo({
    "url": "../shotPhoto/shotPhoto",
    success(res) {
      console.log(JSON.stringify(res));
    },
    // 失败回调
    fail(res) {
      console.log(`navigateTo fail: ${JSON.stringify(res)}`);
      tt.redirectTo({
        "url": "../shotPhoto/shotPhoto",
        success(res) {
          console.log(JSON.stringify(res));
        },
        fail(res) {
          console.log(`rediractTo fail: ${JSON.stringify(res)}`);
        }
      })
    }
  });

但,依然要注意的一点是,redirectTo只能跳转到非tabBar界面,如果要跳转至tabBar界面,还请使用switchTab方法。

更多关于navigateTo, 请参考 navigateTo
更多关于redirectTo,请参考 redirectTo
更多关于switchTab,请参考 switchTab

鉴权的获取

在飞书小程序的开发中,有时我们在尝试使用其服务端的一些功能时,可能需要我们的鉴权即tenant_access_token,此时我们可以通过小程序调用post请求来获取相关的数据。
值得关注的是,鉴权信息2小时过期,过期后重新申请即可。

tt.request({
        url: 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
        method: "post",
        data: {
          app_id: "appid",
          app_secret: "secret"
        },
        header: {
          'Content-Type': "application/json; charset=utf-8"
        },
        success: function(res) {
          console.log("try to get accessToken success:" + res);
          accessToken = res;
          tt.setStorageSync("accessToken", res);
          tt.setStorageSync("accessTime", new Date().getTime());
        },
        fail: function(res) {
          console.log("try to get accessToken failed:" + res);
        }
      })

多维表格?简配数据库!

多维表格文档 多维表格

多维表格可以被视为一个简配的关系型数据库,在飞书小程序不支持数据库的前提下,可以作为数据库的一个替代选项。

在对多维表格进行增加操作时,我们需要先自行创建一个多维表格,并获取到其app_token以及table_id,
如我们多维表格的url为
https://abc.feishu.cn/base/abcedfg?table=higklm&view=vewAVZdmul
此时,abcdefg即为app_token,table_id即为higklm。
同时,我们还需要获取鉴权。获取鉴权的方式如上介绍。
此处我们仅展示新增数据:

tt.request({
      url:'https://open.feishu.cn/open-apis/bitable/v1/apps/apptokenapptoken/tables/tableidtableid/records',
      method: "post",
      header: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + accessTokenString
      },
      data: {
        'fields': {
        	"人力耗时": 64,
       		"人力评估": "8",
        }
      },
      success: function(res) {
        console.log("上传数据成功"+ res);
      },
      fail: function(res) {
        console.log("上传数据失败" + res);
      }
    })

持续更新。。。

初学小白,在线挨打,如果有什么纰漏之处,还请大佬们多多指正。

有关飞书小程序开发经验的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  3. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  4. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  5. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  6. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  7. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  8. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  9. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  10. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

随机推荐