Dec 11, 2018 - 小程序开发经验

记录一些开发小程序的经验。

自定义组件

tabBar

底栏tabBar是可以自定义的。但如果自定义的话,最好把几个tab对应的页面做成一个单页面。否则切换tab时,由于页面的跳转,底栏tab会有明显的闪烁。

顶部状态栏

顶部状态栏也是可以自定义的,设置"navigationStyle": "custom"即可。但是要注意适配,尤其是像iPhone X,小米8等有刘海的机型。 官方自带的状态栏,高度是会随着机型变化的。

另外,左上角的返回键是无法控制的。小程序内部会维护一个栈(LIFO, Last In First Out)来存贮访问过的页面。 当发生页面跳转时,把上一个页面的路由放入栈中,点击返回键时从栈推出最后访问的页面路由。栈的最大长度时6,也就是页面最多跳转6次。当栈为空时,返回键消失。

官方明令警告,不要尝试修改页面栈,会导致路由以及页面状态错误。一开始把整个小程序做成了单页面,后来悲剧地发现没有返回键了。也没办法自定义,无奈只好重来。

所以自定义状态栏,最多也就能控制下它的高度,字体的大小等等,没有太大的必要。

toast

官方自带的toast组件太不好用了,只有个对号的icon,连个X的icon都舍不得给。而且宽度无法改变,字体长度也有限制。好在自定义toast组件过程中,也没遇到什么问题。

只有一个,在使用wx.setClipboardData复制文本时,复制成功后会自动调用官方自带的toast组件显示内容已复制。这时再唤醒自定义的组件,就两重toast,有些尴尬。解决方法也很简单,手动隐藏掉即可:

wx.setClipboardData({
  data: 'xxxxxx',
  success: () => {
    wx.hideToast()  # 手动隐藏官方的toast
    self.myOwnToast('已复制到剪贴板')
  }
})

cover-view 与 cover-image

cover-view 和 cover-image 是可以覆盖在小程序原生组件之上的文本视图和图片视图。 原生组件指的是像video,mapcanvas等组件。使用时有以下几点需要注意:

  • cover-view标签内部,只能嵌套cover-view,cover-image,button,其他标签无效。

  • 不支持background-image, overflow等样式

其实所有值得注意的点,官方也都列出来了:cover-view.html。 坑爹的是,这些不支持的效果,在开发者工具预览时都是有效的,只有在真机上测试才会失效

Canvas画布

小程序定义了一个新的尺度rpx,所有手机在小程序内部的宽度都是750rpx。写样式的时占满所有宽度就可以width:750rpx。然而当使用canvas绘图时, canvas并不支持rpx,仍然只能用px。若要画图占满整个宽度,只能用以下的方式:

<canvas class='canvas' canvas-id="canvasElement" style="width:px"></canvas>

使用小程序接口动态获取屏幕宽度。

wepy的坑

  • 当修改数据时,记得运行this.$apply()更新页面

  • 没有完整的生命周期,只有一个onLoad事件

Aug 22, 2018 - Django 缓存机制

大部分的内容都在文档里说的很清楚了:Django’s cache framework

需要的注意的是,要在settings.py文件中添加中间件。

MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',           # 更新缓存
    'django.middleware.security.SecurityMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',        # 获取缓存
]

另一个让我烦恼一个多小时的问题是,设置TIMEOUT参数无效。查找Django的源文件(./core/cache/backends/memcached.py),打印出设置缓存时的信息。发现不论参数设置多少,缓存的有效期都变成了600s。

后来终于在django的conf/global_settings.py这个文件里找到CACHE_MIDDLEWARE_SECONDS = 600这个参数。看名字是中间件的缓存时间,懒得深究了。在settings.py文件中把这个参数值也修改一下,再次测试,终于得到预期的效果。这个问题竟然在放狗都没搜到,值得一记。

Jun 20, 2017 - R server & nginx

R的服务器

托福于Rstudio的httpuv包,R语言也终于可以做后端了。httpuv的底层是两个C语言库libuv和http-parser,所以在吞吐量上并不逊色Python的web框架。

httpuv完成了基础的HTTP和WebSocket请求的处理接口,基于它二次开发的框架有fiery和plumber。当然shiny也算,不过shiny的前后端集成度太高,并不适合做为单纯的后端使用。

一个fiery的例子:R的高性能 http 服务 fiery

fiery和plumber的简单对比:Benchmark of R’s http framework

Nginx

Nginx是一个开源的HTTP Server,同时支持转发,代理,权限认证和负责均衡等功能。在Nginx的帮助下,可以轻易的在一台服务器上配置多个网站和应用程序。

在使用R语言的框架搭建好一个简易APP之后,可以使用nginx来为他配置上你的域名。以下是一个简单的配置文件,假定有两个APPs在监听9123和9124端口,下边的配置可以将访问serverr.com的请求均匀的转发到9123和9124端口。

upstream rserver {
    server 127.0.0.1:9123;
    server 127.0.0.1:9124;
}

server {
    server_name serverr.com;  # config host name
    location / {
        proxy_pass http://rserver;
    }
}

把以上配置写入rserver.conf文件中,并放在nginx的配置文件里,重启nginx使之生效。此处以及后文假定系统为Ubuntu。

sudo cp rserver.conf /etc/nginx/conf.d
sudo nginx -s reload

如果serverr.com是你自己的域名,你需要到域名提供商那里设置DNS将该域名指向你的主机IP。为了简单起见,可以修改本地的hosts文件,将serverr.com域名指向自己:

sudo vi /etc/hosts
# 添加这样一行信息:  127.0.0.1 serverr.com

设置完成后,就可以通过curl http://serverr.com/predict?val=190访问了。可以使用siege工具来测试效果:

siege -c 255 -r 10 'http://serverr.com/predict?val=190'
siege -c 255 -r 10 'http://localhost:9123/predict?val=190'
siege -c 255 -r 10 'http://localhost:9124/predict?val=190'

这里使用nginx的测试结果稍微好一点点,但效果并不十分明显。因为数据的处理太过简单,主要在于IO的耗时。相比于直接访问端口,访问域名会需要额外的一点时间来解析并转发。使用nginx的负载均衡的另一个优点在于,当其中一个程序宕机时,nginx会自动把请求转发到另一个健康的程序上去,保证服务不间断。

最后介绍一些安全措施:

  1. 参考Shiny 工程化实践之HTTPS加密中的nginx设置,为你的网站配置https。

  2. 参考RESTRICTING ACCESS WITH HTTP BASIC AUTHENTICATION为APP设置密码

  3. 通过iptables规则,设置特定IP才能访问。

以下规则使得只有192.168.1.1到192.168.1.255的IP地址可以访问本机的9123和9124端口,杜绝其他外来流量。

sudo iptables -I INPUT -p TCP --dport 9123 -j DROP
sudo iptables -I INPUT -p TCP --dport 9124 -j DROP
sudo iptables -I INPUT -m iprange --src-range 192.168.1.1-192.168.1.255 -p TCP --dport 9123 -j ACCEPT
sudo iptables -I INPUT -m iprange --src-range 192.168.1.1-192.168.1.255 -p TCP --dport 9124 -j ACCEPT