《0到1实践系列》开发运维一个独立微信小程序

背景

想来自己许久未在掘金写文章了,也没有在自己的博客上发一些自己的见解,技术成长等相关的内容。这可能跟自己从学生进阶为打工人有关,每天都加着班搬砖,我自己其实做了很多个人觉得有意思的小东西,我想把这些小东西整理为一个《0到1实践》系列,希望能通过分享设计实现过程来给自己找灵感,同时能帮助到正在做这方面开发的同学那就是我的荣幸了。 第一个我觉得可以分享出来的就是OfferTalk:offer说平台,这里想必大家都用offershow,我也用,我设计开发Offertalk的的灵感便来源于它,但我觉得offershow有点单一,至少一年前我在准备校招的时候是这样觉得的,于是我便开始操刀offerTalk了,当时有了这个idea到完全上线断断续续用了大概2月的样子,接下面我便将设计,实现,上线,运营的过程分享出来。 offertalk小程序的开发实现的过程将分为3部分来讲,分别是小程序前端,web管理端,node服务端,今天是小程序管理端,过程中会掺杂产品思考,技术细节,技术沉淀等等来讲

各项准备

总所周知,微信小程序于2016年正式发布,其有一个独特的优势就是依靠微信背书,自带大流量,运气好说不定能火一波。开发微信小程序前,你需要准备以下各项:

小程序账号申请

有一个从未注册过微信开发平台的邮箱账号,用户来注册小程序,注册微信小程序的过程如下:点击注册后,会让填该小程序的管理员,一般来说用自己的微信扫码即可,注意,一个个人账户最多只能绑定5个小程序账户,一个企业用户账号可以绑定最多50个小程序账号, image.png 小程序账号注册成功后,便可进入小程序的后台管理了,在后台管理上,可以进行基础设置的管理,可以查看小程序的各项数据 image.png

准备开发环境

小程序架构

小程序的架构采用了双线程架构,UI渲染一个线程,JS运行一个线程,与H5相比的单线程的好处就是js的运行不会阻碍到UI的渲染,但有一个线程间通信的消耗,也就是小程序的setState不能无节制的随意使用的原因,这里不讨论技术的底层原理,后续会单独出一篇小程序架构文章,尽请期待

开发框架

熟悉前端的同学能够很容易上手小程序,小程序有自己官方的开发框架MINA微信团队将前端三套件html+js+css转换为了wxml+wxss+js,就可以像写页面一样编写小程序了。这里我选择了微信的官方框架+自己抽象组件的方式来开发,社区有很多小程序框架(mpvue,wepy等),可以用vue写,也可以用react写,更有多端框架能够一套代码出码多终端代码,如rax,taro等,这里不展开将框架的对比,有需要的话后续我可以出一期微信小程序上层框架的对比。

开发工具

微信提供了自己的开发工具,微信开发者工具下载安装即可,按照教程创建项目,选择项目模板填入appid即可与项目关联。 image.png

产品设计

我们在解决问题最关键的步骤就是定义问题,我对offertalk小程序的构思是能够做成大家对offer进行讨论的一个匿名社区,并能够将信息上链(blockchain),做到真正的不可篡改和用户掌控。但往往理想是美好的,现实是骨感的,后面我会单独出一期跟blockchain有关的应用。 这里我对offertalk做了一个模糊的功能模块设计,因为当时我也不清楚最终要做成啥样,毕竟不是专业产品

  • 1.心智模块:有一个进入广告页面,给offertalk打上一个slogan,期待带来XXXXXXXX(当时一直没想好)
  • 2.入口主页:提供一个offer相关的推荐阅读
  • 3.信息检索:提供对薪资查询及offer文章检索
  • 4.薪资匿名发布:用户可匿名发布薪资信息
  • 5.社区功能:能够对offer相关文章,薪资内容进行评论,点赞,转发
  • 6.个人中心:常规设置选项,收藏等
  • 7....

image.png

模块及组件设计

按照上面的原型设计,我新建了小程序项目,并按照静态文件,页面,组件,工具库的方式进行了代码库目录设计 image.png
我最初的想法是将所有模块拆开利用SPA的方式完成整个小程序的开发,后来我发现,随着功能的越加越多,代码的可读性变得越来越差,在一个页面里面切换不同组件的状态也使得页面有一定的卡顿,在这时,果断换为了MPA的实现方式。 image.png

组件语义化的真实意义及可读性的实践

通常我们在进行组件库才分设计的时候,并没有一个明确的可参考的规范,跟我们使用的技术栈,业务形态都相关,如果只是业务组件库,可能根据不同的业务形态能够定义出不同的组件库分层定义,这里我给出一套自己的组件分层抽象设计的方式,以基础组件未底,构建兼容性强的基础组件库;往上利用基础组件封装实现功能样式多态的技术组件;利用技术组件封装业务组件。 image.png
基于此,我将自己做过的小程序进行同意抽象,抽离出了一套自己的组件库,bowenUI :一个用原生MINA框架实现的小程序组件库: image.png 我认为组件应该极大可能的以纯函数类型出现,给定输入会返回确定输出;不受外界依赖影响;所以,我在每个基础组件下创建了一个readme来对组件进行函数式解读,同时也增加可读性和可维护性。 image.png

