这段时间开始做小程序的开发,所以稍微研究了下小程序的开发框架。
当下比较有名的有以下几个开发框架:

  • 基于模板的类 vue 的原生框架
  • 在原生框架上改良的仿 Vue 框架 wepy
  • 基于 Vuempvue
  • 基于 Reacttaro

另外还有几个小众的:

因为之前比较熟悉Vue,所以没有太费脑力就选了 mpvue

看了文档觉得虽然有所限制,比如:

  • 模板里不能写复制的表达式
  • 模板里不能用函数
  • 不能用 filter
  • 不能用 slot

感觉虽然有限制,但是好像没有特别大的关系。多费点代码还是能克服的。

谁知道,刚码了两个页面就遇到了坑。

  • beforeDestroy 回调基本没用
  • mounted 可能永远不会调用第二次
  • 再次进入页面时有上次状态的残影
  • 再次进入页面时取不到变化的页面路径参数
  • 使用 HTML 原有的标签名作为组件名时,自定义组件内模板不起作用
  • 错误如果不捕捉会被吞没,不报错

倒不是某个框架的问题,搜了一下其他的框架基本也都有这些问题。

还没有具体看过 mpvue 源码,但是看了前人介绍,有些是因为小程序的特色所导致的。
比如为什么页面再次打开会有之前的状态值存留。

个人感觉以下内部世界被割裂成了3个世界:

mpvue 对象 -> 小程序Page对象 -> View render

原生的 Page 里 通过 setData 把数据传输给视图进行显示,
当页面关闭后,页面对象消失,但是 mpvue 对象会重复使用,
每次页面重开时会使用之前的 mpvue 对象,造成了数据的残留。
理想状态是 Page 关闭时,销毁 mpvue 对象,打开时再重新生成。这样整个生命周期就与预期一致了。

正因为以上的原因,造成了很多意想不到的问题(keng)。

也探索了一些解决方法:

问题1:数据残留

export default {
  data () {
    return {
      a: 23
    }
  }
}

对策:onUnload里重置初始值

export default {
  data () {
    return {
      a: 23
    }
  },

  onUnload () {
    Object.assign(this.$data, this.$options.data())
  }
}

这里的 this.$optionsVue内部使用的属性,保留着初始的对象值。
可以把他写成一个Vue plugin,这样就可以省却每个页面都要写的尴尬。

问题2:computed 内获取的参数不会变化

export default {
  computed: {
    id () {
      return this.$root.$mp.query.id
    }
  }
}

对策:写入 mounted 里,赋值到 data 对象内

export default {
  data () {
    return {
      id: null
    }
  },

  mounted () {
    this.id = this.$root.$mp.query.id
  }
}

问题: 组件文件名不要使用HTML标签名

组件名用了 article, 引入时不报错,但是组件内部模板不显示,也不报错。
即使引入时改了,也还是不显示:

import Article2 from './article'

对策: 为了减少麻烦,一定要使用非HTML标签名,引入时也最好名称一致。

问题4:自定义组件时写的事件处理函数不起作用

<template lang='pug'>
  .container
    tag1(
      @click='handler'
      v-for='item in items'
      :key='item.id'
    )
</template>

对策:如果想再调用时处理事件的话,需要在自定义内部通过$emit 发出来,
自定义组件所有的事件都需要自己发射到父组件。

暂时就先记这么多,后续有再跟进。
多说一句: mpvue 是基于 Vue 2.4.1 基础上开发的,所有 2.4.1 以上的功能就不要去用了。

自从去年2017年微信开放了小游戏之后,极大的促进H5游戏的发展。可以想象今年微信游戏必定非常火。
乘着这股春风,结合近期研究的 rxjs,想尝试下用 rxjs 改写微信官方小游戏。

weixin-game

阅读全文 »

使用 Docker 安装了 Redmine 之后,已经过了很久了,这几天在维护服务器时,发现 Redmine 的版本也升级了。
就想着也升级一下容器吧。

先说下大体思路:

  • 升级 Docker Image
  • 关闭就容器,并删除之
  • 重新开启新的容器,这样才能使用新的代码
  • 升级数据库

升级 Docker Image

升级Image很简单,只要从服务器拉下来最新的数据就行了

docker pull quay.io/sameersbn/redmine:latest

关闭就容器,并删除之

到工作目录 /data, 使用 docker-compose 来关闭级容器

cd /data
docker-compose stop
docker rm data_redmine_1

重新开启新的容器,这样才能使用新的代码

因为代码升级,新增加了些环境参数的配置

REDMINE_SECRET_TOKEN
DB_NAME

这两个一个是log提示我的,另一个发现服务升级完后,旧用户登录不了了,查了原因才知道是因为数据库名称的默认值变了。
可能受影响的还有其他不少参数,需要在详情页仔细看看。

docker-compose start

升级数据库

docker exec -it data_redmine_1 bash
cd $WORKDIR
RAILS_ENV=production bundle exec rake db:migrate

深度学习笔记。

公式

h(x) = XW + b

方阵尺寸
X = (100,784), batch size: 100, 特征尺寸: 784
W = (784,10), 特征尺寸,输出个数
b = (10,1), 输出个数,1
h = (100,10) batch size, 输出个数

分类方法

softmax,确定图像是属于10个数字中的哪一个

激活函数

tanh, sigmoid, relu,深度神经网络中推荐使用 relu

输出值范围

  • tanh
    -1 ~ 1
  • sigmoid
    0 ~ 1, 1 / (1 + e^-x)
  • relu
    0 ~ 正无穷, max(0, x)

Loss function

交叉熵 Cross entropy:
- reduce_sum(Y_ * log(Y))

训练算法

SGD

梯度下降算法: SGD
步长: 0.01, 太大速度快但可能取不到最精确值,太小则速度慢

缺点: 步长选择比较困难

Momentum

下降初期能够很好的加速

Adagrad

前期放大梯度,后期约束梯度
依赖人工设置全局学习率

Adadelta

Adagrad的优化,不需要人工设置全局学习率

训练初中期,加速效果不错,很快
训练后期,反复在局部最小值附近抖动

RMSprop

Adadelta 的一个特例

  • 依赖全局学习率
  • 趋于 Adagrad 和 Adadelta 之间
  • 对于 RNN 效果和好

adam

本质上是带有动量项的RMSprop

  • 自适应学习率

最大池化

max pooling, 比如 5x5 的池中取最大一个值作为输出值

strides 步长

步长的意义在于缩小特征尺寸。比如输入 28x28 的方阵如果使用 2x2 的步长,则输出的方阵缩小为 14x14

输入通道,输出通道

在建立深度学习的层中,一般是缩小特征尺寸,增大通道大小。整个特征个数是呈现变小的趋势。

No.     方阵              kernel 和通道       步长
1       28x28x1           5x5,1,4             1x1                                             
2       28x28x4           4x4,4,8             2x2                                             
3       14x14x8           4x4,8,12            2x2                                             
4       7x7x12            全连接                                                              
5       200               softmax                                                             
6       10                用于10个数字                                                        

如何确定通道大小

比如手写的数字 4 个通道是比较小的,需要增加到6个,是个经验值

No.     方阵              kernel 和通道       步长
1       28x28x1           5x5,1,6             1x1                                             
2       28x28x6           4x4,6,12            2x2                                             
3       14x14x12          4x4,12,24           2x2                                             
4       7x7x24            全连接                                                              
5       200               softmax                                                             
6       10                用于10个数字                                                        

后续阅读

https://zhuanlan.zhihu.com/p/22252270
http://ycszen.github.io/2016/08/24/SGD%EF%BC%8CAdagrad%EF%BC%8CAdadelta%EF%BC%8CAdam%E7%AD%89%E4%BC%98%E5%8C%96%E6%96%B9%E6%B3%95%E6%80%BB%E7%BB%93%E5%92%8C%E6%AF%94%E8%BE%83/
https://yq.aliyun.com/articles/250639

例子

https://www.tuicool.com/articles/vieuIbi
https://www.tuicool.com/articles/bayI7ne

最近在写一个发邮件的小程序,经常会碰到邮箱系统报错,但是看了日志也没看出的头绪来。
因为出错信息不详细,或者是信息与真正的错误没啥关联,会被带到沟里去。

其实用 SMTP 服务器的话,都是用 smtp 协议来发邮件,都是文本形式的协议,协议其实挺简单的。