模块编码

按照模块及组件设计,进行模块编码,这里给出查询页面的代码实现示例

<!--pages/search/search.wxml-->
<view class="container">
  <header title="薪资查询" path="search"></header>
  <!-- <view class="sub_title">查薪资,上offer说</view> -->
  <!-- 搜索框 -->
  <view class="input_box">
    <view class="input_box_left">
      <image src="../../images/search.png"></image>
    </view>
    <view class="input_box_right">
      <input class="weui-input" placeholder="输入关键字模糊查询" bindinput="bindinput" bindblur="bindblur" value="{{value}}"
         />
    </view>
  </view>

  <view class="searchbox">
    <searchitembox data="{{itemData}}" bind:itemclick = "itemsearch"></searchitembox>
  </view>
  
  <scroll-view scroll-y="true" class="scroll-view" wx:if="{{!emptyshow}}">
    <view class="ad-box">
      <ad unit-id="adunit-e88152005d8158cc"></ad>
    </view>
    <card wx:for="{{arr}}" wx:key="{{item.id}}" infoObj="{{item}}"></card>
    <footer></footer>
  </scroll-view>
  <empty wx:else text="Empty"></empty>

</view>

<!-- filter 组件 -->
<view class="filter_box" style="right:{{filterRight}}">
  <image src="../../images/filter.png" class="filter" bindtap="showfilter"></image>
  <view class="filter_item" bindtap="filterItem" id="0">校招</view>
  <view class="filter_item" bindtap="filterItem" id="1">实习</view>
</view>
复制代码
// pages/search/search.js
let net = require("../../utils/net");
let app = getApp();
Page({
  /**
   * 页面的初始数据
   */
  data: {
    value: "",
    arr: [],
    emptyshow:true,
    itemData:["快手","美团","百度","字节","阿里"],
    filterRight:"-145rpx",
    filterItemValue:{
      "0":"校招",
      "1":"实习"
    }
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: async function (options) {
    let that = this;
    this.setData({
      value: options.param
    });
    that.getinfo(that.data.value);
    this.getLabel();
  },
  // 数据获取api
  getinfo: async function (data) {
    wx.showLoading({
      title: '数据请求中...',
    })
    let that = this;
    try {
      let result = await net.fetch("/getinfo", data, "POST");
      if (result.data.code === 1) {
        if(result.data.data.length === 0){
          that.setData({
            emptyshow:true
          })
        }else{
          that.setData({
            emptyshow:false
          })
        }
        that.setData({
          arr: result.data.data,
        })
      } else {
        wx.showToast({
          title: '获取失败',
          icon: "none"
        })
      }

    } catch (error) {
      wx.showToast({
        icon: "none",
        title: '网络繁忙',
      })
    }
    wx.hideLoading({
      success: (res) => {
        
      },
    })
  },
  // 回退
  back: function () {
    wx.navigateBack();
  }
复制代码
/* pages/search/search.wxss */
page{
  height:100%;
}
.container{
  height:100%;
  background-color: #e6645f;
  overflow: hidden;
  opacity: 0.9;
}
.sub_title{
  width:100%;
  text-align: center;
  font-size:25rpx;
  font-weight: bolder;
  color:white;
  letter-spacing: 3rpx;
}
.input_box{
  width:90%;
  height:70rpx;
  background: rgb(245, 255, 255);
  margin: 30rpx auto;
  margin-bottom:0;
  border-radius: 10rpx;
  box-shadow: 0 0 1px 1px white;
}
.searchbox{
  width:90%;
  margin: 15rpx auto;
}
......
@media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) {
  .filter_box{
    top:350rpx
  }

}

/*  xr */
@media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) {
  .filter_box{
    top:350rpx
  }
}

/*  xs max */
@media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) {
  .filter_box{
    top:350rpx
  }
}
复制代码

程序上线

小程序完成开发自测后,便可借助开发工具进行代码的提交,然后在管理端进行版本的切换与提审,审核通过以后,切换版本上线,小程序便可在公网访问了,微信搜索offertalker就能访问了,欢迎提出宝贵意见 image.png

总结

在整个开发过程中,体验了一把真全栈开发,从产品构思到产品设计到产品的开发实现落地到线上运营,最终产出了offertalk小程序,web管理端,node服务,bowenUI小程序组件库,体会到了独立开发者的不容易,web管理端和node服务设计将会以另外文章展示出来。

猜你喜欢

转载自juejin.im/post/7079229211507949582