总的来说3个大步骤

  1. 建立连接
  2. 验证
  3. 上传邮件内容

详细来说一下这个过程:

  1. HELO , qq邮箱域名是必须的。

     helo qq.com
     250 smtp.qq.com
    
  2. AUTH base64编码的用户名,密码,每个单独一行

     auth login
    
     334 VXNlcm5hbWU6
     aW5mb0BqaWFveHVlYmFuZy5jb20=
    
     334 UGFzc3dvcmQ6
     xxxxxxxxxxxxxxxxxxxxxxxxxxx
    
     235 Authentication successful
    
  3. MAIL FROM: 发件人邮箱

     mail from: info@jiaoxuebang.com
     250 Ok
    
  4. RCPT TO: 收件人邮箱

     rcpt to: ryan@jiaoxuebang.com
     250 Ok
    
  5. DATA 邮件数据,包括邮件头部,正文, 以 换行.换行 结束

     data
     354 End data with <CR><LF>.<CR><LF>
     subject: test
    
     test
    
     .
    
     250 Ok: queued as
    

250 显示已经进入队列等待发送了。

正好项目中要使用外部的 DLL 接口,如果用 C 来写固然是可以的。
但是也好多年没用了,觉得再拿起来也要些时间。就搜了下 Ruby 来怎么对接。

基本上网上推荐了2种方法:

  • fiddle
  • ffi

fiddleRuby 标准库自带的,用法比较简单,但是官方文档特别少。
ffi 是一个独立的 Gem,他是基于 libffi 的一个外部扩展来实现的,官网文档比较多。

感觉 fiddle 使用比较简单,我用的 DLL 也不是很复杂,就只试了 fiddle
首先推荐看下这篇基础教程 ,大体就知道怎么用了。

但是很快就遇到了一个问题,int[] 这种数组怎么传过去。
搜了下,看到了这篇文章,试了一下用 a.pack('i' * a.size) 方法的确可以。

遇到的第二个问题是如何传 UNICODE 字符串,搜了一下没有搜到。
于是我就想说不定 ffi 这边的文档会有些提示。
果然官方Wiki 里有一篇例子讲到了,使用需要encode('UTF-16LE')一下,
有一点我试的时候不在末尾加 \0 也是没问题的。

是的,又换了一个博客引擎。

从 Octopress -> middleman-blog -> Hexo,博客没写几篇引擎倒是换的很勤,自嘲一下!

自从 2014 年切换到 middleman-blog, 已经有3年时间了,但是 middleman-blog 发展却停滞了。
究其原因,我想到了几点:

阅读全文 »

ImageMagick 是强大的图片处理工具,
可以用来处理图转换,旋转,放大,缩小,模糊等很多处理。

本篇准备用一个案例来说明 ImageMagick 的用法。

需求描述

  • 给定一张底图图片,白色背景,黑色散列点小黑子,大小为6400x6400
  • 要求把这张图片8x8的切成64小块,打乱排序后重新得到一张图片。
  • 在每张小图片底部叠加一张中间有序号的图片,用于确认图片顺序。
阅读全文 »

现在与主机交互的首选工具应该是 ssh 相关的工具了,比如 scp, rsync。因为他们都是建立在传输层基础上的安全协议。
而老牌的 ftp 则不然,因为他们访问主机时的登录交互容易被窃听,有泄密的可能性。
ftp 也有对应的安全版本 sftp, 但是用的就很少了,因为 sftp 也是基于 ssh 的,但是 ssh 自带传输特效,所有 sftp 就很少用的了。

本篇为什么要写 ftp,是因为对接老的系统的时候,是超出我们控制的。
最近的项目中就需要把本地的数据包传到服务器上,因此找了几个 ftp 工具来分析了下。

阅读全文 »

当系统访问很频繁,服务器日志增多到一定量时,仅靠 tail -f 已经很难分析出有用信息了。
可能就只能进行一些简单的排除工作,比如根据日志内的时间信息,查找该时间附近有什么特殊访问之类。

即使这样用有时候也会比较麻烦,因为当你的应用服务器增多时,每个服务器都是单独写到本机日志文件内,造成了分析日志的难度。
这个时候就很需要一个工具来收集各个服务器日志来统一处理。

今天说的就是有关于这个问题的解法。

阅读全文 »
0%