Giter VIP home page Giter VIP logo

blog's People

Contributors

islishude avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blog's Issues

人行道红绿灯的产品思考

生活在北京,天天都得过人行道,较之小城市比较人性化的是人行道有了红绿灯闪烁倒计时。

P.S. 后续补充:随着我经常的走动,事实证明有的街道有倒计时,有的没有的。

经过我计算,25米大道绿灯时长约45秒,倒计时闪烁长约30秒,我过人行道大约15秒,考虑到其他群体,比如老人小孩,他们的走路速度过人行道30秒左右。大流量人群全部走过去大约也需要30秒左右。如果我走到人行道就闪烁了或者走在路口没有闪烁,那么就无所谓了,肯定能过去。如果我刚到路口就看到红绿灯已经闪烁,大多我心里会犹豫要不要过去,因为我不知道绿灯是不是还有15秒,结果人肉尝试走了几次都是走到路**就红灯。。衰

如果改到剩余15秒再闪烁,这样子如果像我这样的看到闪烁就不过去了。大流量人群都是在等绿灯形成的,所以总共45秒的肯定能过去。对于老人小孩子刚看到闪烁肯定不会过去,因为只有15秒,但是如果走到路口没有闪烁,因为如果还剩下20秒也是没有闪烁,老人和小孩子肯定不会选择过去。

如果我们做产品会优先考虑哪类人群?为了节约上班族的时间剩余15秒闪烁最佳,但是我们产品的群体有老人小孩这些弱势群体,我们不能不考虑这些,为了社会和谐,最佳的选择就是剩余30秒闪烁。

但是如果我们对我们的用户都考虑到,是不是可以使用直接罗马数字式的倒计时?但是又考虑到执行性价比以及现有的技术标准,我们做产品时就只能暂时除掉这个需求或者小范围A/B试验。

如果你仔细观察生活,你会发现地铁和普通铁路不一样,地铁不需要枕木。你知道为什么?观察并思考,这就是做产品。

运营工作常用的工具网站

这篇简单写写。

运营工具

文案狗
经常看到一些好名字,比如脉脉APP的「业问」,好名字都是重新排字组合的,文案狗就能帮到我们一些创意灵感。
网址:wenangou.com

Grouplus
这是一个社群管理工具,发布一个活动,线上售票等等。非常好用。
网址:grouplus.com

文图
可以用于运营复盘的展示工具,这个网站简单说就是帮我们做一个包含数据报表的在线报表,简单免费,还可以**热度地图这样的控件。
网址:wentu.io

百度脑图
在线制作思维导图最佳的网站。我最喜欢的是可以键盘快捷操作。
网址:naotu.baidu.com

公开数据

百度指数以及百度风云榜就不说了。

阿里指数
买卖双方数据,前身是淘宝指数,有一定参考价值,能看到一些地区和特定人群的主要购买喜好。如果想获取更多的,那最好是成为淘宝天猫卖家,然后付费购买数据。
网址:alizs.taobao.com

新媒体指数
社会热门风向标,对内容运营有很大帮助。
微博指数:data.weibo.com
清博指数:gsdata.cn

新榜:newbank.cn

免费图库

很多公众号作者都在用Pixabay的照片,图库大、质量高、基于CC0协议免费使用。但是访问速度稍慢,尤其是第一次加载。推荐另一个网站。

摄图网
也是基于CC0协议的免费图库,服务器在国内,所以访问速度非常快。图库质量非常高,而且全面。我一般都在这里找图片。不过这个网站只能免费每天下载3张图片,如果下载更多的话需要付费。
地址:699pic.com

常用工具

麦客CRM
我用这个的时候,当时还只是简单地用来招聘表单,后来还用这个做过学校的快递代取(可以内嵌商品支付)。我比较喜欢的这个的原因就是可以自定义分享到微信朋友圈的文案还有可以在微信内接收新的表单申请。
地址:mikecrm.com

草料二维码
二维码制作、美化、解析这些简单地功能都能做,还可以做参数二维码。
地址:cli.im

Tagul
被推荐最多的文字文图工具。缺点还是很多的,访问慢、对中文支持不好。
网址:tagul.com

虫部落
中文聚合搜索中的神器,你想搜索的都能搜得到。有这样的网站基本不用学习高级搜索引擎语法。
网址:so.chongbuluo.com

如果你有更好的想法可以联系我的个人微信交流:isLishude

在Git中仅仅改变文件名称的大小写不被追踪的解决方式

在对文件命名大小写不敏感的文件系统中,如果你改了文件名(只是大小写变化),Git 默认模式是识别不了这种变化的,自然就无法提交,那该怎么做呢?有不少方法,看看 StackOverflow 的讨论。当然绕过这个问题的办法是约定所有的文件名小写。

git mv -f OldFile oldfile

密码学家的工具箱

窃听(秘密泄露)——机密性——对称密码、非对称密码

篡改(信息被修改)——完整性——单向散列函数、消息认证码、数字签名

伪装(伪装成真正的发送者)——认证——消息认证码、数字签名

否认(事后称自己没做)——不可否认性——数字签名

阿里云PPA源403报错的解决方式

阿里云添加ppa源403错误解决方式

我在阿里云 Ubuntu16.04 添加 ppa:certbot/certbot的ppa源的发现在sudo apt update时,所有的 PPA 源使用都会出现类似

Err:4 http://ppa.launchpad.net/ondrej/php/ubuntu xenial Release
403 Forbidden [IP: 112.124.140.210 80]

这样的 403 错误提示,而且 IP 是阿里云的 IP。

经过排查以后发现原来是阿里云在安装的时候默认使用了 apt 代理导致被 PPA 源 403。

解决方案:

sudo vim /etc/apt/apt.conf

删除其中的

Acquire::http::Proxy "http://mirrors.aliyun.com/";

一行即可。

使用Certbot免费升级到https

安装certbot

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot

下面的教程根据Ubuntu16.04 nginx+php 的配置,你可以在certbot上找到你的系统需要的配置,但是基本差不多。

第一步配置nginx

这里在80端口配置以下就可以了

 location ^~ /.well-known/acme-challenge/ {
                default_type "text/plain";
                index index.html index.html
                root     /usr/share/nginx/html;
        }

记得重启服务sudo service nginx restart

开始获取证书

letsencrypt certonly --webroot -w /usr/share/nginx/html/ -d wukonghr.com

-d命令可以接多个域名。

第二步配置nginx

在配置文件中最下面有个#https server{}

server {
       listen 443;
       #需要多个域名配置的话下面只需要保留一个
       listen [::]:443 ssl ipv6only=on;
       #server name
       server_name your-project-name.com;

       root your-project-dir;
       index index.html index.htm index.php;

       ssl on;
       #注意下面的地址要正确
       ssl_certificate /etc/letsencrypt/live/your-domain/fullchain.pem;
       ssl_certificate_key /etc/letsencrypt/live/your-domain/privkey.pem;

       ssl_session_timeout 5m;

       ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
       ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
       ssl_prefer_server_ciphers on;

       location / {
               try_files $uri $uri/ /index.php?$query_string;
       }
       location ~ \.php$ {
                try_files $uri /index.php =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
        }
}

记得重启服务sudo service nginx restart

使得80端口跳转到433端口

index index.html index.php index.htm;
return 301 https://wukonghr.com/;

到期更新

certbot renew --dry-run

自动更新

暂补充

怎么不让学校的电脑修改自己的U盘

外语系经常做ppt,但是汇文楼的电脑不仅老,还会给你的U盘内写入一些文件,以前我没在意,现在买了个新U盘,我再也不能忍了,现在行动!

此操作有风险,
如果对windows操作不熟悉,
最好找一个高玩来做!

备份并清空你的U盘
因为我们要对U盘进行权限设置,如果你的U盘是FAT32,而非NTFS格式,那么就进行这一步,记得选择快速格式化

image

把文件放入U盘内并设置权限:
右键U盘选择属性,切换至安全标签,操作如下,最后确认保存即可:

image

image

关于硬盘格式
在windows下,每个硬盘分区都有一个自己的文件系统格式,常见的有FAT,FAT32,还有NTFS,微软在千禧年发布了NTFS的文件系统,与FAT的文件系统格式,NTFS突破FAT的单文件不可大于4G的大小限制,如果你的U盘大于16G,我建议你选用NTFS格式,但是如果你同时使用了Mac电脑,还是给U盘设置为fat,因为Mac不支持NTFS。

git notes

Git Study Notes

This is a repository of git-study,the "#" mark is a commad comment

lable

  1. git init
  2. branch
  3. tag
  4. Reset
  5. issues
  6. pull requests

Start

  1. git init #Start a local git repository
  2. vim README.md #Create a readme file , and write something
  3. git add . #add all files to git index
  4. git commit -m"init" #comment this commit
  5. git remote add origin https://github.com/isLishude/test #remote the github repository,at first you have to create a new repository.you can remote two or more server
  6. git push -u origin master #push to github,and set default push operating,if you have more remote server,you can "git push REMOTE_NAME BRANCH_NAME" to another.

Branch

  1. git checkout -b dev #Create branch and change banch to dev
  2. git add . # add file
  3. git commit -m"add file"
  4. git push origin dev
  5. git checkout master #change branch to master
  6. git merge dev #merge dev branch to master
  7. git push origin master #push to github
  8. git branch -d banchName #delete merged branch,and -D unmerged can be drop.
  9. git push -d branch #delete remote repository branch
  10. git fetch -p # remove any remote-tracking references that no longer exist on the remote.

Tag

  1. git tag tagName #set curent commit as a tag
  2. git push --tags #This command JUST push tags to the remote server,and need command git push origin to push your latest code.
  3. git push -d tag tagName #delete remote server's tag

Reset

  1. git checkout -- filename # situation that don't command "add",and will reset to your last file
  2. git reset HEAD filename # situation that "add to index"
  3. git reset --hard commit-hash # situation you commit
  4. git log # show the commit log,"--abbrev-commit" can show short hash,"-2" can show the first two times commit hash

Issues

  1. you can create a new issue on github remote repository
  2. git commit -m"fix #num" #the "fix # 1" commit mark can fix issue # 1

Pull requests

  1. if fork the code,ande wanna contribute your code,you can pull requests on github.
  2. click "New pull request",and write your PR comment to forked repository.
  3. if your code is OK,the pull request can merge your code to forked repository.

Others

anytime you can command "git --help" to show the manual,for exsample,"git log --help" to show the "git log" manual.

微信小程序开发初探

2016-12-03 03:50 | adesight

先不谈开发,先说说我对小程序的理解。

上周五微信小程序公测,懂不懂技术的都感觉这是个趋势潮流,无论以后火不火都想先占个坑再说。其实说,小程序类似以前百度的框计算应用,比如你在百度搜索“10+30*56”这样的公式就会出现“计算器”网络应用。不过呀,搜索可没有社交「高频」,所以小程序未来对于微信来说机会还很大。

不用下载,用完即走,小程序其实最适合低频高需的工具型和服务型应用接入,比如上面说的“计算器”应用,也可以是O2O、票务、招聘等这些应用接入。

现在的小程序体系很像苹果IOS应用商店,有很多限制——不能**除订单模板消息外的信息,不能读取本地资源,也不能接入类微信体系如朋友圈的功能的应用。

更大的限制有两个,如果你的公司想开发小程序需要注意,第一目前的形式是仅仅可分享到好友和群,不能分享到朋友圈,传播红利不会很大;第二小程序开放的接口也会和现有OAuth开发出现有三六九等,腾讯体系“亲儿子”和“自家人”享受到的API权限更多,比如获取共同使用的好友,帮助分享内容到微信。

image

红利或许没有想象的多,不过很多人都说,先接入肯定会因为大众新奇而有流量导入,不管怎么说吧,先接入试一试吧。

接下来说说小程序开发。

小程序接入和服务号、订阅号、企业号接入流程一样,需要重新注册一个公众号,目前仅对企业、媒体、政府、其它组织开放权限,每年需要付费300元进行认证,比苹果应用商店收费实在的多。

官方文档:https://mp.weixin.qq.com/debug/wxadoc/dev/index.html

开发工具:https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html

微信官方文档不太适合前端新手阅读,对于近些年流行的数据绑定以及模块开发等都是一带而过。

为了方便大家理解,下面的内容大多数是我自己的理解,官方文档并没有说明。

我的理解是小程序主要包含 2 个文件系统, 4 个文件类型 。

image

小程序提供了官方Demo

2 个文件系统指的是app全局文件和page局域文件; 这2个文件系统下面可以包含 4 个文件类型指的是WXML、WXSS、JSON、JS。(如果你读文档时候一定会注意到小程序由逻辑层和视图层驱动,这个就是流行的MVVM模式)

app全局文件内的属性以及设置是可以应用到page局域文件内,page局域文件也可以重写app全局文件的相同属性和设置。除了基本的样式表,这里面可以设置“应用的生命周期函数”、“变量数据”、“窗口和Tab样式”、“所有页面的路径”以及“网络超时时间”等。

WXML也就是HTML,不过“ HT ”变成微信的缩写“ WX ”,类似的 CSS 文件在小程序内编程了 WXSS,("▔□▔)幸好JS文件没变成WXS。

其中 WXML 使用的标签基本上都变样了,和 HTML 标签基本都不一样,只是部分语法形式比如属性设置都是一样的。WXSS 和 CSS 语法一模一样,需要特别注意的是里面 CSS 是 flex 布局。

小程序样式表使用的组件的尺寸大小是rpx,这个属性厉害了,前段时间的朋友圈全屏广告就是用到这个解决素材在不同屏幕上显示效果不一样的问题,用到了前端中rem属性,根据屏幕宽度设置像素大小。唉,这个东西被一群麻瓜们称之为H6技术,真是无语。不过这真是个创新,安卓的为了解决不同分辨率机型的适配可是费了不少功夫。

这其中的样式是大多数引用的WeUI的,微信去年(?)开发的前端样式库。小程序包括了基本视图组件、表单样式组件、媒体组件、地图和Canvas组件。

小程序不使用DOM结构,而是使用数据绑定来构建页面。这里可以把标签简单看作

标签。

<view> {{ message }} </view> <!--page.wxml-->

Page({
  data: {
    message: 'Hello MINA!'
  }
})//page.js

小程序还提供了条件渲染、列表渲染、模板等,如果你使用过React或者AngluarJS的话,对这个应该很熟悉。

每个page文件夹是不同的页面,里面包含此页面的所有的样式和脚本,用不同的名字区分,比如主页可以设置成index,用户主页可以设置为user。跳转的逻辑在js脚本中定义。

总结一句就是微信小程序都是前端的工作。就像以前说的,小程序需要JS以及HTML5的知识技能。如果想做的尽快学**吧。

现在第三方开发商还没有权限接入小程序开发,看文档的措辞以后可能有。

为什么 zepto/jquery 无法使用?
zepto/jquery 会使用到window对象和document对象,所以无法使用。

我认为,未来微信会做一个Weixin Package Manager,用于模块和样式加载。做一个操作系统生态这是必须的。

目前开放的api接口还不多,目前开放微信体系的用户信息、支付、模板接口。微信封装了JsCore,我们可以通过简单调用内部的api接口使用这些接口。

其实开发的工作不多,大部分都是微信APP接手了,包括系统级API、数据缓存等等,说真的,如果APP的体量不大,服务类目很少,最好选择开发小程序而不是选择开发APP。

肯尼亚是如何成为移动支付领头羊的?

前几天看到新闻看到这样一段描述:

Facebook CEO扎克伯格在肯尼亚首都会见了许多企业家和开发人员。在移动支付领域,肯尼亚处于世界领先地位。此外,扎克伯格还尝试了许多新食物。他成非常喜欢粗玉米粉和完整的炸罗非鱼。

如果把移动支付领头羊的头衔放在一个非洲国家身上,我还是有点不能接受的,我想当然的认为是**移动支付领域是老大。马上查资料之后才发现,全世界一半的交易量都发生在肯尼亚,年交易额高达100亿美元,移动支付领域最成功的国家实至名归。

普遍买不起高昂的智能手机,那如果不用APP和蜂窝网络,非洲朋友们是如何进行交易的?短信?有可能,短信也可以直接用一段代码(比如:账户A#金额#账户B#密码),但是这个有风险呀,别人可以查看记录的呀,安全上就可以一步否定。电话语音转账?确实可以,但是要说是发展规模超过欧美**,这个也不会可能。

肯尼亚人民创新了一种不需要智能手机的支付方式——隶属移动运营商沃达丰后被分拆独立的M-PESA,多级代理的制度让这种支付手段遍布肯尼亚全国各地,甚至小村子里面的代理点都可以使用开户购物提现,就像国内便利店也可以充值话费一样方便。

image

M-PESA使用的是很安全的SIM STK技术。如果你用过早期诺基亚你应该记得,手机设置中有一个特别的运营商菜单,里面有彩铃购买,订阅新闻啦,通过空中升级(OTA)就可以获取最新的菜单和内容,或者手机拨号一个特定的数字也能打开SIM应用,这个本质上也是利用短信的通道,但不会在手机短信里面留存。

image

有信号就能转账

M-PESA利用简单地SIM卡入口,除了不能使用方便的二维码支付和好友转账以外,做到了媲美支付宝的操作流程体验。可惜的是**移动联通电信有这样方便的支付入口以及强大的技术早些年却没有做移动支付。

这个我最大的启发就是产品必须学会“优雅降级”。

如果用户还在用十几年前的IE6访问网站,我们能做些什么?不升级浏览器不让用?不会,我们可以根据浏览器的user agent让网页加载适配版本并且提示用户升级浏览器。

网速慢,我们就根据客户端Request时间过长给用户提供基本CSS视图;配置老,我们就给用户提供可选有损画质的游戏体验。

image

典型优雅降级方式

为满足用户需求,考虑用户使用环境和场景,仅仅影响部分用户体验,这就是“优雅降级”。

你还从中得到了什么启发?后台或者微信和我聊一聊。

有几个地方我在跟踪关注,如果你感兴趣也看看:

运营:淘宝正在内容电商的新尝试,淘宝二楼·一千零一夜。

产品:支付宝进行生活服务LBS新尝试,“到位”,用户可以在支付宝上发布需求,比如借一个充电宝,甚至借钱,继续玩社交。

技术:今日头条正在放大招,新媒体人工智能,说是帮助创作者减轻劳动,但是感觉未来一大部分新媒体运营将会失业。

提前祝大家中秋玩的痛快,月饼好,可不要贪吃呀~

Datalist实现搜索提示框

说明

代码来源于张鑫旭大神的博客

代码示例

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Datalist实现搜索提示框</title>
</head>

<body>
    <!--input 元素绑定 list 属性即可-->
    <input type="email" id="email" list="emailList" name="off_autocomplete" />
    <datalist id="emailList">
        <!-- add by lishude
            option 元素加入“/”结尾可以让一些IDE代码格式化正常 -->
        <!--加入label属性可以设置说明-->
        <option label="qq邮箱" value="*@qq.com" />
        <option label="163邮箱" value="*@163.com" />
        <option label="Gmail邮箱" value="*@gmail.com" />
        <option label="阿里云邮箱" value="*@aliyun.com" />
        <option label="126邮箱" value="*@126.com" />
    </datalist>
    <script>
        var eleList = document.getElementById("emailList")
            , eleMail = document.getElementById("email")
            , htmlListInit = '', arrEmailList = [];

        if (eleMail && eleList && (htmlListInit = eleList.innerHTML) !== '') {
            // 得到类似["qq.com", "163.com", "gmail.com", ...]的数据
            arrEmailList = [].slice.call(eleList.getElementsByTagName("option")).map(function (option) {
                return option.value.replace("*@", "");
            });

            eleMail.fnListReplace = function () {
                var arrValue = this.value.trim().split("@");
                // 修复FireFox浏览器下无限input问题
                // 如果值不完全匹配某option值,执行动态替换 
                if (arrValue.length !== 2 || arrEmailList.indexOf(arrValue[1]) === -1) {
                    eleList.innerHTML = htmlListInit.replace(/\*/g, arrValue[0]);
                }
                return this;
            };
            // 绑定输入事件侦听
            eleMail.addEventListener("input", function () {
                this.fnListReplace.call(this);
            }, false);

            //  载入即匹配
            eleMail.fnListReplace.call(eleMail).focus();
        } else {
            eleList = document.createElement("datalist");
            eleList.innerHTML = '<p class=sorry>抱歉,当前浏览器不支持HTML5 datalist.</p>';
            eleMail.parentNode.appendChild(eleList);
        }
    </script>

</body>

</html>

跨版本升级Ubuntu

upgrade ubuntu

当前Ubuntu稳定版本为 16.04 ,官方已经释放出新版本 17.04。

step

  1. 打开系统设置->软件和更新->更新->选择不支持的更新。
  2. 打开命令行,运行sudo apt update
  3. 继续运行sudo update-manager -c -d
  4. 按照提示操作即可,中途有几处需要确认。

Ubuntu server update

run do-release-upgrade

ubuntu wiki

To upgrade on a desktop system:

  • Open the "Software & Updates" Setting in System Settings.
  • Select the 3rd Tab called "Updates".
  • Set the "Notify me of a new Ubuntu version" dropdown menu to "For any new version".
  • Press Alt+F2 and type in "update-manager" (without the quotes) into the command box.
  • Update Manager should open up and tell you: New distribution release '16.10' is available.
    • If not you can also use "/usr/lib/ubuntu-release-upgrader/check-new-release-gtk"
  • Click Upgrade and follow the on-screen instructions.

To upgrade on a server system:

  • Install the update-manager-core package if it is not already installed.
  • Make sure the Prompt line in /etc/update-manager/release-upgrades is set to normal.
  • Launch the upgrade tool with the command sudo do-release-upgrade.
  • Follow the on-screen instructions.

竞争对手门店为何总在一起?

以前经常看到肯德基和麦当劳总是开在一起,来到北京后发现房地产中介链家和我爱我家也开在一起,这是为什么?

切户?也就是抢客户,你有优惠我也优惠,而且更大。

不过我后来思考也不对,商家一点儿也不喜欢竞争。想想我们去多家店聚在一起的餐厅,有很多家但是几乎没有一家做相同的食物,你做饭我就做面,这就等于一家垄断了一个区域的一个品类。有个概念是商圈,就是不同品类商家在一起能更大化的聚合客流,提高每家的曝光量。

但是竞争对手也开在一起就有些不合商圈的规则了。换个角度再重新思考一下。

如果你要开一家店,你会考虑哪些问题?如果按照我的思路,所有的选址依据都得参考「目标客群流量」和「选址成本」,那么问题来了当我们确定一个商圈或者一个写字楼的时候,客群流量均衡,租赁成本也差不多,那该怎么选?

换位思考,如果我是顾客的话,我该选哪家店?口味**惯、服务、价格等等,我们假设这三点所能选择的店铺都能提供一样的品质,那么我们该怎么选择?那肯定哪家离的近就去哪家。是不是这个道理?

那我作为商家只要选一个离用户最近的地方就可以了。我们做到计算题吧,假设一条100米的步行街,我们有5个地点选择而且每个地点都平均分布在这条街道上,然后我和竞争对手选择。

1——2——3——4——5

5个可选点位

对于顾客而言,最好一家放在2点,一家放在4点,这样两家都能方便的服务两边的用户,而且两家能各包揽一半的用户。

1——A——3——B——5

平均获得

但是对于商家而言抢占更多的用户才最为重要。这时候A向中间靠拢,这样A商家就能多抢占B一些用户。

1——2—A—3——B——5

开始侵占

这样子作为A就有可能多获得以前B能获得部分红色区域用户。这时候B商家也不会放弃这部分用户,也开始向A商家用户群体迈进,这样子有形成一个平衡。

1——2—A—3—B—4——5

又变成平衡

...

可想而知,经过多次竞争然后平衡,最终会变成这个样子,也就是两家变得我们看到的「相爱相杀」。

1——2——AB——4——5

纳什平衡

其实这又变成第一次的平衡关系,但是你不做竞争对手就会做。

这篇不是讲博弈论。

大二时候看到一个公众号评论,谈论沙县小吃和桂林米粉这两家知名的小吃连锁在吃前吃后收钱的不同策略的原因,突然有点汗颜,明明都是我们身边的事情,自己为什么就只能知其然而不能知其所以然?

物联网是前端工程师的新蓝海吗?

作者|刘洋洋(阿里loT前端负责人)
编辑|Emily

物联网是继 Web 、无线之后的又一次重大技术变革,在变革的大潮中,程序员的知识体系和思维方式将面临全面更新。

前端开发的历史

在准备这个live的过程中,我回顾了前端开发短暂的历史,有几次我认为非常重要的变革。

第一个是富交互。

十年前我们聊到富交互,首先会想到的是ActionScript,微软也出过一个叫Silverlight的方案,后来随着前端单页应用的流行以及大量复杂交互框架的出现,让前端开始从切页面进入到复杂的Web应用开发,我认为这是前端开发非常重要的转变。

第二个是无线化。

七八年前,我们讲到无线开发,最先想到是Objective-C或Java,后来随着HTML5的流行以及React Native和类React Native方案的出现,让前端在无线上面有了非常大的场景和空间。

第三件事是Node.js的出现。

2009年Node.js发布,很快开始大规模流行。在那之前,我们讲到前后端分离,可能前端工程师只能触达到服务端应用的模板层面。讲到工程化,我还记得我们当时在用一个Java社区的构建工具Ant,来做前端的构建。Node.js流行起来后,前端开始在服务端、工程化上有了非常多的可能性,出现了“大前端”的概念。

下一个节点可能是什么?我认为有可能是物联网。

现在,所有的人都在谈物联网,从政府到金融投资到技术界,物联网正在引发新一次的技术革命。那么在这个时代到来之前,前端工程师可以做什么?应该怎么做?是我们今天主要要聊的话题。

先来看两张图,第一张是美国著名的咨询机构Gartner发布的2016年新技术成熟度曲线。可以看到,物联网相关的行业方向已经占了非常多。像VR、AR等技术已经开始进入到大规模应用的阶段,IoT平台等技术正在快速上升中。

image

第二张是国际标准组织IEEE发布的2016年的IoT行业技术人员报告,它提到,目前在美国,JavaScript语言在IoT行业中的应用排名第三,仅次于Java和C,Node.js也有31.5%的热度。在他们2015年的报告中,JavaScript只有30%多,Node.js只有20%多。这一年过去,JS在IoT中的热度持续上升。可以看到在美国,已经有很多的物联网工程师在使用JavaScript和Node.js来做物联网应用开发。

image

目录

我们这次Live的内容大体分为三部分。

  • 第一部分简要介绍什么是物联网,以及物联网的技术链路。
  • 第二部分讲前端技术以及JavaScript这门语言在物联网中的应用及前景。
  • 第三部分讲前端工程师如何切入IoT,如何找到新的方向,以及前端工程师的成长问题。

什么是物联网

物联网这个行业特别大,没有一个人敢说自己是物联网专家。物联网,Internet of Things,首先它是internet,是以互联网为基础的。传统的互联网,我们认为是电脑之间的连接,那物联网其实就是物之间的连接。

认识物联网

什么是物呢?像我们熟悉的智能家电,家里的空调、音响,都已经可以方便的联网。同样还有一些大家不太熟悉的物,比如在工业领域,在**大西北,有非常多的林场、风力发电厂,已经在物联网方面有了很多的应用。比如风力发电机会接入网络,它们在大沙漠里运行,不需要人去值守,它们可以通过数据和算法来监控和预测,比如提前半年告诉你这个风机要出问题了,需要准备更换。同样在城市里,也已经有很多东西开始联网,比如红绿灯、路灯、水文气象监测站、交通治安摄像头。还有些比较夸张的,比如杭州在尝试把垃圾箱联网,就可以通过传感器来分析垃圾箱里垃圾是不是满了,它的腐败的程度是不是该换了,来优化垃圾车和环卫工人的路线和工作,可以很好地提高效率和节约成本。

所以大致可以把物联网分为3个方向 : 一是家庭和个人,二是工业服务业,三是城市。

很多人都相信,人工智能机器将取代人类的绝大部分工作,人将不再需要工作,会进入到一种类似于共产主义的社会,专心生活。在这个乌托邦到来之前,就需要物联网的深入发展,将工业、服务业、城市、个人的方方面面都联网,并且在云端有大数据、云计算、人工智能来驱动这些的运行。

物联网的技术体系

简单来说,物联网的技术关注三个端:硬件端、用户交互端、云端。三个端通过网络来互相连接,这是最简单的模型。

细化到每个端,又有非常细致、复杂的技术。比如硬件端,就存在各种形态的硬件,有简单的嵌入式设备,有可以高级操作系统的带屏设备,有只负责数据采集的传感器,也有通信网关类的设备等等。
用户交互端也有很多形态,比如常见的APP、 Web、桌面交互,也有新的VR、AR、语音交互,还有像政府、工厂使用的大屏、控制台等交互。

云端同样也很复杂。需要处理数据的收发和处理、大数据计算、人工智能,还有各种设备间的互联互通。每个细节都需要很多的技术方案去处理。

下面我们就从通信协议、芯片、操作系统、平台来详细说一下。

协议

我认为物联网最重要的就是协议。 协议分两部分,一部分是底层的网络协议,一部分是上层的应用协议。 物联网是基于互联网的,在传输层主要还是基于TCP构建的通信协议,包括HTTP协议,及MQTT等专门为物联网设计的协议。在组网层面,存在适合各种不同场景的协议。比如针对家庭大量小型设备的ZigBee协议、Sub-GHz的协议,以及针对城市的NB-IoT等协议。上层应用的协议主要关注设备和服务数据的解读、处理和存储,以及如何联动和控制。

芯片

另外一个很重要的部分是芯片。每个计算机都有CPU,同样,在物联网的每个端都需要有运算的能力,也需要有CPU。CPU有很多种,像我们常说的嵌入式MCU,以及包含基本的软件系统的SoC,都是CPU在物联网上的不同的形态。

在CPU之外,物联网中很重要的一部分叫做模组。模组就是把常用的功能封装成软件、硬件、板卡一体的方案,比如说我们讲的WIFI模组,蓝牙模组,以及ZigBee模组,都是需要由模组商提供集成化模组,便于组装和生产。

操作系统

在芯片之上,还需要关注的是操作系统。Windows、Linux是通用操作系统,虽然Linux、Android在物联网中很常见,但另外的大量嵌入式设备中,对计算能力要求不高,但要求低成本的设备上,更流行RTOS,即实时(Real Time)操作系统。这些操作系统不需要非常强大的进程管理,但需要精确的时钟控制,可以通过事件中断的方式来完成基本的硬件操作。

平台

最后一块重要的就是计算。我们都了解云计算的概念,在物联网中,还有一些其他形态的计算,比如边缘计算,或雾计算。边缘计算是什么意思呢,因为物联网设备特别多,全都跟云端直接通信的话,在连接管理、数据传输量上都是很大的浪费,网络延迟也存在限制,所以完全可以在网关、路由器等网络节点中,或者在工厂、家庭的集中的控制中心里完成计算。

边缘计算节点跟云之间需要数据同步、离线化等细节处理,这样就可以在用最快的时间或复杂的网络状态下完成基本处理,同时保持跟云端的结果同步。

在物联网行业里面出现了大量的云平台服务,亚马逊、IBM、微软,包括阿里都在做面向IoT的平台,这些平台主要的功能是提供对数据和设备的管理,另外在这之上提供了大量的服务,让开发者可以高质高效地完成物联网开发。

行业现状、应用、前景

行业现状

物联网行业最大的特点就是角色特别特别多,环节层层相扣。从芯片来讲,从CPU厂商到模组厂商,到各种家电的方案商、板卡商、工业设计再到生产组装,以及软件研发、售后、用户交互等等,有非常多的环节。这种复杂的供应链和产业链,给这个行业带来了一些困境。

困境一:成本
第一个困境我认为是成本。尤其是在家电这种竞争已经白热化的行业,它的链路特别长、角色特别多,所以每个环节对成本的控制就要求非常高,几毛钱、几分钱的成本都要去抠,导致用户体验等比较关键的事情上容易屈从于成本。

困境二:供应链
第二个困境就是供应链的问题。一个新的技术经过层层角色,最终到用户手上的产品,要经过很长的时间。比如一个芯片上的技术创新,需要经过芯片研发、代理商铺货、模组商调试、板卡商对接、生产组装、软件研发等一系列的过程,最后到用户手上可能需要一两年的时间。

困境三:效率
基于前面两个困境,它的创新效率会非常低。因为整个行业,尤其是家电、工业、城市这种行业里面,每个环节的技术创新都需要大量的供应链的更新、招标成本的控制核算,才能实施下去。
这样下去导致一个悖论,就是用户希望有更好的体验,但是这个行业的成本和惯性不允许厂商来进行革命性的创新。为什么我们觉得智能家电一直这么不智能,其实很大程度就是因为这样。即使实验室里已经有了很好的技术、很好的体验,但是经过层层的角色和环节,到了用户的手上,就会有很大的延迟且效果打了折扣。

3个好的发展趋势

同时我们也可以看到一些好的发展趋势。第一是硬件成本不断降低,性能不断提升,同时用户对体验的要求越来越高,这样厂商就会慢慢把效率和创新变成主要诉求。

第二个是平台化和产业革新,国内像阿里、百度、小米都已经开始尝试用平台化和影响产业链的方式来推进行业发展。让中下游的传统厂商和中小企业可以省掉很多中间环节,方便、快捷地更新技术和体验。
第三个是人工智能技术在这个行业里不断渗透,比如我们现在已经很习惯语音交互,或者一些新的视觉上的交互方式。新的技术概念可以让用户认知和接受,反过来推进在行业的落地,对这个行业是很好的促进。

JavaScript 与物联网的火花

JavaScript的优势

JavaScript 程序员有一个梗,就是阿特伍德定律:所有可以用JavaScript实现的东西最终都会用JavaScript实现。这个是阿特伍德在2008年说的一句话,后来09年Node.js出现后,不断地验证它,JavaScript开始在各种领域有了非常大的发展。

性能不再是问题

综合来看无非有这样几个原因:一是V8的出现解决了JavaScript的性能问题。

灵活

作为一门脚本语言,它在各种端、各种平台上面都有一致性的实现,在服务端、网页、无线客户端、嵌入式里面都可以一致的使用。

简单灵活的另一个体现就是它可以动态化下发到各种平台和应用,实现热更新,这是非常重要的一个特性。

社区活跃

它的社区非常的活跃,在各个行业、方向都有大量的开发者和模块。基于这些优势,JavaScript在物联网上已经成为了非常受欢迎的语言。下面我们从几个方面讲:一是JS如何驱动硬件,JS硬件框架,JS在物联网平台以及人工智能上的应用。

JS如何驱动硬件

首先我们看JavaScript在硬件里是怎么玩的。

分为两种方案: 一种就是把Node.js、V8直接放进一个硬件,这样的好处就是直接可以使用Node.js开发方式来开发,并且使用NPM这样的包管理工具和社区生态。它的劣势就是Node.js的运行内存最小是64M,对硬件的要求比较高。

所以就出现了第二种,嵌入式的JS解析器,现在比较流行的有Duktape和JerryScript。这两种实现方案类似,它们实现了自己的语言的解析器,然后加上一个事件驱动的模型,这两个用的都是LabUV,跟Node.js是同一个事件的引擎。有了这个之后,他们可以把解析器做得非常小,大概只有100多k的RAM和ROM,能完成JS的解析。

JS硬件框架

既然JS可以跑在硬件里了,上层就需要给开发者提供一些框架,包含硬件操作API、事件管理、输入输出接口、流控制、时间定时器控制等等。

基于JS的硬件开发框架大概有几种形态:一种是基于Node.js的,比如美国有家创业公司Tessel,基于Node.js环境提供了开发板,开发者可以用Node.js的方式来开发硬件,这种方案非常适合不计成本但要求效率的硬件工作,比如原型验证等。

第二种典型方案是非Node.js的,以国内的Ruff为例,它使用JerryScript作为解析器,其特点首先就是非常小,同时JerryScript的API兼容Node.js,是Node.js API的子集,Ruff也在尝试把NPM的包使用在Ruff上面。Ruff的理念是软件定义硬件,它希望把这样一套Ruff的系统、框架、生态来驱动硬件的开发,并且其成本可以控制到可以量产的水平。

第三种方案是直接面向行业生态的,比如说三星的IoT.js,它的技术方案跟Ruff非常像,也使用JerryScript,JerryScript本来也是三星开发的。它通过产业联盟、深入供应链等方式,在工业、产业上有更多的推进。

下图可以清晰的看到Node.js方案与类IoT.js架构的异同:

image

JS在物联网平台以及在人工智能上的应用

我以亚马逊的IoT平台为例,介绍一下JavaScript在平台体系里面可以做些什么。

image

如图,亚马逊的IoT有几层关键技术:一个是IaaS基础设施层,就是它的虚拟主机、数据库、存储等基础应用。

在这之上,亚马逊有个规则引擎服务叫Lambda,我认为它更是一种开发模型。它把应用都抽象成一个简单的触发和执行的模型,一个event和一个callback。同时它提供一种容器,让开发者可以用各种语言开发Lambda脚本,放在这个容器中统一运行。容器的好处一是可以统一管理脚本,二是可以有大量的服务API扩展,亚马逊及三方提供的服务都可以作为容器的插件来提供给lambda脚本调用。Lambda是AWS构建上层应用的重要的框架,同样在物联网这种大数据量、有各种联动触发的场景里非常适用。

第三层是它提供了一个IoT平台,主要负责管理设备的连接、设备的控制、设备的数据管理。这边有个非常好的概念叫Shadow,就是影子,它维护了一个虚拟的设备的模型,这个模型可以让你的用户端跟你的设备端、云端的开发解耦,各个端只需要针对Shadow来编程。Shadow同时会负责离线状态下的各种状态保持和同步,对开发者非常友好。

在这之外,它提供了第四层叫Greengrass,是一个硬件端框架,开发者可以在把Lambda、Shadow等编程模型和框架一致化的在硬件中开发,并且可以做到在本地网络、在不跟云端通信的情况下来实行本地的控制。

这是亚马逊在IoT上一个非常完整的架构。

这个架构里面,JavaScript可以做什么呢?

答案是什么都可以做。它每一层都是支持各种开发语言的。基础设施肯定可以支持Node.js,Lambda有JavaScript脚本的实现,Shadow同样也提供了硬件端、PC端、客户端的JS SDK,Greengrass里也提供一致化的JavaScript实现。也就是说,你使用亚马逊的平台或者搭配一个JS硬件开发板,比如Ruff或IoT.js,你只用JavaScript语言就可以完成从硬件到云端、到用户交互端的所有的开发。

相对于传统的开发方式——硬件里面需要用C、汇编,去编译、烧录、串口调试;云端需要Java,要构建、部署;用户端native方式开发iOS、Android、桌面等不同的应用——在新的模式下,只用一门语言,JavaScript,就可以非常方便地完成各个端,基本上是无缝的。并且它的编程模型和框架是一致的、很多脚本可以复用和共用,这样的方式是一个非常大的变革,对开发方式、开发效率、创新效率、成本控制都是非常好的变化。

物联网与用户交互

前端的新挑战

前端工程师,包括传统的前端用户体验的开发技术在物联网中有哪些新的应用场景和挑战?
前端开发的老本行是用户交互界面,传统的界面开发在物联网行业会遇到更多的挑战。一是解决刚讲的行业的创新的成本和效率的困境,物联网行业的用户交互的端很多,有PC、无线、控制台、设备屏幕等各种媒介。行业中存在大量的中小厂商,需要模块化等方式快速搭建UI界面。

对界面开发来说,第一,需要给各种不同的行业客户提供模块化的快速开发方案。同时要保证用户体验,保证执行效率和稳定性。现在一些好的方案如React Native,在这个场景下面就有更多的施展的场景。
第二是可视化在物联网行业有了更多应用场景,尤其是工业生产、城市等领域,需要大量的数据可视化和流程可视化,并且对精度的实时性要求比较高,同时出现了矢量、3D渲染等新要求。

第三,Node.js开发及框架设计,比如刚才讲同一门JS语言需要在嵌入设备、网关设备、云端来开发一致性的应用,这个对Node.js的不同场景下的框架设计、库实现、包管理、工程支撑、开发社区等都是新的挑战。

同时,物联网行业出现了一些新的交互媒介,比如VR、AR、语音交互、视频交互,目前在这些方向都出现了很多新的框架,比如如VR方向的A-Frame、WebAR、Renderloop 等; AR的AR.js、argon.js等,我们熟悉的Three.js也在AR的时代出现了很多扩展和库来实现AR渲染;对于语音交互,主要的挑战是内容和服务的管理,比如在智能音箱里需要对接订机票、买东西、查天气、叫车等三方服务,这背后需要一个复杂的NLP领域管理和对接各种行业服务的框架,需要一种灵活、动态部署的胶水语言来连接,JavaScript是很好的选择。亚马逊的ASK就是一个语音交互框架的好案例。

前端工程师如何切入物联网并建立竞争力

前端工程师如何建立竞争力?

前端工程师在这个行业里面怎么去成长、怎么去建立竞争力。我觉得最重要的是你先去了解它、先动手玩。你要去了解JavaScript在前端、在硬件、在物联网平台里是需要怎么做。最简单的就是买个开发板,我强烈推荐从Ruff来入手,了解使用JavaScript、Node.js的方式来开发一个硬件的应用、硬件的驱动。同时Ruff已经支持很多的物联网平台,比如说向微软、亚马逊的平台都支持。目前亚马逊是免费一年,你可以去玩Lambda、Shadow,看是怎么回事。

因为这个行业特别新,并且特别大,所以可以找到非常多的点去贡献、去建立影响力。你可以去尝试做一些科研项目,在社区里面参与项目,都可以很快地找到很多的小伙伴跟你一起来玩。

第二部分我们可以用Web思维解决行业的困境。Web天然的就是动态更新,灵活部署,这个东西在物联网行业是非常珍贵的特性。怎么样让你的硬件里的程序来进行方便的部署、包管理、动态更新,怎么样让用户的控制终端可以快速地更新体验,流畅地运行,并且可以不断升级,跟硬件同步进化,这个是我们用Web前端的开发经验可以去优化的很多地方。

第三个就是作为全栈开发者,我觉得非常珍贵的一点就是我们可以从全局、从整个用户体验的角度去推进,动用一切技术优化用户体验,这物联网行业也非常重要。因为它的端很多,怎么在各种端用一致化的模型来开发应用,来做功能的拓展,前端工程师或者JavaScript工程师在这里面有非常合适的场景。
第四点我觉得非常重要的就是用户体验,前端工程师一直是关注用户界面和用户体验。Web1.0时代,是人与信息的交互,Web2.0时代,我们关心的是人和人的交互,在物联网时代,我们应该去关心人与物、人与环境、人与生活的交互。我们关于用户体验的最佳实践和理论基础是可以延续到物联网这个行业的。前端工程师发端于Web,带着Web的基因,在新的时代,我们也必将来继承这种情怀和梦想,继续前行。

前端工程师的成长建议

我的建议有三点:深度、广度、好奇心。

第一是要有足够的深度,在协议、编程语言、工程化上有深入的理解。不管是富交互、无线、Node,还是物联网,对基础技术的要求都类似,有了这种深度,才可以去拓展你的广度。因为前端开发的领域非常大,边界非常大,JavaScript这门语言也是有非常多的场景,你在不同的场景下都可以找到一些非常好的东西去尝试、去落地技术成果。所以就需要你有强烈的好奇心,你需要对新的技术,对新的领域有敏感、有洞察力、有兴趣去探索、去挖掘。

以上是我今天讲的内容,内容比较多,时间比较短,所以很多是点到为止。我前面也建了一个群,后面大家有需要也可以一起加入这个群来交流(QQ群:627103455)。

Q & A

Q1:从技术上看,NB-IOT已炒作了一段时间,智能家居却仍以蓝牙、WIFI为主,除了技术不成熟外,是否有其他原因?
A1:NB-IOT是一种数据LPWAN窄带物联网技术,并由通信运营商控制,可以理解成一种类似3G的网络,它的传输速率不快,但是功耗特别低,连接更稳定。所以对市政这类的设备,比如说路灯、垃圾桶,是非常适用的。但它明显不适用于智能家居,因为家庭里面都是有电有稳定网络的环境,不需要来直接跟运营商网络通信。我认为NB-IoT在未来的智能城市和工业、服务业里面会有非常大的发展。同时窄带物联网还有一些别的协议,比如像LoRa,它是完全开放的协议,不依赖运营商,企业可以自行组建园区、城市网络。这些技术在不同的场景下都会有很多需求,但是目前在智能家居里,还是WiFi、蓝牙或者以ZigBee等更适用。

Q2:物联网和传统web有什么不一样?为什么说是前端新蓝海?感觉物联网更需要后端发力。
A2:我觉得前端工程师不要把自己局限于做Web页面的,有两种方式。第一种,你往JavaScript程序员的方向发展,因为这门语言在IoT行业确实有非常大的应用的场景。第二,你从用户交互的角度,比如在IoT的无线客户端上的场景,或者在一些用户交互界面的场景去做一些创新,这个是非常有需要的。比如说我们现在在做基于React Native在做一些家电控制上的组件化、服务化,一些开放的东西,这个对前端的开发能力和工程能力要求都是非常高的。应用的场景也非常非常大。

Q3:物联网在开放平台的发展上面现状是什么样的?
A3:刚才讲其实现在大部分的平台是来满足基本的接入、控制、数据管理这方面以及边缘计算这方面的事情。在上层,有很大的需求其实是在开发平台有要求的。比如说物联网中很重要的像内容、服务,内容的话,比如说你的VR、AR里面或者音响里面接入的这种音乐、服务,这些肯定是需要开放的。就是说在底层基础设施之上,上面需要一个很大的生态来满足各种,比如说家庭场景或者工业场景的各种第三方的服务和内容的输入输出。这部分我认为是物联网在开放平台上的很大的机会,也是像阿里这种互联网企业比较擅长做的一些事情。因为像在底层,在通信,在硬件这方面,可能像**联通这样的运营商,或者华为、中兴这样的设备商有更多的经验,但是在上层,在用户体验、在内容、在生态上面,互联网公司有更多的场景。

安装使用Gitlab进行内部代码管理

这里选择你的系统,按照提示安装。

下面以Ubuntu 16.04 LTS版本为例,以后会补充使用docker来管理 gitlab。

安装依赖包

sudo apt-get install curl openssh-server ca-certificates postfix

添加gitlab源

curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash

网络不好的选项

这里 找到你的版本号并替换下面 url
sudo curl -LJO <url>
sudo dpkg -i gitlab-ce-XXX.deb

更新源以及安装

sudo apt-get update && sudo apt-get install gitlab-ce -y

配置 /etc/gitlab/gitlab.rb

sudo vim /etc/gitlab/gitlab.rb

配置访问接口

external_url = 'http://git.example.com'

配置邮件服务

gitlab_rails['smtp_enable'] = true  
gitlab_rails['smtp_address'] = ""   
gitlab_rails['smtp_port'] = 25  
gitlab_rails['smtp_user_name'] = ""  
gitlab_rails['smtp_password'] = ""  
gitlab_rails['smtp_domain'] = ""  
gitlab_rails['smtp_authentication'] = "login"  
gitlab_rails['smtp_enable_starttls_auto'] = false  
gitlab_rails['smtp_tls'] = false  

注意:

smtp_address和smtp_domain的设置,以阿里云企业邮箱为例  
gitlab_rails['smtp_address'] = "smtp.mxhichina.com"   
gitlab_rails['smtp_domain'] = "mxhichina.com"  

关闭 prometheus

个人经验:如果不关闭的话,会一直报错。
prometheus_monitoring['enable'] = false

重启GitLab

sudo gitlab-ctl reconfigure && sudo gitlab-ctl restart

一些推荐设置

首次进入设置管理员密码,设置 your-domain/admin/application_settings

  1. 建议关闭 Gravatar 头像功能
    在 Account and Limit Settings 关闭 Gravatar enabled,国内访问不友好。

  2. 关闭注册功能
    在 Sign-in Restrictions 关闭 Sign-in enabled,如果是内部使用建议关闭,然后管理员工分配注册。

升级Gitlab

在管理后台位置 overview 界面如果红色提示需要升级,那么尽快升级到最新版本。

  1. 关闭 gitlab
    sudo gitlab-ctl stop
  2. 升级 gitlab
    sudo apt-get install gitlab -y

修改为国内镜像

详情: https://mirror.tuna.tsinghua.edu.cn/help/gitlab-ce/

vim /etc/apt/sources.list.d/gitlab_gitlab-ce.list
## 添加
deb https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu xenial main
deb-src https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu xenial main

这不会是故事最后的答案…

这不会是故事最后的答案…

高三之后的每年生日那天,我都要送自己一首歌。

《亲爱的路人》——送给你,阿德,祝你生日快乐!

上大学后,“生日”二字在自己心中就感觉越来越重要,因为在这个节日中,珍视你的人会更加珍视你。

让我好好回忆回忆20岁前的这一年——

我在远离山东老家的龙江的一所大学学习俄语,记得有许多人惊奇我的选择,不过都有一年多了,我早已习惯了东北的一切——不爱吃的米饭也能习惯,一直到暑假前仍盖着暖被——That’s just life.

十一月份初,冬天的第一场雪,不是很大,但已经非常冷了。如果我没记错的话,双十一那天,我上铺的家伙没怎么睡觉,一直刷天猫到半夜。两天前的晚上,应该是很愉快吧!雪越下越凶,一点又一点堆积到半米多高,寒冷的冬,正如那颗寒冷的心——“我放弃了”——不过还好,你的最美好的时光才刚刚开始。《ただいま、おかえり》 ,我听了一个冬天,温暖治愈。对了,还有许童鞋推荐给我的《倾尽天下》 。

十二月末 ,哈尔滨,冰和雪的世界。那是我从来没见过的冬天,松花江俨然变成了一条冰路,成百上千的人在冰上玩乐。记得高明说过一句话,今年冬天找个女朋友一起回家。我是没有什么机会了,高明,我还是看好你的。那天我献了血,高明不愿意献血,在零下二十度的**大街等了我二十多分钟。

又一次开学,我看了好多书,Кира送我的《三体》是我看到的最好的科幻小说。

四五月的长假,还有好多好多的星期六的教室,从早上到晚上是我最喜欢的时间了,会看到Доня从教室里取书到图书馆,会看到Кира洗完澡到教室凉浴袍...从前我最喜欢喝的是绿茶,而那时我最喜欢的橙汁,我会买一两瓶橙汁到教室背英语单词、看书,只有我一个人——惬意?亦或是舒坦?外面的天气不会仅仅是好天气,心情也不会总是好心情,时间长了,一日又一日,或许真的把自己逼疯了,莫名的想起了从前,有莫名的想起了未来,我叹了口气,合上书,走出教室,天气恰如那时的空气,压抑得很,不想回宿舍的我开始绕着学校走,至今我仍保留了这个习惯。

五月末,绥化,会有好似秋景的落叶。阴晴不定的天气一直持续到六月初。晚自习,不变的节奏,似乎也出现了点状况,外面的广场不会有梧桐树叶被风吹打散落的场景,而教室却出现你的哭声。好似相同的场景,我慌乱了,乱糟糟的信息疯狂向我涌来,我该怎么办才好?但那不过是世界上与我无关的一件事而已。那天晚上,我走在还算寒冷的路,胡思乱想。

六月,越来越温暖。你可能知道九思湖在哪,但未必也知道九思路在哪,路走多了,总觉得那路不再仅仅是路。那天我删除了手机中所有伤感的歌,或许很多人都会体会到那种感觉。夜晚开始变长,熬夜也会是家常便饭——或许,或许我真的找到了对的路。

我记得我妈对我说过,我出生后很少哭,而那天晚上我也没有哭,若无其事的打开电脑,打开游戏——只不过在最后按下了Alt+F4。第二天,我默默祝福了学弟学妹能考个好成绩,然后绕着学校走了不知多少圈,我开始仔细看学校的每一处地方,中午时不是很饿的我吃了好多。我曾用“难过”形容我的无力感,没有,我没有用“难过”这个词形容那时的心情——我看着天空,没有仰望四十五度角,但是我哭了.

不要说话——

七月中旬,青海湖,带着林和陈的歌,开始了我的环湖之旅。在平均海拔3200米的环湖公路我没有出现高反,不知道是红景天的原因,还是因为想起了那温暖的阳光。上坡路后,下一条路必定有一条下坡路——从远处看很陡的坡,走到眼前也不过如此——我不是三郎,而是蜗牛。两天后,青海湖畔,湖光山色,我亲眼看到了——原本远处青色的湖面变成有如大海般的蓝色,竟也忘了继续前进。

八月中旬,我还是没有完成那部小说,是想了无数种结局,竟也没有一条符合我的心意的,有点急躁地否定后在否定——原来,书德只是太害怕这个结局。滕州,在那天突然褪去凉意,荷花也在那几天试着摆脱颓败再次盛开——已经很晚了吗?对了,那个微笑,是最让我感到惊艳的一次。

现在的我有什么不同吗?仍然不会吸烟,仍然不乐意喝碳酸饮料,但现在最喜欢喝冰糖雪梨饮料。

从前说过,写东西时不适合听歌,现在看来,适不适合,有时候确实没这么简单。

这就是我二十岁的前一天,倒觉得有点失落啊。已经二十岁了,但未来还有很长的路要走,今天也将成为过去,唯愿你安好。

二十岁了哟,阿德,生日快乐!

也祝远在千里之外的许童鞋生日快乐!

14.10.20 前

写在22岁前

类似这篇,十八岁那年生日那天也写了一篇随笔。那时候我把自己定性为爱纠结也爱折腾,四年之后,爱折腾的心小了不少(比如 MIUI 变成了稳定版),不过这纠结的心还是留下了。

大学时候我把这种“纠结”演绎成了“选择困难症”,尤其对于「吃」方面,虽然我对食物要求不高,但——自己一个人订外卖没有半小时根本停不下来,一起出去吃饭一般都是让朋友点餐。有个玩笑挺适合我的,如果我困在一个孤岛上,但是这个孤岛上有无数我没吃过的美食,那我一定会饿死在岛上。

过去这两三年,每每和新朋友认识之前都被问到我大学是学什么的,他们都很惊讶我是学俄语。对于选择大学学俄语的理由,给别人的回答,我感觉都有五六个版本了,实话说这只是在为自己当初选择做一个合理解释。不过得说一下,我选择学**俄语是没有一点犹豫的。

1

大学第一次运动会。那天下雨,大雨。

不过是阵雨,我刚打开伞没几分钟,就下的差不多了,变成淅沥沥的小雨下个不停。当我像往常一样随意把伞折起来时,却被一个女生教训了一顿,“你怎么能这样收伞?!”我有点错愕,然后她告诉我,应该按照伞的皱褶一个一个地仔细卷起来。

第一次,听到这样细腻的收伞方式,也没想到喜欢一个人会是这样简单。

我总是说了很多要做的事情,梦想或是目标,却是没怎么去认真努力实现过。所以她总是一边凶巴巴嘲笑我,又一边鼓励我努力去实现目标。

那个夏天,我实现了所有的诺言——骑行环青海湖,把没有写完小说结尾,进入一家互联网公司实**。一年半后,与朋友一起在校创业。

选择,真的有些奇妙,如果没有去东北上学,如果没有遇到她,我或许不会这么早就坚持努力尽可能的接近自己的目标。

我时常回想一些事情,当我重新捡起初中学**的Web技术一个人做项目被难为的时候,当我在工商局和税务局办理手续特别无助的时候,当我在为了公司发展逃课去解决问题被扣学业平时分的时候,那些时候我都想些什么?

——我想我应该想想这样的选择到底值不值得。我没有多想,在这些选择面前我没犹豫。

2

我似乎特别适合帮别人做选择。几个月前很多人问我该怎么选择,学弟学妹问我“迷茫不知道怎么选择”,同学问我“去考研还是实**”,朋友问我“去国外还是留在国内”。

他们或许不知道,那时候我也面临着选择,“去北京实**还是留下来继续做”。其实我心里特别清楚,如果伙伴愿意留下来,我也会留下来。今年三月份,伙伴告诉我暑假前就走。

那个时候,我经常换位思考,思考这个团队每个人,我特别明白他们留在学校这里的风险,我也特别感同身受一次又一次的挫折对一个人的打击到底会多大。

听到过这样一句话,能把生活打趴下的男人不多,可男人们胸口都烙着两个字:不服。 要挨多少时间的打,吃多少岁月的亏,那与生俱来的,如胎记一般的两个字才会消失,这不好说。无需怀疑的是,被生活劝降是早晚的事。

今年开学之后,家里人还有朋友就问我,大三之后去哪里实**。或许他们都感到了我会离开。

我告诉他们,我会来北京。可能不会回家。

3

7月份底我来到北京。

来之前,我在朋友圈说了一句,所有的成长都是因为站对的了地方。

第一天,我站在五道口搜狐大厦下面仰望星空,嗯,雾霾挺重的。那天我才知道有一个叫做快手的互联网产品已经是国内流量的前三甲了。看来我挺无知的。

我相信我选择对了。

我的成人礼,十八岁开始思考人生

我的成人礼,十八岁开始思考人生

十八岁真是个好时节,可以尽情的谈人生谈理想,没有人会说你幼稚。高三开学,又是一个光景,分秒时间带来的不只有压力,还有难以言表的煎熬。开学是班主任给每个人发了一张小纸条,让我们写下自己的高三宣言和要求。在高三宣言栏上我想写下“无悔高三”,这四个字很平常的四个字,连我都不知道为什么会这样写,像是应付工事一般,没有目的,没有感情(现在想想应该是“没有感觉”)。直到我写下这四个字的时候,我才发现自己还是渴望奋斗渴望成功。我对自己的“要求”是“不纠结,不折腾”。是的,高三以前我纠结了两年年,也折腾了两年。总是听别人说高三如何苦如何累,不知不觉自己也堕入这里了。高三到处都会有激情,也会有无助。赵喜欢摇滚音乐,喜欢自由的人生,不喜欢人情世故的圆滑,不喜欢考试和分数,只寻求平凡的生活就知足了(现在的他呢,他是怎么想的我就不知道了)。他和我不一样,我有自己的理想,我总是想反驳他,但后来也知道自己没有理由反对他们的选择,因为生活本就没有绝对的对与错。

我知道他要的不是绝对的自由,毕竟我们每一个人都要生存。至少说来,这也是他的理想。我总是说,我想做天上的一朵浮云,就像鹿丸一样,讨厌麻烦,讨厌努力,可我也渴望努力地实现自己的理想。

我对同桌说,大学后我要创业。同桌却把一大堆失败理论摆在我面前。我只说,我现在敢想,将来敢做,至少在这一点上我就比你们强。在那时,我努力地摆脱一切烦恼,思考未来该怎么做才好,如何做才能成功,面对他们的嘲笑,我无动于衷,我不知道他们有无恶意,但我想说,那种感觉真的让人厌恶。

有人对我说,现在谈理想还太早。

是呵,从年少开始,我都不知道改变了多少选择了。邻家大哥哥老是欺负我,我当时就立志要当个军官;看电视喜欢看自然科学类的节目,我就想要当一名像爱因斯坦一样的科学家;当我求知若渴,疯狂读书却找不到合适的书时,我就想要编辑一本全方面的百科全书。曾经,我还想当一名写手,类似作家的职业,如今看来,恍若晨烟。

小学时候,我的好奇心很重,喜欢探索自然科学的奥秘,喜欢谈论连自己都不太懂得相对论。不懂的东西很多,想鼓捣的东西也很多——想方设法拆开石英表,结果自己用砖头砸都没砸开。现在想想当时自己是多么“可爱”啊。不过我想说,那种感觉真的很好。

初中时我遇到自己一生的兄弟。也许自己在某一方面懂得太少——那时的我不懂上网,不懂喝酒,可他们懂得很多。耳濡目染,虽然有人认为那些着都是不好的事情,但是现在的我仍然很肯定,那对于我是非常正确且宝贵的经历。现在仍记得我们三人在最后面一排,有点可笑,有点逆反,那种生活真让人怀念,没有什么心烦事。(姓名被作者隐藏)

可能当人开始思考人生是,人生道路就开始改变了。为了中考,我变的压抑,玩着fps射击游戏,玩世不恭的心态似能坦然面对一切,而这种心态也影响着现在的我。那时候,我开始续起胡须,妄想这能掩饰自己的彷徨和无奈。

时间来不及我享受,就这样,磕磕绊绊地进入高中。高一时我不知道自己是怎么样的,也许真的犯了许多不该错的错误,说到后悔,对于某些事,追悔莫及。由看小说正式演变成为写小说是在高二,自己心里真是在较劲,也确实激发了许多灵感,在那时,我也确定了自己的理想目标是“造轮子”。高中时,我发现对一切网络游戏都免疫,连现在的我都不太明白自己当时为什么这么决绝。

记得高一时,有位女生说我总是郁郁寡欢,没点生气。我也不明白,那时是怎么了,可以说的是那时的我学会了(我至今都改不了的)沉溺自我。那时的我是个差生,无视分数和成绩。有人说,人的生活全部体现在他的脸上。别人说我太深沉的做作,或者说我深沉的成熟,我想说,我不是那个饱经风霜但依然勇敢活着的人,我知道我脆弱的可怕。如果人生是个故事的话,我也希望有个温暖的结局。

不知道自己是什么时候喜欢上历史和文学,高一我说,大学要学历史,但现在我知道,这已经是个不可实现的理想(如今我在黑龙江绥化学院学习俄语)。我从小就喜欢物理,但现在我十分厌恶它,它没有给我带来探索自然的快乐,我鄙视那无聊的习题,但我又不敢放弃它,因为它是我应试的基础。

我说,我喜欢写小说。不知道这是不是习惯,每天梦境中都能浮现一些人和事,而我习惯把它记下来,一个又一个的场景,在我笔下被描绘,我感觉到了充实的快乐。那是一种什么样的享受,也许当你静静地思考才会感觉到吧。

现实的确很残酷,我总是把我的文字里的人儿塑造一个更加真实些,他们也有不幸,他们也会有自己的思考方式。或许,我写他们就是在写我自己吧。

老妈总是和我说,别想这么多,想那么多没用。可是,一旦人开始思考自己的人生是,那就再也收不住了。

“你知道人为什么有烦恼么?就是因为我们想的太多了。”

“人一生下来就没有选择,浑噩的学习吃饭睡觉,当你真正了解你自己时,你就有烦恼了。也可以说人一生本没有选择,可当你自己有选择权的时候,你不会轻易放弃这种选择。”

“我想探寻一种独特的美,徒劳的是当我找到时,我却没了勇气和能力去承担。”

“我不知道对你是什么样的感觉,说不清,道不明,我不敢掩饰看你的眼神,但我又不得不逃避你的目光,因为我害怕。”(这也是我想对她说的话,她不知道,但她一定能感受到)

这些东西没有几个人了解,写出来也没对几个人看,算得上“孤芳自赏”吧。我喜欢听音乐看电影读书,但我不是文艺青年,当然也算不上2B青年。

我喜欢不刻意描述事实,不太喜欢复杂多变而又矛盾但喜欢朦胧中和的写法。

就像我的小说,我的复杂而又简单性连我都有点琢磨不透,但是世界上又有几个真正了解自己的?!

十八岁,总算个新的起点,也许以后的我还是一个爱纠结并且爱折腾的人。

:before和::before的区别

在一次项目中,有一次要用到::selection伪元素,然后开发同学问我,CSS中一个冒号和两个冒号有神马区别?

这好像真的是个问题,或许很多前端同学对此都有疑惑,查了些资料,证实了下两个符号的区别,简而言之:单冒号(:)用于CSS3伪类,双冒号(::)用于CSS3伪元素。

W3C关于CSS3选择器的规范中有一段描述:

A pseudo-element is made of two colons (::) followed by the name of the pseudo-element.
This :: notation is introduced by the current document in order to establish a discrimination between pseudo-classes and pseudo-elements. For compatibility with existing style sheets, user agents must also accept the previous one-colon notation for pseudo-elements introduced in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and :after). This compatibility is not allowed for the new pseudo-elements introduced in CSS level 3.

简单翻译一下,大意就是,伪元素由双冒号和伪元素名称组成。双冒号是在当前规范中引入的,用于区分伪类和伪元素。不过浏览器需要同时支持旧的已经存在的伪元素写法,比如:first-line、:first-letter、:before、:after等,而新的在CSS3中引入的伪元素则不允许再支持旧的单冒号的写法。

那么现在就可以完整的回答标题中的问题了,对于CSS2之前已有的伪元素,比如:before,单冒号和双冒号的写法::before作用是一样的。

所以,如果你的网站只需要兼容webkit、firefox、opera等浏览器,建议对于伪元素采用双冒号的写法,如果不得不兼容IE浏览器,还是用CSS2的单冒号写法比较安全。

Copy API

使用document.execCommand('copy',true)可以拷贝用户已经选定的内容,需要注意的是:为了安全需要放到某一个有用户出发的事件响应函数内才可以使用,如点击等事件,放入setTimeout等内是不能进行的。这一点FireFox Dev Edition会提示,可恶的是Chrome就是不提示。。浪费了我半小时。。

复制Input等表单内容

var btn = document.getElementById('btn');
btn.addEventListener('click', function () {
var inputText = document.getElementById('inputText');
//var currentFocus = document.activeElement;
//焦点定位到input
inputText.focus();
//选择input的文字范围,参数第一个为起始位置,第二个为最后位置的下一个
//也可以使用inputText.select();
inputText.setSelectionRange(0, inputText.value.length);
//document.execCommand返回bool
if (document.execCommand('copy', true)) {
    alert('复制成功!')
    // currentFocus.focus();
} else {
    alert('复制失败,请手动复制!');
}

复制div等元素内的内容

// 清理选定
window.getSelection().removeAllRanges()
let range = document.createRange()
// 生成区域
range.selectNode(this.$refs.address)
// 选中
window.getSelection().addRange(range)
// 复制
if (document.execCommand('copy')) {
  // 提示
  console.log('复制成功!')
} else {
  console.log('复制失败,请手动复制!')
}

风决定要走 云怎么挽留

风决定要走 云怎么挽留

爷爷家有个院子,里面种满了青菜果树,这儿也是阿德儿时的乐园。只因为他父母亲整日在外工作,很少在家,所以只得让阿德跟着爷爷奶奶一起住,而阿德眼中的世界大多也是来自于爷爷奶奶。

阿德永远忘不了那一天,爷爷告诉他,他的小妹回家了。阿德问爷爷,小妹是谁?爷爷只是说,她是阿德的同胞妹妹,阿德不懂,但是没有继续问下去。然后出了门,看见门口旁站着一位清秀可爱的小女孩,接着不由自主地喊了一声:“小妹,我,我是你哥哥。”女孩抬起小脸看着阿德,小声地叫了一声“哥”。

阿德的梦从此开始,可没几个月,传来噩耗说奶奶不行了。

阿德对于奶奶的印象是模糊的,甚至早已忘记了她的音容。奶奶去世只因为得了糖尿病。为了治好奶奶的病,家里的人没少费心。那是阿德六岁那年,家境并不算很好,治疗费用只得与他的三个姑姑平摊。由于大姑父的关系,奶奶被送到城里的大医院里。那也是阿德记忆中第一次去城里,他只想着奶奶生病了,要去医院这么简单,却并未懂得父母勉强对他笑的原因。阿德直到奶奶过世也未想到奶奶会离开他,唯记得妈妈对阿德和小妹说奶奶活不了多长时间了。那年夏天奶奶离开了人世。

那是个夏末秋初的季节,天气没那么好,阿德只记得奶奶发丧那几天,天总是阴阴暗暗的,却不怎么要像下雨的样子,她和小妹找到了爷爷,爷爷独自在屋子里坐着,眼角氤氲着泪水,小妹扑倒爷爷身上叫爷爷不要哭了。那场景,阿德却记忆犹新,还有爷爷那天的皱纹和白发。

就这样几天,丧礼结束。随着时间离去,阿德也渐渐忘记奶奶。父母依旧在外工作,他们只得跟着爷爷生活在一起,爷爷的印象对于他们来说是深刻的。爷爷喜欢种田,家里的空余土地全部被他种上青菜和果树,有阿德喜欢的草莓,也有小妹喜欢的葡萄。还有一颗大枣树,每年秋天,阿德与小妹在树下打枣吃,而爷爷坐在摇椅上,安慰的笑着看着他们一起玩。就这样,阿德和小妹一起上学,一起回家,阿德总是让着妹妹,妹妹也对哥哥十分关心。小妹学习优秀,唱歌十分好听。

不知为什么,小妹特别迷恋河边的那棵柳树。

“哥,你看这片叶子像不像我,小小弱弱的。”

从那以后,小妹给自己起了个小名字,小叶子。阿德说不好听,但是小妹就是喜欢,以后的以后,叫着叫着大家都熟了,都叫小妹小叶子。

夏日的小麦发着金色诱人的光芒,小河旁的蛙声那么动听,晚上的蝉鸣也没有那么聒噪。冬天雪地上,阿德和小叶子堆雪人,打雪仗,冻着手通红通红的。半个童年的时光就这样慢慢流走了,就像那河里的水。

爷爷越来越老了,不中用了,看着自己即将离去,想着阿德和小妹还那么小,怎么能安心放?但是,天不遂人意,爷爷还是离开了阿德和小妹。那天中午爷爷走的很安然。阿德和小叶子到了学校,小妹却发现自己忘拿了东西,阿德飞奔回家去南,到了家里,却看见不常回家的父母在门口站着,物理还围着一群大人,姑姑们也赶过来了。妈妈告诉阿德,爷爷走了。

小叶子见哥哥迟迟不回来,便向老师请假回家了。一路上,她总觉得有什么事情要发生,可她没想到爷爷去世了,回到家,见哥哥一个人蹲坐在门口哭泣,一群大人从爷爷物理走进走出,个个神情凝重,便也猜出了七八分。然后走到阿德身旁蹲下身问:“哥,难道爷爷...”

阿德点了点头,小叶子仿佛失去了知觉,然后瘫软在地上。阿德见状,立刻扶起她,“小妹!你没事吧!”小叶子微微点了点头,晕倒过去。阿德抱着妹妹就往家里大喊,小妹晕倒了。姑姑们看见这样,皱了皱眉头,急忙把她放在沙发上,几位年长的看了看说,没事,一会就好。

小叶子晕倒的那几天,爷爷的丧礼也进行完了。大雨下了三天,但丧礼还是办的有模有样。爷爷走后,园子就荒废了,草莓没了,葡萄架也朽了,那棵老枣树也败落了,园子里长满了杂草,再也没有青菜果树的园子了,母亲开始在家里照顾阿德和小叶子,父亲还是在外工作,很少回家。不知怎么的,小叶子的精神总是不太好,请了还几天病假。

直到这时,阿德也未知道,自己活了四年,为什么突然多出个妹妹。就像天注定一样,一定要我们去承受。

一天,阿德整理杂物的时候,发现了两块生日锁,一块是自己的,另一块是小叶子的,上面分明写着"1994.10.20",这和阿德的生日一模一样,但是他记得妹妹的生日还要在晚一个月,更令他奇怪的是小叶子的出生时间只是比阿德晚十个小时。为什么这样子,难道...阿德告诉自己不要乱想,并一心想着,小叶子是我的亲妹妹!!

小叶子的病越来越严重,令阿德不明白的是一次晕倒怎么让妹妹病的如此严重,小叶子被送到医院里治疗,看了好几天也没治好。一次,阿德放学到医院里看妹妹去,看见母亲在与医生交谈,医生表情很严肃,阿德疑惑,于是走上前在门口停着。

“活到现在已经是奇迹了...最多还有三个月...做好后事吧!”

阿德听后,身体像受了什么指令似的,让他冲进去,他要问明白,问明白94年那一天到底发生了什么。

“到底怎么回事,小妹怎么了,为什么这么多年你们一直很少回家...”

母子俩含着泪看着,命运连同那年那天,一同明了起来。

小叶子并不是阿德的亲妹妹。当年她的亲生母亲抛弃了她,因为小叶子得了一种心脏疾病,需要做心脏移植才可以治好。她只比阿德晚出生10个小时,父母决定领养她,一直让她呆在医院里,而阿德父母在外拼命赚钱只为了能有一天治好小叶子,后来医生说小叶子的病情稳定,应该让她享受一下家的生活,接着阿德就有了一个可爱的小妹妹。

阿德听后,心情复杂极了,一个人走出医院,望着天空,想着以前的种种,从未有过的悲伤涌进眼睛里。他不知道为什么不幸会降临到小妹身上,为什么人生下来就要受这么多的苦难,到头来还只是如此结局。他哭泣着,泪水落进了草地里,渗到了大地里。哭红肿眼睛的阿德找到小叶子,“妹妹,你一定要坚强,你一定会好起来的!”

“哥,等我好了,我们要一起爬山,要爬好高好高的山。”

“咱们拉钩,我答应你。”

三个月过去了,阿德每天都来看小叶子,她度过了危险期,医生说,“如果有人能捐献匹配心脏源的话,治好的机会会很高很高,不然,拖不到十八岁了。”阿德舒了一口气,走到小叶子病床前:“妹妹,你快好了,到时候我们一起去爬山。”小叶子嘴唇失去血色,脸色发白,强勉着笑容点点头。

几天后,医生同意小叶子回家做间期治疗,并承诺寻找匹配心脏源。阿德每天早早回家,帮小叶子学习。

“哥,你说我会好起来吗?”

“小妹,一定会的,如果这是一个奇迹,我相信这个奇迹会发生在你身上,叶子,你知道吗?爸爸妈妈坚持了这么多年,就是相信这个。我会陪你到那一天,无论会发生什么,我们家一起承担。”

十岁那年,小叶子迷上了钢琴房的乐曲,优美的音乐让小叶子的心情一天天的好起来,但病情并没有好转,她越来越感到害怕。

“哥,我不是爸妈亲生的,对吗?”

“小妹,不要多想,你永远是我的妹妹。”

“哥,我早已知道了,只是我不想,我不想...我不想和爸妈,和哥哥分开,我不想!”

“小妹,无论发生什么,我会陪你到最后。”

转眼间,八年过去了,小叶子的心脏也面临着枯竭,但她仍想着哥哥对她说的一切,正面面对即将发生的一切。

奇迹从不吝惜降临。就在小叶子要放弃的时候,医院传来消息说,一例匹配样本出现了,捐赠家属愿意无偿给小叶子治疗,但成功率只有六成。

没有改变的笃定,生命在那刻带着感情重新生长起来,小叶子签订了移植手术协议。阿德望着手术室的“手术中”那几个字,心里很焦急地不停,还不敢在门口徘徊,恐怕影响了手术的进程。

240分钟不紧不慢的结束了,手术很成功,但需要留院观察一个月。阿德一听便说,一个月不是我和妹妹的生日吗,我一定要给她一个惊喜!

医生观察了一周说,异体排斥反应甚微,不需要再做观察,可以提前出院了,不过这么奇怪的案例还真没有听说过。

阿德听后不由得想到,捐献者可能是小叶子的家里人!阿德想找那个捐献者的档案,但是捐献者家属说,不要泄露他们的信息。无奈,阿德只能放弃。

一个月后,小叶子顺利出院,阿德高兴的把她接回家,并在家里举行了一个生日聚会,小叶子很惊喜,现在他才知道,她和哥哥是同年同月同日出生的。

小叶子始终没有找到她的亲生父母,她仍然在这个家里生活,一家团圆幸福无比。

阿德和小叶子没有忘记他们的约定——一起去爬山。爬到山顶,他们看到一轮火日,一天要结束了,新的一天又将到来。风决定要走,云怎么挽留,但我相信一定有一个奇迹会发生。

——哥,不要悲伤,爷爷奶奶不是也安然离开了么?

——小妹,我现在终于明白,我只是不想和你说再见。

End

今日头条与信息过载

现代人的阅读通常面对两个问题:一是碎片化阅读;二是信息过载(或者说是信息焦虑)。以前也写过一篇关于“碎片化阅读”的文章,所以今天不提,这篇通过今日头条讲讲信息过载。

今日头条解决过载

每天新产生的大量信息给我们自己大量的选择,选择过多就会造成我们无所适从,时间一长就会造成信息过载。

我自己总结解决内容过载的问题有三种。第一种培养自己获取信息的能力和效率,信息过载自然解决。第二种信息管控,借助外部力量,只选择几个意见领袖推荐和编辑的文章;第三种信息筛选,让自己处在一个良好的阅读环境,内容来自各个渠道经过规则筛选出来阅读。

今日头条个性化推荐系统主要做的就是第三种。

前段时间我在公众号推荐大家关注今日头条的头条号大会,我以为今日头条会放大招——比如机器可以替代大部分编辑工作自动写文章,新媒体从业者会面临一场大考验——后来我才发现是我意会错了,其实还是基于用户兴趣的内容智能分发,只不过这回主角是短视频。

内容智能分发对于内容创作者而言就是省去建设渠道或者流量的工作,可以专心提高内容质量。另一方面用户可以获取「感兴趣」的内容。这似乎就能解决了信息获取的焦虑感——感兴趣的内容给用户一种满足感和沉浸感。

前几天我在朋友圈问了一下好友们的信息获取工具选择,我的好友几乎没有选择「今日头条」作为信息获取工具的,但是今日头条无可争议的已经成为网络流量的大头之一。

今日头条方面的最新数据称,今日头条已累计有3.3亿激活用户,8200万月活跃用户,超过3300万手机日活跃用户,平均每天每个用户使用超过6.5次,每个用户使用的时长超过50分钟。用户每天有超过16亿分钟消耗在今日头条的平台上,同时有近6亿个点击分发各种各样的内容。

不过,虽然很热门,但是对于我而言还不太好用,下面说说今日头条作为阅读工具的两个不足方面,不过随着技术发展和数据积累,下面说的两方面可能就被解决了。当然虽然自己不常用,但我会给它在桌面留个位置,一直留意。

兴趣被头条污染

今日头条官方文档说,“每个人的阅读兴趣都是大不相同的,个性化推荐机制要做的事情就是——让每位用户看到可能感兴趣的内容——这也是用户每天会「沉迷」在今日头条上的原因。”

推荐系统就是个养成系统,每个人对应一个筛选器,每点击一个内容,内容相应的标签就进入筛选系统,这里包括很多权重来再次对进入筛选系统的标签过滤——内容点击率、平均阅读时间以及人工专业评分。经过大量数据积累,我们就可以描述一个人的兴趣。

筛选过阅读让我们自己感到爽,这样就结束了吗?一个朋友说,他在今日头条的筛选系统中大概是个媚俗、八卦的人,因为他也抵不住一些猎奇、噱头的标题。他说,使用第三天他自己就卸载了头条。我们喜欢点击切合人性的内容,但我们意识中的兴趣可不是这些无聊杀时间内容呀。

为什么会这样子?现如今的头条第一次打开不会给我们手动选择几个喜欢的类目,比如科技、投资,而是直接给你推荐内容。推荐的内容从哪里来,第一次打开头条能获取你的手机、地区信息,根据这些信息我们难以推荐精准信息,但是我们可以推荐大多数人喜欢的内容,那大多数人喜欢的互联网内容是什么?所以,一些猎奇、媚俗、八卦的内容就随之扑面而来。然后,我们都被带着贴上了“喜欢娱乐八卦”、“野史猎奇”这样的标签。

不过得说一下,头条一直在治理标题党和减少**猎奇媚俗内容,比如“我不感兴趣”按钮以及人工审核,不过目前来看还是无法避免内容低质量的问题。如果头条能像手机让低成本制作视频流行一样用技术手段辅助长尾内容制作者生产内容,那个时候真是巨变,远比现在自媒体变革的让人赞叹。说一下,UC云观就在做这个。

兴趣是怎么产生的?兴趣不是天生就产生的,而是后天培养的。李笑来说,做地好的事情就变成兴趣。想一想喜欢打篮球就会天天想着如何运球、投篮,经过训练我们打球越来越好,对此的兴趣也就越来越大。所以说「兴趣」具有发展性,我们也不知道哪天突然喜欢上什么东西。

推荐系统必须要做的就是不断试错,在兴趣时间轴中加入其它类型的内容,来不断判断用户是不是有了新的兴趣。另外也可以基于用户主动搜索和社交、购物行为来判断修正筛选器。目前而言,今日头条在类如社交、购物等动作不小。电商方面与淘宝、天猫、京东、有赞、微店合作内容电商导购,特别与京东合作推出“京条计划”做场景式购物。另外在社交方面的设计目前就导入通讯录这个操作,其它类如朋友圈的功能也有但目前做法简陋。

:)头条一直有个颠覆微信的心。

信息过滤后的茧房

凯文·凯利在《必然》中说,好的推荐(过滤)系统有三个指标:

1、识别我感兴趣的。2、识别我可能感兴趣的。3、识别朋友感兴趣或推荐的。

我感觉这个解释并不好。对我自己而言,有的时候面对的不是信息过载的问题,而是信息稀缺的问题。

如果每个人都喜欢和自己趣味相投的人相处,喜欢的内容也是和自己价值观相同的,这种环境长期演进就会形成「信息茧房」,我们只关注自己喜欢的内容和观念,只进行选择性阅读,屏蔽了来自不同领域的其它阅读,认知能力也会被阅读的深度和广度不足所限制。

我觉得在《必然》中推荐系统的这三条之上还得加上一条:更高层次的人物感兴趣和推荐的内容。这里的更高层次指的是高价值人群,在我眼里比如和菜头(id:bitsea)、阑夕(id:techread)等等都是高价值人群。这些人群给我最大的体会就是他们更高更大的视野。

有人认为随着互联网的发展,人们的共识会越来越多,但我们看到的事实正好相反,人们越来越在意自己的看法。有个问题最近我才明白,为什么和菜头和冯大辉会主动羞辱和拉黑读者?

在微信帐号的写作者里面,冯大辉、和菜头这两位著名作者,都有在评论中羞辱读者和拉黑的行为,和菜头说,他在新浪微博有 55 万关注者,假设一个 2000 关注者的人攻击他。那么如果每天遭受攻击的次数是 1%,和菜头会收到 5500 次攻击,而对方是 20 次。前者就算再豁达,也不可能完全忽视这种暴力,于是,时而他就会心态平和的回击一次。在我看来,这简直是对后者的一种体验教育,当他攻击和菜头的微弱声音,被和菜头放到几十万读者眼前的时候,大概他可以稍微理解一点和菜头被他攻击的心情。同样的道理,冯大辉会放出来一些评论,挨个回复 “**”。同样的道理,大咕咕咕鸡会用“挂人” 的方式公开羞辱一部分令他不爽的人。但是,攻击者实在太多了,靠这种办法根本对付不过来。更麻烦的是,你的读者往往很难理解这种感受,就算是喜欢你的那些人,可能也会觉得 “你有点过分了”,“你膨胀了”,“你怎么这么小心眼”…

文字截图来自霍炬公众号文章《网络霸凌、收费阅读和内容创业》

如果仅仅在自己的“茧房”里面永远体会不到这种层次,选择性阅读给我们最大的危害就是选择性偏见。听过一个概念是选择性偏见下归纳法就会失效,这个我理解不深,大概是归纳的大小前提会在偏见下有误差吧。

前段时间图文说自己微信内留了一个微商就是这个道理,认识不同事物和人物才不受制于信息茧房。对于一个PM而言,这个意义会更大。

应对信息过载

正如我们父母辈难以接受我们的刷微博刷知乎式的获取信息一样,从过去到现在我们没能逃脱信息过载。过去我们建设更大的图书馆来储存信息应对信息过载,随着信息变多,图书馆也盛放不下这么多信息。类似图书馆,今天我们把信息放在数据库中,到未来也许数据库也会遇到存储问题时候,我们会生产出更先进的存储数据的模式,但信息过载的问题会一直存在。

当我们个人遇到信息过载的时候,由于时间与记忆力有限,机器辅助筛选变得更重要了。微博、知乎、今日头条、微信公众号,最近圈内流行一个叫做「即刻」的APP,这些工具都可以帮我们过滤非重要信息,获得重要信息。

但,都在说信息过载,可信息的不对称性一直就存在,我一直同意冯大辉的观点,获取信息能力是一种竞争力。如果机器筛选获取信息太糟糕,那改变我们自身获取信息能力就尤为重要。

是不是自己思考太片面?是不是接触的信息不是过载而是太少?是不是自己总是带着偏见来看待问题?很多问题都是因为获取信息量太少,自己的圈子太小造成的。

我把前面说的复制过来:

解决内容过载的问题有三种。第一种提高自己获取信息的能力和效率,信息过载自然解决。第二种信息管控,借助外部力量,只选择几个意见领袖推荐和编辑的文章;第三种信息筛选,让自己处在一个良好的阅读环境,内容来自各个渠道经过规则筛选出来阅读。

你会怎么做呢?

我的个人微信号:isLishude,欢迎大家与我交流想法。

推荐阅读:

  1. 推荐过4次,再次推荐——小道消息·关于「阅读」和「信息获取」的错误认知

  2. caoz的梦呓 ·偏见的由来-选择性阅读

互联网运营知识应该从何开始?

很多入门的运营新人太过注重方式方法的学习,也就是“术”的学习,其实入门一个知识领域都需要从“道”开始。

什么是道,什么是术?简单地说就是

道——概念由来
术——方式方法

而学习一门知识还包括以下两个阶段

器——工具使用
用——最佳实践

我们学习运营或者任何一门知识都是“道-术-器-用”这四个阶段依次进行的。

大多数人可能没有注意到,我们教科书知识是学习的最佳的范例,每个章节都是从介绍一个概念开始,然后在讲解如何用,之后才是练习题。

图片来源于网络,仅用做介绍知识体系。

我们学习这么多年的知识,从来就没有开始就直接讲如何用的。

接下来我简单讲讲学习运营的四个阶段。

首先要知道什么是运营,运营做什么。

一个公司把一个概念做成一个产品,这其中参与的人员主要会有开发人员和产品设计师,他们负责把产品“生出来”。在之后,就是运营的职责了,连接用户,做些活动,写些文案,看看数据调整目标规划,负责把产品“养好养大”。
(现在很多产品经理已经沦为产品设计师而谈不上PM;另外在产品初期,运营人员还要负责运营工具的需求整理和初期运营目标规划)

通常意义讲,在产品周期内,让产品更好的发展,让用户更喜欢这个产品就是运营。

不过,运营这个职能现在还极其特别不标准。在某些公司,客服也通常被认为是运营(认真脸,我在某招聘网站上看到客服运营这个岗位)。在这个混乱的情况下,事实上可以说大部分运营都是很苦逼的打杂人员。

还好,有一些运营大神为运营铺开路,目前最普遍的运营职能划分是“内容运营”、“用户运营”、“活动运营”和“产品运营”。

理解这四个,根据我的经验就是,讲问题。

内容运营:内容的流转机制的建设,内容从哪儿来,到哪儿去,怎么过去?什么内容好,怎么评价好坏?如何让看的人更爽,写的人更有动力?(知乎就是个内容运营的鲜活案例)

用户运营:用户是谁,喜欢什么,不喜欢什么?住哪里,男还是女?他们在哪里活跃?如何让他们高兴的付费?

活动运营:怎么让新用户来?做个用户推荐的活动,老用户推荐新用户注册使用就送XXX。怎么让UGC内容更丰富?做个内容评比大赛,第一名奖励XXX。(双十一是目前活动运营的最好案例)

产品运营:做个小游戏让大家玩一玩,怎么让更多的新用户知道产品?我们在页面上加个分享按钮。
(目前大多数产品经理已经沦为产品设计师,运营人员就要补上去为用户体验和商业模式负责咯)

然后要知道运营怎么做如何做

我一直认为任何东西都是套路,都是可以用公式和模板构建出来的。如何做的更好基本都是套路了,以刚刚成为独角兽的知乎为例。

知乎最初的产品形式是个问答平台,用户和内容这两个方面的运营是知乎最初的套路极其有教科书般的价值。

  1. 仅开放一部分重量级互联网高玩加入
  2. 仅开放互联网创业话题下的问题

没有问题和回答,知乎团队就自己当又问又答。对于所有回答,知乎团队第一时间回复点赞互动。

这样子知乎给外界和内容的感受就是一种高价值的稀缺感。就这样知乎成功做了一次内容初始化。

随之更加开放的平台,知乎在产品形式做了改进,让高质量的回答突出,让低质量的回答降低。

  1. 大家熟悉的同意反对以及没有帮助。
  2. 编写知乎使用指南,制定社区规则,有奖有罚。

当高质量的内容越来越多的时候,知乎对内容进行整合。

  1. 知乎日报诞生,尤其是深夜食堂和瞎扯栏目的火热。
  2. 知乎周刊和知乎盐电子书结集出版
  3. 知乎圆桌聚合某一话题下的高质量回答

知乎在维系内容生产者关系也做很多努力

  1. 举行知乎盐Club在线下和优秀社区成员聚会
  2. 开放优秀话题者用Badge和普通成员做区分

。。。

其实都是套路,我们明白运营的套路就知道如何做运营了。

运营工具的使用

这里的运营工具不是只产品的后台,而是指的我们在运营过程中辅助我们思考和总结的工具。

曾经写了一篇文章,可以瞅一瞅。

包括思维导图、文案写作、搜索引擎、活动组织工具的等等。。

链接在这里 → 运营工作常用的工具网站

运营的最佳实践

其实说这个,不仅仅包括我们看到的干货,我认为更重要最佳实践必须自己用产品才能感知到。

用产品?对,内容运营方面看知乎和简书,活动运营看电商和游戏的。

这一段写的少,呃,因为写累了。。

推荐大家看书吧,在“道”上对我启蒙最大的就是三节课的黄有璨,老黄写了一本书叫做《运营之光》,这本书对运营的系统节奏写的特!别!特!别!好。在“术”上对我启发对大就是亮哥张亮,亮哥写了一本《从0开始做运营》,这本书系统讲解了互联网运营的所有流程。

大学创业期间,对我感受最深的是思维方法对一个人影响有多大。当我早已对思维导图熟稔于心,甚至可以变个花样用到其它用处的时候,还有很多人不知道思维导图的强大之处。

学习学习再学习。

完毕。

跑男快递是怎么成长的(2)

我曾经说过一个事情,共享经济的前两条原则就是快速匹配供需和减少用户使用成本。今天我就讲讲我是怎么为了这两个点,也可以概括成提升效率,做努力的。

思维方法

思维导图。当时画的思维导图早就没了,所以本文不上图了。

所有点都围绕快递来分散,我们的主题当然快递怎么做。需要考虑很多,很多,比如第一级有人员配置,技术(平台)配置,快递点位代取规则,时间优化,当然我还想过中转站。

思维导图的原则就是每个分支一直分到自己能直接做到一点,比如“我去华辰”就不是最后的点,而是“时间:下午三点;地点:学校东门对面;工具:乘坐17路车”——这个例子举得不太好,我的意思就是一定要分支到直观而且不需要思考的地步,然后我们要做的去一个一个的去做就行。

image

有一点特别重要,就是思维勘误,比如我想要的中转站就是一个复制错误,调研过程中,物流系的同学给我们说过这个,但因为快递员人数多了根本就不需要中转站了,所以也不需要考虑“怎么向学校申请或者买一个地点、怎么进行管理中转站安全等”。

再此阶段,我们积累很多重要的信息,那时候我有个很大的感触就是有时候别人的话不是对的,兼听则明,不确定的事情最好实地具体考察。

image

思维转变,精益创业。闭门造车的产品必须先见光,无论它的功能还有很多你还没有完成,你只需要考虑目前的产品能直接解决用户的一部分需求,这个是你现在能做到的,不是你需要花很多很多时间去做你做不到的。

说一个例子,以前我们用的很简陋的公众平台收单,不要以为是高大上的自动处理,不是,而是有时候很多信息需要再次联系确定的用户主动发给我们一个代取的信息:姓名+电话+快递点位+宿舍位置,而且当时为了能在移动端接收到目前仍然很坑的用户主动发送的消息,做了很多功课,但是还是不能像微信客户端那样及时收到信息。

是很简陋,我们就是从那时候过来的,因为在当时我们还没有一个好的解决方式,快速投入市场占领市场,才能获得用户的反馈,才能逼迫你升级产品。

产品思路

那时候我一直看一本书,《快递之王》讲的是顺丰和其老板王卫的故事。快递之王,曾经我看了三遍这本书,感慨一件事情,有些事你只有亲身做你真正明白。

其中讲了一个顺丰原则:每位入职的新员工,无论是什么职位都必须去体验基层快递员的工作,公司高管就算是王卫自己也得每年参与基层工作。

除了让员工体察基层的状况外,更重要的弥补自己对快递行业的认识,比如说定价,定价不是高管们拍脑袋决定的,而是实际情况进行约束的。

这和我们一样,像我们从我自己都是代取员,因为这样我们才能更能懂得我们的产品。比如说,楼层费是我提出的,因为我感受到了代取员爬楼的不易;分层收费也是我改进的,因为距离不同定价不同就是简单的道理。

订单平台使用的第三方的,最怕的就是出问题,所以几乎每天我都登录进去看一看有什么问题,有时候及时发现问题就解决了很多不必要的麻烦,具体我就不讲饿了么商家版有多坑了。当然更主要的是改进产品形态,分类列表因为用着不爽我前后改进了5次,因为我会把自己当作用户一样使用自己的东西,提升产品就是要自己当用户,还要亲近用户了解情况。

这部分要写东西要少,因为以前讲过。内容运营方面,一是信息在供需端的展示优化,一定要把主要重要的信息先行展示;二是信息在流转过程二次使用的便捷性。

用户运营方面,我们确实没做多少,主要靠口碑传播,主要原因还是不敢大宣传,因为有时候真是心有力而不足,如果需求端过多,我们这边肯定不会太好过,如果影响到用户情绪,我们的口碑势必会破坏。

你问,如果不宣传人也多了怎么办?好说,涨价,用钱来选择用户,这一点以后得好好说说,举个栗子就是,广州亚运会的时候市政府宣布地铁免费,结果第一天因地铁人数太多就崩了,第二天没办法就选择说你先付钱,以后政府会想办法补贴回去,结果流量大跌。

为了防止流失,我们也做了传统的一些方法,这里不讲。活动运营方面还是需要我们下一步要探索的方面,以后我会再补充。

我们还在成长,写这些就是为了我们梳理思路,更好的走下去。同时给一些学弟学妹一些经验之谈。写完这一篇最近就不在分享关于跑男快递的事情了。明天讲讲轻松点的东西。

理解ES6中的字符串和数值解构赋值

ES6 允许从数组和对象中提取值,然后对变量进行赋值,这种“模式匹配”被称为解构。

let [a, b, c] = [2, 3, 4];

//也就是
let a = 2;
let b = 3;
let c = 4;

let { foo, bar } = { foo: "aaa", bar: "bbb" };
//let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };

当等号右边不是数组或者对象,类如字符串、数值、布尔值会被转换成了一个类似数组的对象,这些对象都有一个length属性,因此还可以对这个属性解构赋值。

let {length : len} = 'he';
len // 2

上面的字符串hello会先转化为new String('he')包装对象,所以会有lengthtoString等属性或方法,所以如果要理解这个的话可以把上述转化为:

let hello = new String('he');
let {length: len} =  {0: "h", 1: "e", length: 2,__proto__: String}

北京生存指南 Beta 1.0

这是我在北京工作的第一个月,一切还好,最不容易的都基本过去了。下面我将以吃穿住行等方面来简单地介绍我所了解的北京生活,希望能给想要来北京的同学一点帮助。

来之前,我看了知乎了帖子,在北京生活了好几年的朋友分享了自己的生活心得,推荐大家来之前多知乎一下。

北京生存指南·住

先说住,每个来北京的人都要先解决住的问题,说起来这是个很棘手的问题。

如果你资金充足,家境宽裕,最好找房屋中介公司。如果你比较担心中介骗人之类的,不过你大可不必担心。房屋中介越来越正规。北京有很多正规的房屋中介,像链家、房天下这样的房屋中介公司,他们明码标价,合同明晰,并且还会有经纪人带你看房。

如果你资金不充足的话只能自己找。因为没有中介的流程,每个月就节省了一大笔费用。在一个信息严重不对称的环境下,信息获取能力优势越来越明显。要选择信誉和名誉较好的租房网站找,58同城这个不优先考虑,因为上面中介组织太多,发布人鱼龙混杂,信息可靠性不强。

我是根据知乎推荐然后在107间网站上找的房子,这个说是比较可靠的租房网站,能和房东直接签合同。但是有点坑的是,如果你要签约或者看房东的电话,你需要交100块钱的认证费用,这认证费用真是幌子,直接交钱就可以了,说是在线签约成功就退钱,可是一般都是在线下签约的。这大抵是他们的商业模式。最好选择107间线上签约,因为可以有平台保证,可以月付房租、免费搬少量东西等好处。我没在线签约,因为房东不在线签。107间官网:www.107room.com

自己找房子就要自己约房东,根据房东空余时间去看房子。这个也是比较费时的,没有钱只能用时间来换便宜。

租房子要注意以下几点。

优先考虑离上班的地方近的地方。从家到公司上班的距离最好以步行半小时时间为准。我曾经考虑过在昌平(很远)租个便宜的房子,我感觉一个半小时,自己起床早一点也就能应付了。后来我一算账就不合算了,这一天来回至少要16元,一个下来小几百就下去了。宁愿住的条件差一些,也要租离公司近的房子。如果你在四环外上班,那你真的是太幸福了,房子便宜而且环境较好。

现在我住的地方距离我上班的地方大概3公里左右,所以步行半个小时多一点就可以到了。一天基本上都在坐着,所以每天上下班的走路过程我就当做简单地运动了。

不优先租赁低楼层。低楼层而且老房子一般都会被当地人租赁出去,这样的房子有些阴潮,几乎没有什么装修。

周边生活设施是否便利。公交和地铁是我们优先考虑的,如果离住的地方近而且有直达公司的那再好不过。另外一些需要考虑超市、理发店(平均消费40¥)、饭店(平均消费30¥)、快递代收位置(因为工作不在家你可能需要菜鸟快递点代收)、商场等等,这些不太重要,但是对你的生活便利了许多。

我算是住在一个城中村,十分接近二环,住在上个世纪末的老房子,不过离公司近并且周边生活设施齐全。所以下班还是周末都有去消遣的地方,公司人少,我的项目目前就我一个人,室友作息和我不太一样,一天和其他人说不上几句话,有个消遣的地方对于我而言最好不过了。

签合同注意钱款、违约、其它费用以及物品损失赔偿。钱款就是刚租房子押金和租金按照什么时间付,提前什么时候付下一个周期的钱,总共签多长时间,是不是可以转租(自己租一段时间后没到合同期限时间租给别人或者腾出一块地方租出去)。违约,就是什么情况视为违约,怎么处理违约。物品损失和其它费用,房东的东西坏了一般会你来赔偿就是这样,其它费用就是水气电费用,还有网络和有限电视的费用,这些你都要注意。

根据统计,十月份后房子租赁价格开始变得便宜。另外三环内单间的价格已经最低2500¥了,而且大多数都是押一付三,合租的价格会相应便宜一些,大概1500¥左右,这个来北京之前需要特别注意,不过比较好的一点就是冰箱、洗衣机、宽带这些基本上已经成为标配了。

北京生存指南·穿

出门最需要考虑尽量少带东西,如果带多了而且需要各处搬动就不太好了。

我的想法是,带两件应季的衣服,加上穿在身上的衣服应季的衣服正好可以经常换洗。过年前的季节的衣服各带一件就行。

根据自己的情况再做打算,不过我**惯少带然后多在网上买。

北京生存指南·行

来北京,下火车第一件事就是办一张一卡通,一卡通不仅可以坐公交、乘地铁还可以在景点刷门票。

办理北京一卡通需要20元卡费,不需要身份证直接办理。充值的话,每个火车站汽车站都有充值点位,一些小区也有代理点。如果你的安卓手机支持NFC(iPhone没有开放NFC权限),打开NFC后把一卡通贴在手机后面就可以通过微信和支付宝进行充值,很方便。

出门不需要带钱,甚至如果你的手机支持北京一卡通还可以不用带一卡通,所有的地方都可以用手机支付,出门的小摊位也有微信,所以也可以微信支付。(据我了解小米5手机会在9月份末支持北京一卡通)

需要特别注意的是,坐公交上车刷一次,下车也得刷一次。

打的多使用滴滴等出行。打的很贵,你最好学会使用滴滴uber打车,不是有优惠券之类的,是起步价就已经很便宜了。

P.S. 我来北京的时候还没有摩拜以及ofo单车。另外有些公交站点并不是对面都不一样。

乘车使用地图不迷路。来之前,下载百度地图或者高德地图以及 离线地图包。在大城市使用地图的有好处就是无论到哪里,街道甚至房子周边的位置都是很详细。

公交站牌很人性化。来之后,坐车之前就搜索一下目的地,然后直接就会有很详细的乘坐路线。北京有一点非常好,同一个地点两边的公交车牌的名字是不一样的,比如文慧桥北,文慧桥东,看地图也不会坐错方向。晚上坐车的时候站牌还会打开灯,累了旁边有座位可以坐会儿,广告牌中间还有北京的简略地图。

最好选择过天桥。早晚高峰人很多很多,基本上满车都是人,街上也都是人来人往。过马路,红绿灯不太靠谱,你可以试试“**式过马路”,但是一定注意安全。如果有马路要过最好选择先过天桥,这样很省时间,天桥一般都在人行道的不远处。

玩的地方有很多。目前我就去了圆明园看了看,终于看到了和教科书一样的景象。

北京有很多大学,我就住在北京邮电大学对面的小区,有的时候可以进去玩一玩。也有很多免费出入的公园(颐和园这样的公园就收费了),很安静,可以去跑步,也可以去发呆。北京真的**,我还没怎么去哪里玩过,有空再去走走。不过北京的空气质量真的不太好。。

这周末我想去这里看看,嗯,安和桥。

北京生存指南·吃

说实话,在北京吃饭很不实惠,比如说我一个山东人最喜欢吃的馒头1块5一个,在学校是4毛钱一个。

三环内的餐厅的确很贵,而且量很少,一般一个人消费大概就是30¥左右。外卖和团购一次没用过,但是看起来也不是很便宜,大概也是这样的消费。六环之外就很便宜了,但也差不了多少。

我**惯吃711便利店(7-Eleven)的包子和水果,有时候也吃他们的便当,不是很贵,但是食物太精致,比如说面粉绝对是精面粉,虽然精致但是我感觉少了点什么。

水果一直就很贵。最近我发现一个比较便宜的可以替代水果的蔬菜就是西红柿,大家可以百度一下西红柿的营养成分,真的很逆天,维生素含量是一般都在桃子、苹果的4倍。我这边最便宜1.98¥/斤,买两个就只有2.5¥,买两个桃子还6块多。

早餐,这里的油饼很特别,我看是油炸饼,可能是北京特别的一样吧。。北京喜欢吃猪肉白菜的,老字号的餐馆大多数就这一种肉馅包子。。烤鸭,北京人不怎么喜欢全聚德,而是喜欢便(bian)宜坊。

想要省钱就要多走超市然后自己做饭。生活半径半公里有空就要走一走,我以前的思维就是什么都可以网上买,来之后也是网上买,后来一对比有时候线下还比较便宜。现在天天下午下班就得走一趟超市,还不错,去了几次都有促销的。23333

北京生存指南·其它

如果你准备来北京,请做好心理准备,受些挫折是必然的。

如果你真的来北京了,请不要太依赖你的朋友亲戚,那只会让你丧失奋斗心,让未来的你受到一点儿点击就受不住。

支付宝又做社交了 不过这次没有被骂

这是一篇打脸文,最终支付宝还是被社会主流舆论骂了,最终支付宝撤下圈子。

在一个安全而且能满足虚荣心的环境里,如果女生们po自拍可以获得无数赞美和赞赏,那么她们绝对会义无反顾的去刷屏。

上周六晚10点,支付宝在首页**了一个邀请用户加入「白领(学校)日记」的圈子,这个圈子目前只能是女性用户发布,芝麻信用分数必须大于750才能评论,支付宝会智能的把毕业和工作的女性区分出来[注1],**加入不同的圈子。

看到有人评论说「支付宝好智能,竟然能识别出来她是学生而不是白领」,其实说来大家早已不知觉的自愿上传了除身份证和银行卡的能证明身份的个人信息,除了知道你是谁,还知道你做什么工作,有没有贷款和车房。支付宝已经有这种4亿高级实名认证的用户了。[注2]

芝麻信用分值范围是350到950,熟悉二八定律的人肯定会想到,那么750分以上也就是那些20%的「高素质」并且「实名认证」的人群。

支付宝已经为po自拍的女性们筛选出来,在这样一个安全而且可以满足虚荣心的环境里,还能收获无数无数赞美和赞赏,那么她们绝对回义无反顾的去刷屏。确实这样,如果你再能看看那两个圈子,你就会直观的发现支付宝使用频率和流量已经直线上升了。

支付宝想做社交,这个你肯定知道,你也知道支付宝在改变路上一直被骂过,一度被用户骂成“支付婊”。这次支付宝的「白领(学校)日记」,阿德的朋友圈大多数人忽略这个产品,但是一个事实是大多数用户已经是「欣然接受」了。

记得支付宝的某高级产品经理说过,支付宝未来不会有支付功能。当时还有人疑问说,不做支付那还叫什么支付。不过,现在通过一些动作可以看出来支付宝在弱化支付属性。

10月12号支付宝提现和微信支付提现一样的手续费,一面说着用户可以通过多使用支付宝服务来增加免费额度,一面又向用户宣传自家的无限免费提现而且秒级提现速度的「网商银行」产品。唔,不做支付的支付宝以后会不会改名字呢?这真有可能。

支付宝会做什么?这个是支付宝能做什么决定的。支付宝想做社交,不想让微信一步一步蚕食自己的市场。当年微信红包带动了微信支付就是用「社交」通过「红包」带动「支付」,那「支付」可以通过什么带动「社交」?

支付宝想通过生活服务来连接人。10月2号支付宝发布“到位”服务,在北上广深杭居住3个月以上的“宝宝”就会在首页自动开通此服务。在“到位”中,用户发布需求系统会自动匹配服务的用户,最后促成交易。支付宝想切入线下,让每个个体都产生联系。

“到位”服务使用了支付宝最强的信用体系“芝麻信用”,对于支付宝而言,这也是最大的优势。芝麻信用能做什么?

芝麻信用可以评判个人的信用级别和风险能力,对于支付体系而言,知道信用就可以判定能不能借钱,知道风险能力就可以判定借多少。知道信用可以有什么用,可以做社交吗?有人开玩笑说,支付宝做一个附近的有钱人就可以接入社交了。

除了开玩笑,我们确实得思考一下信用与社交其它联系。微信大部分用户的通讯录都是熟人,在没有持续「互动」下,微信内大多数时候很难建立起陌生人的信任关系。

这次「白领(学校)日记」的产品设计很独特,支付宝在尝试链接陌生人的社交。

第一只允许女性用户[注2]发布信息,除了吸引男性侧关注外,女性使用往往有「聚集」作用,类比美柚和河狸家APP,如果产品内女性用户越多,那么后续女性用户参与的也变的越多。

第二只允许信用分大于750分的用户评论,我认为这是在引导用户对芝麻信用分的价值认知,让大家知道信用分决定着用户的身份地位以及可信赖的程度。

有意思的是,微商群体和一些公司已经渐渐懂得支付宝对他们的重要意义,前仆后继的想先进入再找出口,不过我们身边的互联网人却对这一切无感。真是有意思。

这次活动还在持续刷屏,社交的性质开始被激活,一些人开始说“750分的加一下好友啊”并在建各种群,也还有人开说“大家加好友一起种树”,随后更多的人在问“什么是种树”,增加用户黏性的蚂蚁森林也被这次活动传播开来。

除了自拍照以外,我发现了圈子内信息流开始像微博一样,有些用户开始po普通日常吃饭、狂街等这类图片。这回是真有意思了。

你说这次支付宝会不会在社交领域成功迈出一步?

注1:支付宝在2015年9月9日开展「大学生信用节」,通过比拼每个学校学生信用来鼓励学生开通自己的芝麻信用。

注2:开通芝麻信用服务,会提示你录入公积金、车辆、工作单位信息会帮你提升信用分。2016年3月21日「遇见名画中的自己」,通过自拍来识别出3位与你相似的名画里面的人物鼓励大家进行刷脸,也就是进行高级用户认证。

注3:身份证信息的第15位数字可以确认用户性别,奇数为男性,偶数为女性

初始化 Ubuntu Server 清单

说明

学习Linux最好的方式就是使用发行版的操作系统,Ubuntu是我第一个接触的系统,当然也是广泛被推荐给新手学习的第一个操作系统。

下载安装

百度搜索下载即可,windows下我们需要先安装虚拟机,我用的VMware 12,这个挺好用的,中文界面,功能强大,不过不好的地方就是需要花钱。不过有些事情你懂的。Ubuntu一般都是下载图形界面的桌面版本,其实我感觉学习Linux要有feel的话,当然还是要用全字符界面的Server服务器版本咯。下载安装比较简单,不提。

我们安装好了虚拟机,其实在虚拟机中操作不太好,我们最好在桌面上下载一个可以ssh软件来连接虚拟机。另外我推荐大家使用一个xshell软件。

新建环境

这个也不难,打开vmware,新建一个虚拟机,选择Ubuntu Server的镜像,一步一步的来。基本上我们不用管,需要留意的是,因为vmware简易安装使用的美国的软件源,安装过程中会很慢,这个我们稍等一下就好。

进入系统

更新软件源

sudo apt-get update
一般会很慢,因为是用的美国的软件源。等一会,然后我们安装vim文本编辑器来修改软件源。

安装vim

是的,vmware简易安装模式没有文本编辑器,所以我们要手动下载一个文本编辑器。这里推荐安装vim。

sudo apt-get install vim

同样会很慢,我们稍等一会就好了。

修改源

cd /etc/apt/
sudo vim source.list  

我们把所有的us换成cn就好了。

如果不用vim修改源的话,可以使用sed命令。

sudo sed -i 's/us/cn/g' /etc/apt/sources.list

安装ssh服务

这里是个大坑,因为我学linux的时候死活在宿主机上用xshell连接不上虚拟机。原因现在看来很简单,就是server没有安装ssh服务,所以我们用xshell连接虚拟机的22端口的时候是被拒绝。

安装ssh server
sudo apt-get install openssh-server
启动ssh server
sudo /etc/init.d/ssh start
确定ssh服务启动
ps -e | grep ssh
设定服务端口
sudo vim /etc/ssh/sshd_config
sudo /etc/init.d/ssh restart

一般情况下不需要检查ssh服务是否启动成功。

用xshell连接虚拟机

在虚拟机中输入 ifconfig 找到 inet ip,然后再 xshell 连接这个 ip地址 就可以了。

DevOps

持续集成仰赖以下原则来达到目标

  • 维护一个代码库
  • 自动建置
  • 让建置时会自我测试
  • 所有人每天至少提交一次
  • 应该要建置每一个提交
  • 让建置维持快速
  • 用在线环境的复本测试
  • 让获取最新发布版本更容易
  • 任何人都可以查看最后建置的结果
  • 自动部署

持续集成目的在产生以下效益如

  • 及早发现集成错误且由于修订的内容较小所以易于追踪,这可以节省项目的时间与成本。
  • 避免发布日期的前一分钟发生混乱,当每个人都会尝试为他们所造成的那一点点不兼容的版本做检查。
  • 当单元测试失败或发生错误,若开发人员需要在不除错的情况下还原代码库到一个没有问题的状态,只需要放弃一小部分的更改 (因为集成的次数频繁)。
  • 让 "最新" 的程序可保持可用的状态供测试、展示或发布用。
  • 频繁的提交代码会促使开发人员创建模块化,低复杂性的代码。

返回文档在垂直方向已滚动的像素值

返回文档在垂直方向已滚动的像素值

使用范围

  1. 返回顶部
  2. header动画效果

scrollY

window.scrollY 的值 —— 当前页面垂直滚动的像素个数(初始为 0)。

当用户滚动时,window.scrollY 的值会相应的增加或减少。

语法

var y = window.scrollY || window.pageYOffset;

y 是文档从顶部开始滚动过的像素值,pageYOffset是为了兼容其它浏览器。

示例

// 保证刚好滚动到第二页
if (window.scrollY) {
  window.scroll(0, 0);  // 重置滚动位置为文档的左上角
}

注意:改变此值无法改变状态

scrollTop

Element.scrollLeft属性表示网页元素的水平滚动条向右侧滚动的像素数量,Element.scrollTop属性表示网页元素的垂直滚动条向下滚动的像素数量。对于那些没有滚动条的网页元素,这两个属性总是等于0。

如果要查看整张网页的水平的和垂直的滚动距离,要从document.body元素上读取。

document.documentElement.scrollTop||document.body.scrollTop

注意:设置该属性的值,会导致浏览器将指定元素自动滚动到相应的位置。

腊月前

假期前准备要和伟伟童鞋、草哥一起工作,结果很不理想,没找到合适的工作,受了不少的罪,当然也收获了许多,最后独自一个人回家。

家里无非这样,家乡话还是那么容易让我不知所措,口音不像普通话,家乡话也淡了不少。

回家第一件事,就是去姥娘家,去看看表哥和小侄子,依旧平常,闹心的和烦心的情节还是在上演,不过还好,放不下的依旧放不下,放得下的依旧放得下。

没几天,我就参与了干哥的婚宴准备。在我们这,结婚前半个多月就请人来家里商量婚宴的事情,参与的都是家族的和村里面有经验的人,记得从前我爷爷也是这样的人。

席间说完许多事情,大多数都是是关于婚宴的事情,还有就是其他事情,比如说关于我,关于我的她,每每如此,我都不好回答,或苦笑,或无语。晚上我把这件事情告诉了她,她也说了她的事情,妈妈也是老是提及我,那个山东的同学。

有很多时候,我很难控制自己,很烦躁,不想学习,也不想玩游戏,瞬间不知道要做什么了,是不是很难过的事情?不过最近好了,我开始看更多的知识和书,压着自己的性子去做,虽然我知道这样做的效果不太好。我也决定了,上学后不带自己的笔记本电脑,那干什么呢?到时候自会知道,一方面,俄语专四要开始了,另一方面,我的知识储备还远远不够。

我买了极路由,体验了智能路由的感觉,说实话感觉很平常。由此我搬到了楼上,那个她曾经住过的房间里,本来想告诉她的,后来一想,罢了,自找无趣。

每每都有一种失落感,我知道为什么,但是我就是...

每天老爸都会在晚上九点多,帮我把路由器电源关上,然后第二天早上很早的又打开电源。我自开玩笑说,老爸真好啊,晚上提醒我早睡觉,早上提醒我早起床...

今天是干哥婚礼的前一天,早上帮忙贴对联,放鞭炮,中午吃了一顿饭。

早上我到干哥家时,村里的大娘二娘们又提醒我关于我找没找女朋友的事情,又给我提及暑假她的事情,我又是干笑着,最后她们得出结论,我分手了,然后我有找了一个,还说现在年轻人不都这样,说说便把话题转移到自家的孩子身上,我才解脱。

中午前,我和以前的玩伴遇到了,我也看到似曾相识的面孔,并且猜测她的身份,最后知道了,她是我二奶奶家的闺女——

齐肩的短发,碎碎的刘海,还有和她母亲一样的肤色,很清秀的小女孩,应该上初中了吧。都长这么大了,的确有一种沧海桑田的感觉,这些年在家里也没怎么出门和周遭的人打交道,除了学校就是家庭,似乎错失许多啊。我也变了,变化不大,他们还是认出了我,在我答应他们的我的名字之前却还是有一点不确定。

我问道,什么时候结婚?

后天。

那真赶巧。

我以为他是说玩笑。后来我才知道,这是真的,确确实实的事情。真为他高兴,听说他的孩子都六个月了。只不过,我没想到——

没想到后天我又能吃一顿小时玩伴的婚宴。

人之所以言之凿凿,是因为知之甚少

你怎么看待下面这几个说法?

反对同性恋!如果两个男人都能结婚,那么兄妹之间、人兽之间甚至人物之间就都能结婚!难道您赞成乱伦和人兽恋吗?!

必须好好学习!如果不好好学习,就上不了好高中、上不了大学、找不到好工作,就只能扫大街!你难到想一辈子扫大街吗!!!

为什么不能随地扔垃圾?不随地扔垃圾,地面上就没垃圾,没垃圾,环卫工人就没有存在的意义,难道你想让环卫工人都失去饭碗吗?!

先不着急讨论这个问题,重点在于,我们深处这个社会,尤其在微博、贴吧上,各种信息扑面而来,意见领袖说着我们觉得很有道理的内容,并且不由得深信这些话。

但是,你真的认真思考这些话吗?

好的,让我们回到这些话的实质上,让我们先提出第一个问题:这些话的结论或者理由是什么?

结论:反对同性恋;理由:如果同意同性恋就相当于同意兄妹乱伦人兽杂交!
结论:不好好学习就会找不到工作,找不到工作就会扫大街;理由:不好好学**,就不会考上好的高中大学,进而找不到好工作,只能扫大街。
结论:随地扔垃圾帮助环卫工人不丢掉工作;理由:不扔垃圾地面就没有垃圾!环卫工人就不能工作赚钱!

然后,我们分析一下这些结论和理由,有哪些关键词语含义不明确或者有歧义。

关键词是什么?比如第一条的”反对同性恋“,关键词就是”反对“和同性恋”,”同性恋“指的是男性与男性之间或者女性与女性之间存在爱情或者婚姻关系,这个词语并没有其它抽象意义,我们可以明确。另外我们可以使用“反对”相近的词语,比如说“不支持”来替换“反对”,如果意义有较大变化,那么这个关键词就有不明确或者歧义,进而影响我们对论证(即理由和结论的结合)的看法。

第二条和第三条也是如此。

经过我们分析,这三条理由和结论都没有语义不明确和歧义。

那么看起来,这些观点就没有什么问题了...!?让我们继续想想,这三条观点的共同之处:如果存在A就会发生B,如果存在B就会发生C....每条观点就像滑坡一样,顺下来一直存在必然联系。

那么我们仔细思考一下,为什么就会导致和人兽?为什么找不到好工作就只能扫大街?
为什么地上的垃圾都是随地扔的?

你的答案是什么?你还会觉得这些观点看起来很正确吗?

人之所以言之凿凿,是因为知之甚少。

修改Ubuntu的时区

安装了Ubuntu Server之后,默认的英文环境下时区是国外的,所以使用Git等操作的时候,记录的时间会有些错乱,我们可以简单的使用命令行来修改时区。

sudo dpkg-reconfigure tzdata

image

然后我们依次选择 Asia-China-Beijing就可以了!

谷歌账户注册手机号一直无法验证?

谷歌账户注册流程有个手机号验证Bug 。

如果在国内注册那就是不要用Chrome,因为那样手机号验证流程始终会提示“手机号不可用”,这个时候可以使用Edge或者IE浏览器来注册,然后就可以了。

P.S.如果一直就404,那么。。嗯。

另外,补充一句,谷歌账户是可以随时删除的。 在尝试删除Github帐号之后,我又尝试删除了用了两年的gmail,成功删除。国内的产品是不是也学习一下?

怎么学习一门新知识?

如何去学一门知识?我们可能想到去网上搜索一下评价高的入门书,或者不断在各种慕课网站学**。我们一般按照书本或者视频上的思路走,但是你有没有想过我们自己该按照哪儿思路走?

今天我们就讲讲如果我们要学**一门新知识,我们要使用的“套路”,这个“套路”叫做“道、术、器”。我不太清楚这个的来源,大概是来源于道家或者佛家。

接下来我们先讲一讲“道、术、器”的概念。

道——要学的知识是什么?知识的概念本质是什么?学这个知识的目的是什么?

术——学会这个知识的方法是有哪些?需要哪些相关的资源?

器——学**这个知识需要的工具是哪些?这些工具怎么用?

如果你仔细看的话,我在上周五写的关于《内容标准化》的思路就是按照这个来的。使用这种方式来学**新知识就简单化为问自己问题,然后驱使自己找答案的过程。

就像有个师傅带进门的感觉一样,学**一直有个清晰的目标可循。接下来举个例子,详细说明这三点。

假设我们要学**使用微信公众平台。

按照思路我们我们首先认识一下”什么是微信公众平台,是做什么的,和我们有什么关系“。

这样我们可以清楚的知道,微信公众平台是依托于微信客户端的媒体平台,可用来营销、电商、社群等等互联网服务,公司可以用来做用户和活动运营,个人而言也可以做自媒体博客。还有要了解”微信的有哪些功能”,群发信息,智能机器人和客服功能,支付功能,连wifi进场服务,摇一摇营销等等。

然后我们会想把办法把微信公众平台用好,除了自己不断摸索,还要在网上搜集技巧。这个是“术”,就是学**的方式方法。

我们再使用基础功能的同时会接触到微信是一个巨无霸的开放平台,我们可以用第三方平台辅助来使用,也可以自己开发。排版可能用到135编辑器,秀米编辑器,这样我的图文也能变得很漂亮;电商我们可能用到有赞,微店等,我们就不用费劲造轮子在造一个商城。这个是“器”,就是使用的工具。

除了这三点之外,还有一点很重要,就是“用”,什么是用,不是自己用,而是好的案例,我们要学这些案例,商城谁做的好,我们搜索到良品铺子做的好,那我们就得参考他们的电商的内容样式和关注他们的活动策划等等,好的案例能让我减少学的成本。


这是我北京住的第三个周五,这是我在北京写的第三篇文章。

一个大城市,一个三四线来的穷学生,刚开始你会感到一切新奇还有友好,但是生活一段时间,你会感觉累,除了身体上的累,最主要的是认知上的累。你的想当然可能是错的,错就会付出代价。不过,最好的莫过于这座城市虽然一直在放大你的缺点,但也一直在为你增加经验。

直白冷酷,别忘了你还有温情关系你的朋友。今天的雨过天晴对我又是另一种感觉。感谢我的这些朋友,谢谢你们当我在北京遇到困难时刻伸出援手。

无论生活有多糟糕,还是要好好照顾好自己,学会让自己成长,永远相信美好的事情即将发生。

Ubuntu中怎样添加或删除一个PPA源

PPA源

Personal Package Archives(个人软件包档案)是Ubuntu Launchpad网站提供的一项服务,允许个人用户上传软件源代码,通过Launchpad进行编译并发布为2进制软件包,作为apt/新立得源供其他用户下载和更新。在Launchpad网站上的每一个用户和团队都可以拥有一个或多个PPA。

PPA的一般形式是

ppa:user/ppa-name  

添加之前请确定已经安装 Python 以及必要依赖:

sudo apt-get install software-properties-common

添加PPA源的命令为:

sudo add-apt-repository ppa:user/ppa-name

也可以打开【软件中心】->【软件源】->【其他软件】,选择添加,在弹出的窗口中AT行里输入ppa:user/ppa-name 格式的内容。

例如,要添加一个用户名为 certbot 的 certbot 源中,则命令为

sudo add-apt-repository ppa:certbot/certbot

添加好更新一下:

sudo apt-get update

然后就可以运行 sudo apt install certbot 安装了。

删除命令格式则为:

sudo add-apt-repository -r ppa:user/ppa-name

sudo add-apt-repository -r ppa:eugenesan/java

然后进入 /etc/apt/sources.list.d 目录,将相应 ppa 源的保存文件删除。

最后同样更新一下

sudo apt-get update

CSS收集

布局

负margin
-负margin用法权威指南

简单总结几点:

  • 不使用 float 的话,负 margin 元素是不会破坏页面的文档流。所以如果你使用负 margin 上移一个元素,所有跟随的元素都会被上移(而 relative 定位的元素则不同,会保留原位置,影响文档流)。
  • 当 static 元素的 margin-top/margin-left 被赋予负值时,元素将被拉进指定的方向。
  • 如果你设置 margin-bottom/right 为负数,元素并不会如你所想的那样向下/右移动,而是将后续的元素拖拉进来,覆盖本来的元素。
  • 当元素不存在 width 属性或者 width: auto 的时候,负 margin 会增加元素的宽度.
  • margin-top 为负值不会增加高度,只会产生向上位移;margin-bottom 为负值不会产生位移,会减少自身的供 CSS 读取的高度,影响下方的元素位置;上下相邻的元素两者均为负时,效果不叠加,取负值更多的那个效果。

清除浮动

Flex 布局

CSS3动画

sass中文文档:http://www.css88.com/doc/sass/

LNMP环境搭建最佳实践

laravel+LNMP配置最佳实践

更新软件源

sudo apt-get update

解决语言问题冲突

sudo apt-get install -y language-pack-en-base
locale-gen en_US.UTF-8  
export LANG=en_US.UTF-8 
export LC_ALL=en_US.UTF-8 

安装所有依赖

sudo apt install git vim php7.1-mysql php7.1-fpm php7.1-curl php7.1-xml php7.1-mcrypt php7.1-json php7.1-gd php7.1-mbstring php7.1-curl php7.1-zip php mysql-server nginx -y

安装PHP7.1需要PPA第三方源支持,具体参考这篇文章

安装Git和Vim

sudo apt-get install git vim -y

安装 php7

sudo apt-get install php -y

查看php版本:php -v

安装 php7-lib

sudo apt-get install php7.1-mysql php7.1-fpm php7.1-curl php7.1-xml php7.1-mcrypt php7.1-json php7.1-gd php7.1-mbstring php7.1-curl php7.1-zip -y

注意: php-zip 包,composer特别需要!

安装 mysql

sudo apt-get install mysql-server -y
查看mysql版本:mysql --verison

新建数据库

create database dbname default charset utf8mb4 collate utf8mb4_unicode_ci

更新数据库

sudo mysql_upgrade -u root -p
service mysql restart

安装 Nginx

sudo apt-get install nginx -y
查看nginx版本:nginx -v

配置 PHP

php-fpm配置

打开并编辑: /etc/php/7.1/fpm/pool.d/www.conf

listen.own = <nginx.user>
listen.group = <nginx.group>
listen = /var/run/php/php7.1-fpm.sock`

URL安全配置

打开并编辑: /etc/php/7.1/fpm/php.ini

/cgi.fix_pathinfo = 0

配置 Nginx

打开并编辑: /etc/nginx/sites-available/default

server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        root YOUR-PROJECT-DIR/public;
        index index.html index.php index.htm;

        server_name YOUR DOMAIN OR IP;

        location / {
                try_files $uri $uri/ /index.php?$query_string;
       }

       location ~ \.php$ {
                try_files $uri /index.php =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
       }
}

配置gzip

打开并编辑:/etc/nginx/nginx.conf

gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript
text/xml application/xml application/xml+rss text/javascript;

同样的,在此文件最上面编辑 user

user user group

建议就使用当前用户

重启服务

sudo service nginx restart
sudo service php7.1-fpm restart

Composer

安装

sudo wget https://dl.laravel-china.org/composer.phar -O /usr/local/bin/composer
sudo chmod a+x /usr/local/bin/composer

注意:因为Composer不推荐使用root用户进行安装依赖(安全问题),所以最好把网站目录放在当前用户目录之下。

国内Composer镜像

composer config -g repo.packagist composer https://packagist.laravel-china.org

为文件目录赋权

为访问网站用户赋权,如果nginx设置的就是当前用户就不需要这一步。

sudo chown -R <nginx-user:nginx-group> YOUR-PROJECT-DIR

为storage赋予写权限,但这一步,我建议在开发环境就设置并提交到git中

sudo chmod -R 775 YOUR-PROJECT/storage

所以这两步骤都可以省略!最好都省略掉,如果不省略掉就会很麻烦的 git pull 之后还得更新文件权限和所属关系。

更多内容可以参见我的 nginx 分类中文章。

File API

Exsample code

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Test Index</title>
    <!-- <link rel="stylesheet" href="dist/css/base.css"> -->
    <script>
        window.onload = function () {
            var fileInput = document.querySelector('#file'),
                info = document.querySelector('#info'),
                preview = document.querySelector('#preview');
            fileInput.onchange = function () {
                var file = fileInput.files[0],
                    fileName = file.name,
                    fileSize = file.size,
                    fileType = file.type;
                if (fileType.indexOf('image') == -1) {
                    alert('您选择的不是图片!请重试');
                    return;
                }
                info.innerHTML = '文件名:' + fileName + '<br />'
                    + '文件大小:' + fileSize + '<br />'
                    + '文件类型:' + fileType;

                var reader = new FileReader();
                reader.onload = function (e) {
                    var data = e.target.result;
                    preview.style.backgroundImage = 'url(' + data + ')';
                }
                reader.readAsDataURL(file);
            }

        }
    </script>
</head>

<body>
    <form action="">
        <div> <input type="file" id="file"></div>
        <div id="info"></div>
    </form>
    <div id="preview" style="width:100%;height:200px;border:1px solid gray"></div>
</body>

</html>

朝三暮四和朝四暮三一样?

小时候我们都读过这个故事。

说是一个养猴子的老人,十分喜欢猴子,他可以理解猴子的意思,猴子也可以理解老人的意思。不过,有一天老人家里的粮食不够,于是就想限制猴子的伙食的数量,于是就跟猴子商量说,“给你们枣吃,早上三颗,晚上四颗,行吗?”猴子们都十分不乐意,老人又说,“早上四个,晚上三个,这回够了吧?”猴子们十分高兴,就这么决定了。

然后,我们学到一个成语,并且感觉猴子很笨,明明都是七个枣,只不过早上和晚上换了一个形式,猴子就很满意了。

但是我们考虑到这个世界的不确定性,我们就很可能认可猴子的决策。这个世界瞬息万变,谁知道早上到晚上会发生什么事情呢?

因为万一早上只吃了3颗,万一老人死了,万一老人破产,没人管猴子了,晚上就没得吃了。综合来看,对于猴子的决策还是有可取之处。

这篇我们讲讲不确定性下的决策。

北京第二天,租房工作都确定后,我就考虑三餐以及出行,尤其是出行。假设我从家里到公司上班的时间是30分钟,当然这是不堵车的情况,但是如果堵车的话,我们可能需要45分钟到1个小时的时间,那我是提前一个小时出发,还是只要提前三十分钟出发就可以了?

如果是你的,为了应对这种30分钟的不确定以及上班不迟到,你最好提前一个小时出发。

不确定情况下的决策就是这样,可提供的方案很多种,我可以提前30分钟,也可以提前45分钟上班。如果可提供的方案很多,那么对于我们而言就会增加我们决策难度,尤其是谈判桌子上。

但是也不是没有方法,我们只要知道进一步的信息,通常情况下,有三个方面的信息需要我们进一步寻找,第一,我(也就是决策者)有多少选择,对方(也就是自然状态,比如我们上班从30分钟到60分钟之间都可以),最后一个最为重要就是决策者在某种情况下的损益结果,也就是哪种决策对我们最优。

接下来谈谈决策损益计算。一种是我们知道对方的决策结果,一种是我们不知道对方决策结果。当然最好的就是知道对方决策,如果不知道我们就需要根据相关数据来研究。

大庆油田发现后,外国迫切想了解油田具体情况。但是又不知道大庆油田的具体情况,但是日本人根据一张铁人王进喜的照片就估算了大庆油田的产量,方位等,进而得出我国继续炼油工具进口,后来在与**合作中快速应变获得了合作机会。进一步了解日本人是如何得到大庆油田资料的 http://blog.sina.com.cn/s/blog_5c49fc4f0100k8bn.html

如此,应对不确定性的决策就是要收集更多有利自己的更多资料。不过说起来,决策不都是不确定性的吗?

现在是商业智能的时代,所有组织需要知识管理以及商业智能的辅助才能进一步发展,现在,我正在我们公司探索这种模式,随后分享。

Linux用户和用户组的一些命令

组操作

0、查看所有组: /etc/group

1、添加用户组:groupadd [-g gid] gname

2、重命名组:groupmod -n new_name old_name

3、编辑组编号 : groupmod -g gid gname

4、删除组: groupdel gname #at first you must del the groups' users

用户操作

0、查看所有用户:cat /etc/passwd

1、添加用户: useradd -g gname -d /home/udir -c comment uname

2、重命名用户:usermod -l new_name old_name

3、更改用户所在组:usermod -g new_group uname

4、删除用户: userdel -r uname ( -r删除用户的文件数据)

5、禁止非root用户登录touch /etc/nologin

6、锁定用户: passwd -l uname

7、解锁用户: passwd -u uname

8、登录不需要密码:passwd -d uname

9、添加用户到其它组: gpasswd -a uname gname

10、登录到其它组: newgrp gname

11、从组中删除:gpasswd -d uname group

12、给组设置密码:gpasswd gname

13、使用其他用户登录:su uname

14、查看用户信息:id uname

15、查看用户所在组:groups uname

16、编辑用户资料:chfn uname

17、显示用户资料:finger uname

补充内容

Linux 视一切包括硬件为文件,所以对用户增删改查都是对文件的操作。

Linux系统的每个用户都有一个唯一的 User ID,User的信息存储在 /etc/passwd 中;每个User都属于一个Group,具有唯一的标识符gid,Group信息存储于/etc/group中。

这两个文件的权限均为644,用户以及用户组为 root,也就是说任何用户都有读的权限。所以这里修改用户和用户组需要root权限。

如果文件属于用户,用户可以使用 chmod ,但是只有 root 用户才可以 chown。

精细化运营之参数二维码

2016-10-03 15:14 | adesight

image

二维码就是通过将内容二进制编码生成的二维图形。对于运营者而言,二维码越来越重要,不论是海报广告,还是文案内容,运营们都忘不了加一个二维码。

对于用户而言,通过扫描二维码就能很简单地获取信息以及和企业商家互动。同时企业和商家也可以简单地获取目标用户和渠道流量。如果我们要跟踪用户和渠道数据,做精细化运营的话就需要使用到参数二维码了。

什么是参数二维码?简单地讲就是在标准二维码信息之上添加标记用于场景营销和数据分析统计的二维码。

我总结了参数二维码的用法有两个:数据分析和场景营销。最后再说一个分众传媒的最佳参数二维码实践。

数据分析

上面讲的是添加渠道标签参数到二维码中,比如说,我们的公众号需要推广,并且找了几个大V,这个时候我们给不同的大V加上不同的渠道标签,这样子我们就知道哪个大V的导流效果好了了。另外电梯广告、公交车站广告都使用了参数二维码来分析渠道数据。

比如说我原先的二维码的解码内容是 http://www.domain.com/,这个能跳转到我们的活动H5页面,现在我们在这个内容之上加入一些信息但是并不影响正常使用,像这样加入渠道信息http://www.domain.com/?utm_source=lishude,当运营者查看数据的时候就可以知道用户来自lishude的推荐,lishude这个标记就是参数。

除此之外还可以用于给用户打标签,比如说我们在某个公司做了一个团购,团购二维码上可以添加这个公司的信息,后台就可以给扫描这个二维码的用户进行贴标签。图为有赞的页面,除了设置专属商品优惠**,还可以设置扫描二维码后给用户添加的标签和会员。

image

场景营销

餐厅自助点餐功能。餐厅在每张餐桌上添加不同的桌号的参数到二维码中,这样用户就可以直接点餐付钱了,如果用户是在微信号中还可以加入H5小游戏和微信连WiFi,必要时**个优惠券,这样不仅节省了餐厅人力,还增加了用户由于互动产生了对餐厅的忠诚度。

image

特定化反馈和信息。自动售卖机上不同的二维码对应不同的商品,扫描一个商品二维码之后关注微信公众号这个商品的购买链接;ofo和mobike的共享自行车,每一辆车的参数id并不相同,扫描车身上的二维码就可以解锁这辆车;网站注册新用户不用填写账户密码,直接扫一扫微信二维码关注之后就成功注册,并且**一个完善信息和简单引导的文字消息。

image

给老用户打折。一大袋坚果,吃完就看到一张卡片,除了优惠码,卡片上还有老用户的优惠购物链接二维码,用户扫一扫关注公众号输入优惠码就获得优惠。

image

活码营销活动。活码就是不用修改二维码就可以修改扫描二维码后获取的页面,活动文案可以随时修改,同时也可以设置二维码失效时间。

“用”

参数二维码结合微信可以发挥最好的作用,微信浏览器内部不用cookie标记用户,可以直接调用微信接口获取用户信息,同样的支付宝也有类似的开放接口,作为运营人员就可以使用微信的唯一id标记用户,然后来定制化内容。

image

这个页面是分众传媒制作的电梯广告H5页面,同样的使用了参数二维码,这里不同的地点投放的二维码有不同的参数,分众就可以借此来看不同渠道广告转化率,不过感觉大街上或者电梯里像我经常扫二维码的人不多吧 ("▔□▔),不过曝光率提高了,我们可以给客户合作时收集客户大致位置信息,或者要求客户提供客户从什么渠道知道的产品服务。

当我们收集到大量信息数据之后,我们就可以有的放矢的做运营。通过数据驱动来为下一步运营做指导,这就是精细化运营。

嗯,这周写到这。

为了提升认知我的微信里留了一个微商

2016-09-04 05:29 | adesight

大学,我的印象中我遇到五六个微商,有的是朋友,有的是网友。

大学一年级我主动接触一类大的微商,他们认识的人多,圈子大,然而我主动是有目的的,我想借他们的力导流到我运营的悟空校园。后来没什么成效,又因为平台渐渐式微,最后不了了之。

直白的讲我不太喜欢微商刷屏,就像每天都在浪费看这些与自己无关的商品广告。所以自己,也有很多人和我一样,主动的关闭连接。

最近,又又一个微商主动加上我,这次我没有屏蔽或者删除,而且每天会花费时间研究一番。

为什么?我来讲一个事情。

做互联网,往往会有人组织一个社群,每天大家互相交流,虽然社群人员参差不齐,但是每天聊大家的见闻琐事,往往能让你遇到相同的问题能快速解决问题。

不过,有的时候,群内有些问题没有人能给出答案。晚上有个做高颜值主播直播APP策划说,现在公司要拉新可是不知道如何去做。

做运营都知道,一个新产品的目标用户是对产品有需求的这类人,这类人集中的区域就是我们要开发的渠道。直播是一个双边市场,用户有主播,还有观众,如果不了解这两类人,所有的拉新或者留存策划都是没有什么成效的。

我自认不了解,虽然我知道运营的方法论,我能做一个运营框架,但是我不能给出什么建设性的建议。这个时候,我深深感受到自己被局限了。

如果你去软件商店,会有很多分类,新闻、阅读、游戏、办公等等,如果你不能随时切换视角,对这些产品的目标用户、渠道市场、盈利模式也没有认知存量,需要做时而自己做不到,那自己如何在竞争激烈的互联网中活下去?

**比特币首富李笑来先生推特关注了18000人,不为了做粉丝而是为了扩展自己的认知,后来他看到了比特币这种虚拟货币,比特币开始很好获得,越往后越难,我也没想到的是比特币价值狂飙,后来李笑来先生获得很大的财富回报。现在我知道为什么我当时不在意比特币了,就是因为我的认知就局限在当下,打不开所以就看不到更遑论去做了。

初中时候看到一句话叫做“思路决定出路”,如果这句话是对的,我现在真想说“认知决定思路”。小道消息公众号上冯大辉说:“这是一次不折不扣的信息革命,所有人都在不知不觉地获益,是这一代人的红利,然而却有人不断地拒绝。”

作为一个互联网人,尤其是互联网产品经理和运营人员,研究各种产品形态,研究各种类型人群(从业和用户)特点,研究各种失败成功案例,只有这样你才能在各种场景中随意转化视角,有的放矢。

那该如何做?网上的所谓干货太多了,不过我看到一个比较好的方法论。

我们下周五详细讲一讲。

一周总结:

这周和以往差不多,每天都在忙于寻找编辑发布内容,但是比以往好多的是,模板化操作让我每天早上能完成未来一两天的工作进度,每天下午我可以抽出时间学**和思考,当然也可以闲聊。

这一周接触到很多北京的互联网从业者,突然想到以前看到的一句话,“每一个互联网从业刚开始的时候都想成为乔布斯、张小龙那样的布道者,然而事实上极少部分人成神,大多数都成了狗,而绝大多数猪狗不如。”我感觉很形象。

认知可能是拉开人之间的距离的唯一点。这个距离不仅仅包括财富和地位。

JavaScript正则表达式

概述

正则表达式(regular expression)是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用作按照“给定模式”匹配文本的工具。比如,正则表达式给出一个Email地址的模式,然后用它来确定一个字符串是否为Email地址。JavaScript的正则表达式体系是参照Perl 5建立的。

新建正则表达式有两种方法。一种是使用字面量,以斜杠表示开始和结束。

var regex = /xyz/;

另一种是使用RegExp构造函数。

var regex = new RegExp('xyz');

上面两种写法是等价的,都新建了一个内容为xyz的正则表达式对象。它们的主要区别是,第一种方法在编译时新建正则表达式,第二种方法在运行时新建正则表达式。

RegExp构造函数还可以接受第二个参数,表示修饰符(详细解释见下文)。

var regex = new RegExp('xyz', "i");
// 等价于
var regex = /xyz/i;

上面代码中,正则表达式/xyz/有一个修饰符i

这两种写法——字面量和构造函数——在运行时有一个细微的区别。采用字面量的写法,正则对象在代码载入时(即编译时)生成;采用构造函数的方法,正则对象在代码运行时生成。考虑到书写的便利和直观,实际应用中,基本上都采用字面量的写法。

正则对象生成以后,有两种使用方式:

  • 正则对象的方法:将字符串作为参数,比如regex.test(string)
  • 字符串对象的方法:将正则对象作为参数,比如string.match(regex)

这两种使用方式下面都会介绍。

正则对象的属性和方法

属性

正则对象的属性分成两类。

一类是修饰符相关,返回一个布尔值,表示对应的修饰符是否设置。

  • ignoreCase:返回一个布尔值,表示是否设置了i修饰符,该属性只读。
  • global:返回一个布尔值,表示是否设置了g修饰符,该属性只读。
  • multiline:返回一个布尔值,表示是否设置了m修饰符,该属性只读。
var r = /abc/igm;

r.ignoreCase // true
r.global // true
r.multiline // true

另一类是与修饰符无关的属性,主要是下面两个。

  • lastIndex:返回下一次开始搜索的位置。该属性可读写,但是只在设置了g修饰符时有意义。
  • source:返回正则表达式的字符串形式(不包括反斜杠),该属性只读。
var r = /abc/igm;

r.lastIndex // 0
r.source // "abc"

test()

正则对象的test方法返回一个布尔值,表示当前模式是否能匹配参数字符串。

/cat/.test('cats and dogs') // true

上面代码验证参数字符串之中是否包含cat,结果返回true

如果正则表达式带有g修饰符,则每一次test方法都从上一次结束的位置开始向后匹配。

var r = /x/g;
var s = '_x_x';

r.lastIndex // 0
r.test(s) // true

r.lastIndex // 2
r.test(s) // true

r.lastIndex // 4
r.test(s) // false

上面代码的正则对象使用了g修饰符,表示要记录搜索位置。接着,三次使用test方法,每一次开始搜索的位置都是上一次匹配的后一个位置。

带有g修饰符时,可以通过正则对象的lastIndex属性指定开始搜索的位置。

var r = /x/g;
var s = '_x_x';

r.lastIndex = 4;
r.test(s) // false

上面代码指定从字符串的第五个位置开始搜索,这个位置是没有字符的,所以返回false

lastIndex属性只对同一个正则表达式有效,所以下面这样写是错误的。

var count = 0;
while (/a/g.test('babaa')) count++;

上面代码会导致无限循环,因为while循环的每次匹配条件都是一个新的正则表达式,导致lastIndex属性总是等于0。

如果正则模式是一个空字符串,则匹配所有字符串。

new RegExp('').test('abc')
// true

exec()

正则对象的exec方法,可以返回匹配结果。如果发现匹配,就返回一个数组,成员是每一个匹配成功的子字符串,否则返回null

var s = '_x_x';
var r1 = /x/;
var r2 = /y/;

r1.exec(s) // ["x"]
r2.exec(s) // null

上面代码中,正则对象r1匹配成功,返回一个数组,成员是匹配结果;正则对象r2匹配失败,返回null

如果正则表示式包含圆括号(即含有“组匹配”),则返回的数组会包括多个成员。第一个成员是整个匹配成功的结果,后面的成员就是圆括号对应的匹配成功的组。也就是说,第二个成员对应第一个括号,第三个成员对应第二个括号,以此类推。整个数组的length属性等于组匹配的数量再加1。

var s = '_x_x';
var r = /_(x)/;

r.exec(s) // ["_x", "x"]

上面代码的exec方法,返回一个数组。第一个成员是整个匹配的结果,第二个成员是圆括号匹配的结果。

exec方法的返回数组还包含以下两个属性:

  • input:整个原字符串。
  • index:整个模式匹配成功的开始位置(从0开始计数)。
var r = /a(b+)a/;
var arr = r.exec('_abbba_aba_');

arr // ["abbba", "bbb"]

arr.index // 1
arr.input // "_abbba_aba_"

上面代码中的index属性等于1,是因为从原字符串的第二个位置开始匹配成功。

如果正则表达式加上g修饰符,则可以使用多次exec方法,下一次搜索的位置从上一次匹配成功结束的位置开始。

var r = /a(b+)a/g;

var a1 = r.exec('_abbba_aba_');
a1 // ['abbba', 'bbb']
a1.index // 1
r.lastIndex // 6

var a2 = r.exec('_abbba_aba_');
a2 // ['aba', 'b']
a2.index // 7
r.lastIndex // 10

var a3 = r.exec('_abbba_aba_');
a3 // null
a3.index // TypeError: Cannot read property 'index' of null
r.lastIndex // 0

var a4 = r.exec('_abbba_aba_');
a4 // ['abbba', 'bbb']
a4.index // 1
r.lastIndex // 6

上面代码连续用了四次exec方法,前三次都是从上一次匹配结束的位置向后匹配。当第三次匹配结束以后,整个字符串已经到达尾部,正则对象的lastIndex属性重置为0,意味着第四次匹配将从头开始。

利用g修饰符允许多次匹配的特点,可以用一个循环完成全部匹配。

var r = /a(b+)a/g;
var s = '_abbba_aba_';

while(true) {
  var match = r.exec(s);
  if (!match) break;
  console.log(match[1]);
}
// bbb
// b

正则对象的lastIndex属性不仅可读,还可写。一旦手动设置了lastIndex的值,就会从指定位置开始匹配。但是,这只在设置了g修饰符的情况下,才会有效。

var r = /a/;

r.lastIndex = 7; // 无效
var match = r.exec('xaxa');
match.index // 1
r.lastIndex // 7

上面代码设置了lastIndex属性,但是因为正则表达式没有g修饰符,所以是无效的。每次匹配都是从字符串的头部开始。

如果有g修饰符,lastIndex属性就会生效。

var r = /a/g;

r.lastIndex = 2;
var match = r.exec('xaxa');
match.index // 3
r.lastIndex // 4

上面代码中,lastIndex属性指定从字符的第三个位置开始匹配。成功后,下一次匹配就是从第五个位置开始。

如果正则对象是一个空字符串,则exec方法会匹配成功,但返回的也是空字符串。

var r1 = new RegExp('');
var a1 = r1.exec('abc');
a1 // ['']
a1.index // 0
r1.lastIndex // 0

var r2 = new RegExp('()');
var a2 = r2.exec('abc');
a2 // ['', '']
a2.index // 0
r2.lastIndex // 0

字符串对象的方法

字符串对象的方法之中,有4种与正则对象有关。

  • match():返回一个数组,成员是所有匹配的子字符串。
  • search():按照给定的正则表达式进行搜索,返回一个整数,表示匹配开始的位置。
  • replace():按照给定的正则表达式进行替换,返回替换后的字符串。
  • split():按照给定规则进行字符串分割,返回一个数组,包含分割后的各个成员。

下面逐一介绍。

String.prototype.match()

字符串对象的match方法对字符串进行正则匹配,返回匹配结果。

var s = '_x_x';
var r1 = /x/;
var r2 = /y/;

s.match(r1) // ["x"]
s.match(r2) // null

从上面代码可以看到,字符串的match方法与正则对象的exec方法非常类似:匹配成功返回一个数组,匹配失败返回null

如果正则表达式带有g修饰符,则该方法与正则对象的exec方法行为不同,会一次性返回所有匹配成功的结果。

var s = 'abba';
var r = /a/g;

s.match(r) // ["a", "a"]
r.exec(s) // ["a"]

设置正则表达式的lastIndex属性,对match方法无效,匹配总是从字符串的第一个字符开始。

var r = /a|b/g;
r.lastIndex = 7;
'xaxb'.match(r) // ['a', 'b']
r.lastIndex // 0

上面代码表示,设置lastIndex属性是无效的。

String.prototype.search()

字符串对象的search方法,返回第一个满足条件的匹配结果在整个字符串中的位置。如果没有任何匹配,则返回-1

'_x_x'.search(/x/)
// 1

上面代码中,第一个匹配结果出现在字符串的1号位置。

该方法会忽略g修饰符。

var r = /x/g;
r.lastIndex = 2; // 无效
'_x_x'.search(r) // 1

上面代码中,正则表达式使用g修饰符之后,使用lastIndex属性指定开始匹配的位置,结果无效,还是从字符串的第一个字符开始匹配。

String.prototype.replace()

字符串对象的replace方法可以替换匹配的值。它接受两个参数,第一个是搜索模式,第二个是替换的内容。

str.replace(search, replacement)

搜索模式如果不加g修饰符,就替换第一个匹配成功的值,否则替换所有匹配成功的值。

'aaa'.replace('a', 'b') // "baa"
'aaa'.replace(/a/, 'b') // "baa"
'aaa'.replace(/a/g, 'b') // "bbb"

上面代码中,最后一个正则表达式使用了g修饰符,导致所有的b都被替换掉了。

replace方法的一个应用,就是消除字符串首尾两端的空格。

var str = '  #id div.class  ';

str.replace(/^\s+|\s+$/g, '')
// "#id div.class"

replace方法的第二个参数可以使用美元符号$,用来指代所替换的内容。

  • $& 指代匹配的子字符串。
  • $` 指代匹配结果前面的文本。
  • $' 指代匹配结果后面的文本。
  • $n 指代匹配成功的第n组内容,n是从1开始的自然数。
  • $$ 指代美元符号$
'hello world'.replace(/(\w+)\s(\w+)/, '$2 $1')
// "world hello"

'abc'.replace('b', '[$`-$&-$\']')
// "a[a-b-c]c"

replace方法的第二个参数还可以是一个函数,将每一个匹配内容替换为函数返回值。

'3 and 5'.replace(/[0-9]+/g, function(match){
  return 2 * match;
})
// "6 and 10"

var a = 'The quick brown fox jumped over the lazy dog.';
var pattern = /quick|brown|lazy/ig;

a.replace(pattern, function replacer(match) {
  return match.toUpperCase();
});
// The QUICK BROWN fox jumped over the LAZY dog.

作为replace方法第二个参数的替换函数,可以接受多个参数。第一个参数是捕捉到的内容,第二个参数是捕捉到的组匹配(有多少个组匹配,就有多少个对应的参数)。此外,最后还可以添加两个参数,倒数第二个参数是捕捉到的内容在整个字符串中的位置(比如从第五个位置开始),最后一个参数是原字符串。下面是一个网页模板替换的例子。

var prices = {
  'pr_1': '$1.99',
  'pr_2': '$9.99',
  'pr_3': '$5.00'
};

var template = '/* ... */'; // 这里可以放网页模块字符串

template.replace(
  /(<span id=")(.*?)(">)(<\/span>)/g,
  function(match, $1, $2, $3, $4){
    return $1 + $2 + $3 + prices[$2] + $4;
  }
);

上面代码的捕捉模式中,有四个括号,所以会产生四个组匹配,在匹配函数中用$1$4表示。匹配函数的作用是将价格插入模板中。

String.prototype.split()

字符串对象的split方法按照正则规则分割字符串,返回一个由分割后的各个部分组成的数组。

str.split(separator, [limit])

该方法接受两个参数,第一个参数是分隔规则,第二个参数是返回数组的最大成员数。

// 非正则分隔
'a,  b,c, d'.split(',')
// [ 'a', '  b', 'c', ' d' ]

// 正则分隔,去除多余的空格
'a,  b,c, d'.split(/, */)
// [ 'a', 'b', 'c', 'd' ]

// 指定返回数组的最大成员
'a,  b,c, d'.split(/, */, 2)
[ 'a', 'b' ]

上面代码使用正则表达式,去除了子字符串的逗号后面的空格。

// 例一
'aaa*a*'.split(/a*/)
// [ '', '*', '*' ]

// 例二
'aaa**a*'.split(/a*/)
// ["", "*", "*", "*"]

上面代码的分割规则是0次或多次的a,由于正则默认是贪婪匹配,所以例一的第一个分隔符是aaa,第二个分割符是a,将字符串分成三个部分,包含开始处的空字符串。例二的第一个分隔符是aaa,第二个分隔符是0个a(即空字符),第三个分隔符是a,所以将字符串分成四个部分。

如果正则表达式带有括号,则括号匹配的部分也会作为数组成员返回。

'aaa*a*'.split(/(a*)/)
// [ '', 'aaa', '*', 'a', '*' ]

上面代码的正则表达式使用了括号,第一个组匹配是“aaa”,第二个组匹配是“a”,它们都作为数组成员返回。

匹配规则

正则表达式对字符串的匹配有很复杂的规则。下面一一介绍这些规则。

字面量字符和元字符

大部分字符在正则表达式中,就是字面的含义,比如/a/匹配a/b/匹配b。如果在正则表达式之中,某个字符只表示它字面的含义(就像前面的ab),那么它们就叫做“字面量字符”(literal characters)。

/dog/.test("old dog") // true

上面代码中正则表达式的dog,就是字面量字符,所以/dog/匹配“old dog”,因为它就表示“d”、“o”、“g”三个字母连在一起。

除了字面量字符以外,还有一部分字符有特殊含义,不代表字面的意思。它们叫做“元字符”(metacharacters),主要有以下几个。

(1)点字符(.)

点字符(.)匹配除回车(\r)、换行(\n) 、行分隔符(\u2028)和段分隔符(\u2029)以外的所有字符。

/c.t/

上面代码中,c.t匹配ct之间包含任意一个字符的情况,只要这三个字符在同一行,比如catc2tc-t等等,但是不匹配coot

(2)位置字符

位置字符用来提示字符所处的位置,主要有两个字符。

  • ^ 表示字符串的开始位置
  • $ 表示字符串的结束位置
// test必须出现在开始位置
/^test/.test('test123') // true

// test必须出现在结束位置
/test$/.test('new test') // true

// 从开始位置到结束位置只有test
/^test$/.test('test') // true
/^test$/.test('test test') // false

(3)选择符(|

竖线符号(|)在正则表达式中表示“或关系”(OR),即cat|dog表示匹配catdog

/11|22/.test('911') // true

上面代码中,正则表达式指定必须匹配1122

多个选择符可以联合使用。

// 匹配fred、barney、betty之中的一个
/fred|barney|betty/

选择符会包括它前后的多个字符,比如/ab|cd/指的是匹配ab或者cd,而不是指匹配b或者c。如果想修改这个行为,可以使用圆括号。

/a( |\t)b/.test('a\tb') // true

上面代码指的是,ab之间有一个空格或者一个制表符。

其他的元字符还包括\\\*+?()[]{}等,将在下文解释。

转义符

正则表达式中那些有特殊含义的字符,如果要匹配它们本身,就需要在它们前面要加上反斜杠。比如要匹配加号,就要写成\+

/1+1/.test('1+1')
// false

/1\+1/.test('1+1')
// true

上面代码中,第一个正则表达式直接用加号匹配,结果加号解释成量词,导致不匹配。第二个正则表达式使用反斜杠对加号转义,就能匹配成功。

正则模式中,需要用斜杠转义的,一共有12个字符:^.[$()|*+?{\\。需要特别注意的是,如果使用RegExp方法生成正则对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。

(new RegExp('1\+1')).test('1+1')
// false

(new RegExp('1\\+1')).test('1+1')
// true

上面代码中,RegExp作为构造函数,参数是一个字符串。但是,在字符串内部,反斜杠也是转义字符,所以它会先被反斜杠转义一次,然后再被正则表达式转义一次,因此需要两个反斜杠转义。

特殊字符

正则表达式对一些不能打印的特殊字符,提供了表达方法。

  • \cX 表示Ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字符。
  • [\b] 匹配退格键(U+0008),不要与\b混淆。
  • \n 匹配换行键。
  • \r 匹配回车键。
  • \t 匹配制表符tab(U+0009)。
  • \v 匹配垂直制表符(U+000B)。
  • \f 匹配换页符(U+000C)。
  • \0 匹配null字符(U+0000)。
  • \xhh 匹配一个以两位十六进制数(\x00-\xFF)表示的字符。
  • \uhhhh 匹配一个以四位十六进制数(\u0000-\uFFFF)表示的unicode字符。

字符类

字符类(class)表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内,比如[xyz] 表示xyz之中任选一个匹配。

/[abc]/.test('hello world') // false
/[abc]/.test('apple') // true

上面代码表示,字符串“hello world”不包含abc这三个字母中的任一个,而字符串“apple”包含字母a

有两个字符在字符类中有特殊含义。

(1)脱字符(^)

如果方括号内的第一个字符是[^],则表示除了字符类之中的字符,其他字符都可以匹配。比如,[^xyz]表示除了xyz之外都可以匹配。

/[^abc]/.test('hello world') // true
/[^abc]/.test('bbc') // false

上面代码表示,字符串“hello world”不包含字母abc中的任一个,所以返回true;字符串“bbc”不包含abc以外的字母,所以返回false

如果方括号内没有其他字符,即只有[^],就表示匹配一切字符,其中包括换行符,而点号(.)是不包括换行符的。

var s = 'Please yes\nmake my day!';

s.match(/yes.*day/) // null
s.match(/yes[^]*day/) // [ 'yes\nmake my day']

上面代码中,字符串s含有一个换行符,点号不包括换行符,所以第一个正则表达式匹配失败;第二个正则表达式[^]包含一切字符,所以匹配成功。

注意,脱字符只有在字符类的第一个位置才有特殊含义,否则就是字面含义。

(2)连字符(-)

某些情况下,对于连续序列的字符,连字符(-)用来提供简写形式,表示字符的连续范围。比如,[abc]可以写成[a-c][0123456789]可以写成[0-9],同理[A-Z]表示26个大写字母。

/a-z/.test('b') // false
/[a-z]/.test('b') // true

上面代码中,当连字号(dash)不出现在方括号之中,就不具备简写的作用,只代表字面的含义,所以不匹配字符b。只有当连字号用在方括号之中,才表示连续的字符序列。

以下都是合法的字符类简写形式。

[0-9.,]
[0-9a-fA-F]
[a-zA-Z0-9-]
[1-31]

上面代码中最后一个字符类[1-31],不代表131,只代表13

注意,字符类的连字符必须在头尾两个字符中间,才有特殊含义,否则就是字面含义。比如,[-9]就表示匹配连字符和9,而不是匹配09

连字符还可以用来指定Unicode字符的范围。

var str = "\u0130\u0131\u0132";
/[\u0128-\uFFFF]/.test(str)
// true

另外,不要过分使用连字符,设定一个很大的范围,否则很可能选中意料之外的字符。最典型的例子就是[A-z],表面上它是选中从大写的A到小写的z之间52个字母,但是由于在ASCII编码之中,大写字母与小写字母之间还有其他字符,结果就会出现意料之外的结果。

/[A-z]/.test('\\') // true

上面代码中,由于反斜杠(\\)的ASCII码在大写字母与小写字母之间,结果会被选中。

预定义模式

预定义模式指的是某些常见模式的简写方式。

  • \d 匹配0-9之间的任一数字,相当于[0-9]
  • \D 匹配所有0-9以外的字符,相当于[^0-9]
  • \w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]
  • \W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]
  • \s 匹配空格(包括制表符、空格符、断行符等),相等于[\t\r\n\v\f]
  • \S 匹配非空格的字符,相当于[^\t\r\n\v\f]
  • \b 匹配词的边界。
  • \B 匹配非词边界,即在词的内部。

下面是一些例子。

// \s的例子
/\s\w*/.exec('hello world') // [" world"]

// \b的例子
/\bworld/.test('hello world') // true
/\bworld/.test('hello-world') // true
/\bworld/.test('helloworld') // false

// \B的例子
/\Bworld/.test('hello-world') // false
/\Bworld/.test('helloworld') // true

上面代码中,\s表示空格,所以匹配结果会包括空格。\b表示词的边界,所以“world”的词首必须独立(词尾是否独立未指定),才会匹配。同理,\B表示非词的边界,只有“world”的词首不独立,才会匹配。

通常,正则表达式遇到换行符(\n)就会停止匹配。

var html = "<b>Hello</b>\n<i>world!</i>";

/.*/.exec(html)[0]
// "<b>Hello</b>"

上面代码中,字符串html包含一个换行符,结果点字符(.)不匹配换行符,导致匹配结果可能不符合原意。这时使用\s字符类,就能包括换行符。

var html = "<b>Hello</b>\n<i>world!</i>";

/[\S\s]*/.exec(html)[0]
// "<b>Hello</b>\n<i>world!</i>"

// 另一种写法(用到了非捕获组)
/(?:.|\s)*/.exec(html)[0]
// "<b>Hello</b>\n<i>world!</i>"

上面代码中,[\S\s]指代一切字符。

重复类

模式的精确匹配次数,使用大括号({})表示。{n}表示恰好重复n次,{n,}表示至少重复n次,{n,m}表示重复不少于n次,不多于m次。

/lo{2}k/.test('look') // true
/lo{2, 5}k/.test('looook') // true

上面代码中,第一个模式指定o连续出现2次,第二个模式指定o连续出现2次到5次之间。

量词符

量词符用来设定某个模式出现的次数。

  • ? 问号表示某个模式出现0次或1次,等同于{0, 1}
  • * 星号表示某个模式出现0次或多次,等同于{0,}
  • + 加号表示某个模式出现1次或多次,等同于{1,}
// t出现0次或1次
/t?est/.test('test') // true
/t?est/.test('est') // true

// t出现1次或多次
/t+est/.test('test") // true
/t+est/.test('ttest') // true
/t+est/.test('est') // false

// t出现0次或多次
/t*est/.test('test') // true
/t*est/.test('ttest') // true
/t*est/.test('tttest') // true
/t*est/.test('est') // true

贪婪模式

上一小节的三个量词符,默认情况下都是最大可能匹配,即匹配直到下一个字符不满足匹配规则为止。这被称为贪婪模式。

var s = 'aaa';
s.match(/a+/) // ["aaa"]

上面代码中,模式是/a+/,表示匹配1个a或多个a,那么到底会匹配几个a呢?因为默认是贪婪模式,会一直匹配到字符a不出现为止,所以匹配结果是3个a

如果想将贪婪模式改为非贪婪模式,可以在量词符后面加一个问号。

var s = 'aaa';
s.match(/a+?/) // ["a"]

上面代码中,模式结尾添加了一个问号/a+?/,这时就改为非贪婪模式,一旦条件满足,就不再往下匹配。

除了非贪婪模式的加号,还有非贪婪模式的星号(*)。

  • *?:表示某个模式出现0次或多次,匹配时采用非贪婪模式。
  • +?:表示某个模式出现1次或多次,匹配时采用非贪婪模式。

修饰符

修饰符(modifier)表示模式的附加规则,放在正则模式的最尾部。

修饰符可以单个使用,也可以多个一起使用。

// 单个修饰符
var regex = /test/i;

// 多个修饰符
var regex = /test/ig;

(1)g修饰符

默认情况下,第一次匹配成功后,正则对象就停止向下匹配了。g修饰符表示全局匹配(global),加上它以后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换。

var regex = /b/;
var str = 'abba';

regex.test(str); // true
regex.test(str); // true
regex.test(str); // true

上面代码中,正则模式不含g修饰符,每次都是从字符串头部开始匹配。所以,连续做了三次匹配,都返回true

var regex = /b/g;
var str = 'abba';

regex.test(str); // true
regex.test(str); // true
regex.test(str); // false

上面代码中,正则模式含有g修饰符,每次都是从上一次匹配成功处,开始向后匹配。因为字符串“abba”只有两个“b”,所以前两次匹配结果为true,第三次匹配结果为false

(2)i修饰符

默认情况下,正则对象区分字母的大小写,加上i修饰符以后表示忽略大小写(ignorecase)。

/abc/.test('ABC') // false
/abc/i.test('ABC') // true

上面代码表示,加了i修饰符以后,不考虑大小写,所以模式abc匹配字符串ABC

(3)m修饰符

m修饰符表示多行模式(multiline),会修改^$的行为。默认情况下(即不加m修饰符时),^$匹配字符串的开始处和结尾处,加上m修饰符以后,^$还会匹配行首和行尾,即^$会识别换行符(\n)。

/world$/.test('hello world\n') // false
/world$/m.test('hello world\n') // true

上面的代码中,字符串结尾处有一个换行符。如果不加m修饰符,匹配不成功,因为字符串的结尾不是“world”;加上以后,$可以匹配行尾。

/^b/m.test('a\nb') // true

上面代码要求匹配行首的b,如果不加m修饰符,就相当于b只能处在字符串的开始处。

组匹配

(1)概述

正则表达式的括号表示分组匹配,括号中的模式可以用来匹配分组的内容。

/fred+/.test('fredd') // true
/(fred)+/.test('fredfred') // true

上面代码中,第一个模式没有括号,结果+只表示重复字母d,第二个模式有括号,结果+就表示匹配“fred”这个词。

下面是另外一个分组捕获的例子。

var m = 'abcabc'.match(/(.)b(.)/);
m
// ['abc', 'a', 'c']

上面代码中,正则表达式/(.)b(.)/一共使用两个括号,第一个括号捕获a,第二个括号捕获c

注意,使用组匹配时,不宜同时使用g修饰符,否则match方法不会捕获分组的内容。

var m = 'abcabc'.match(/(.)b(.)/g);
m
// ['abc', 'abc']

上面代码使用带g修饰符的正则表达式,结果match方法只捕获了匹配整个表达式的部分。

在正则表达式内部,可以用\n引用括号匹配的内容,n是从1开始的自然数,表示对应顺序的括号。

/(.)b(.)\1b\2/.test("abcabc")
// true

上面的代码中,\1表示前一个括号匹配的内容(即“a”),\2表示第二个括号匹配的内容(即“b”)。

下面是另外一个例子。

/y(..)(.)\2\1/.test('yabccab') // true

括号还可以嵌套。

/y((..)\2)\1/.test('yabababab') // true

上面代码中,\1指向外层括号,\2指向内层括号。

组匹配非常有用,下面是一个匹配网页标签的例子。

var tagName = /<([^>]+)>[^<]*<\/\1>/;

tagName.exec("<b>bold</b>")[1]
// 'b'

上面代码中,圆括号匹配尖括号之中的标签,而\1就表示对应的闭合标签。

上面代码略加修改,就能捕获带有属性的标签。

var html = '<b class="hello">Hello</b><i>world</i>';
var tag = /<(\w+)([^>]*)>(.*?)<\/\1>/g;

var match = tag.exec(html);

match[1] // "b"
match[2] // "class="hello""
match[3] // "Hello"

match = tag.exec(html);

match[1] // "i"
match[2] // ""
match[3] // "world"

(2)非捕获组

(?:x)称为非捕获组(Non-capturing group),表示不返回该组匹配的内容,即匹配的结果中不计入这个括号。

非捕获组的作用请考虑这样一个场景,假定需要匹配foo或者foofoo,正则表达式就应该写成/(foo){1, 2}/,但是这样会占用一个组匹配。这时,就可以使用非捕获组,将正则表达式改为/(?:foo){1, 2}/,它的作用与前一个正则是一样的,但是不会单独输出括号内部的内容。

请看下面的例子。

var m = 'abc'.match(/(?:.)b(.)/);
m // ["abc", "c"]

上面代码中的模式,一共使用了两个括号。其中第一个括号是非捕获组,所以最后返回的结果中没有第一个括号,只有第二个括号匹配的内容。

下面是用来分解网址的正则表达式。

// 正常匹配
var url = /(http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;

url.exec('http://google.com/');
// ["http://google.com/", "http", "google.com", "/"]

// 非捕获组匹配
var url = /(?:http|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?/;

url.exec('http://google.com/');
// ["http://google.com/", "google.com", "/"]

上面的代码中,前一个正则表达式是正常匹配,第一个括号返回网络协议;后一个正则表达式是非捕获匹配,返回结果中不包括网络协议。

(3)先行断言

x(?=y)称为先行断言(Positive look-ahead),x只有在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟着百分号的数字,可以写成/\d+(?=%)/

“先行断言”中,括号里的部分是不会返回的。

var m = 'abc'.match(/b(?=c)/);
m // ["b"]

上面的代码使用了先行断言,bc前面所以被匹配,但是括号对应的c不会被返回。

再看一个例子。

/Jack (?=Sprat|Frost)/.test('Jack Frost') // true

(4)先行否定断言

x(?!y)称为先行否定断言(Negative look-ahead),x只有不在y前面才匹配,y不会被计入返回结果。比如,要匹配后面跟的不是百分号的数字,就要写成/\d+(?!%)/

/\d+(?!\.)/.exec('3.14')
// ["14"]

上面代码中,正则表达式指定,只有不在小数点前面的数字才会被匹配,因此返回的结果就是14

“先行否定断言”中,括号里的部分是不会返回的。

var m = 'abd'.match(/b(?!c)/);
m // ['b']

上面的代码使用了先行否定断言,b不在c前面所以被匹配,而且括号对应的d不会被返回。

参考链接

获取元素样式 document.defaultView.getComputedStyle

语法

var style = window.getComputedStyle("元素", "伪类");

如果第二个元素不是伪类,那么就填写 null

getComputedStyle与style的区别

我们使用element.style也可以获取元素的CSS样式声明对象,但是其与getComputedStyle方法还有有一些差异的。

  • 只读与可写
    正如上面提到的getComputedStyle方法是只读的,只能获取样式,不能设置;而element.style能读能写,能屈能伸。
  • 获取的对象范围
    getComputedStyle方法获取的是最终应用在元素上的所有CSS属性对象(即使没有CSS代码,也会把默认的祖宗八代都显示出来);而element.style只能获取元素style属性中的CSS样式。因此对于一个光秃秃的元素<p>getComputedStyle方法返回对象中length属性值(如果有)就是190+(据我测试FF:192, IE9:195, Chrome:253, 不同环境结果可能有差异), 而element.style就是0。

兼容性

function getStyle(elem, property) {
    // ie通过currentStyle来获取元素的样式,其他浏览器通过getComputedStyle来获取
    return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(elem, false)[property] : elem.currentStyle[property];
}

参考链接:http://www.zhangxinxu.com/wordpress/2012/05/getcomputedstyle-js-getpropertyvalue-currentstyle/

共享单车有望成为未来连接线上线下的入口

最近唱衰共享单车的很多,其中一篇凤凰网科技频道的《共享单车与Uber不具有可比性 没有任何经济意义》尤甚,在我的朋友圈出现了五六次,我觉得有必要和这篇文章编辑谈谈互联网思维了。

这篇有两个看起来“没毛病”的观点,文章认为所谓共享单车其实是“伪共享”,不具有Uber的网络效应,多一个用户就得多造一辆车,还有就是共享单车1元/小时左右的租金与其损毁率使其难以正常盈利。

“伪共享”这个概念我表示同意,摩拜还有 ofo 实际上是租赁经济而非真正的共享经济,共享经济是指用户间的共享闲置物品的商业模式,像滴滴快车就是私家车主利用上下班或者空闲时间赚一部分钱,事实上和文章提出观点一样,单车们不具有网络效应。不过如果我们按照“所有权”和“使用权”的角度来讲,摩拜和 ofo 们确实可以称之为“共享单车”。

接下来我们来看看不具有网络效应的单车们能否1块钱收回成本。

最近虎嗅网写了一篇关于共享单车的成本和利润的账,给“共享单车”算一笔账,未来18个月见生死,文章的数据虽然有些臆测,但还是有参考价值,我把成本和利润总结为下,具体可参考原文。

  • 各运营平台的配置已有趋同的迹象,真正规模化之后,单车成本有望降到600元左右。每月被骑100次、收入100元是比较靠谱的假设。
  • 投放和管理成本每月投放成本约800万,每次维护工、物料费按20元计,全年维护费用为40元/年。以及- 各种损毁率和营销费用、政策或许3年报废的限制,让单车成本继续上升。行政管理、研发、线上平台运维以及派往每个城市的数十位“非临时工”用工成本,相对保守计算为2500万/月或3亿/年。
  • 综上一年需要65亿元成本。

照这样看,一元确实不太好收回成本,也不要说能够正现金流盈利了。

有人说押金可以带来银行利息,姑且这个算一个吧,但是目前ofo和蚂蚁信用合作在上海650分免押金,永安行甚至一开始就不收押金,而且媒体舆论以及金融监管的压力,要想做“押金金融”在未来也没什么可能了。

所以凤凰网的编辑得出结论:

目前的共享单车业务就是看各家公司能募集到多少资金,砸钱换市场份额。问题是,即使获得了市场份额,它们也无法真正盈利。
租金,租金,还是租金...难道单车就只有租赁那1元钱的价值吗?

我认为单车有望成为下一个连接线上和线下的入口,接下来我会从头开始分析这个产品,说说我是如何得出这个结论的。

共享单车概念的简单说就是解决“最后5公里出行”的问题的平台,主要覆盖人群是18岁到35岁学生、白领等社会主力消费人群,目前在北上广深等一二线城市运营,主要集中在消费以及商务聚集区域。

在分析产品形式的时候大家都喜欢讨论“刚需高频” ,最近有些运营圈的朋友说,共享单车这种非刚需用补贴赚市场的行为是不会成功的,然后甩给我一个“高大上”的经济学定律以及“需求”分析——

  1. 好不容易大家生活水平提高了,单车渐渐不用了,特么的现在又是满大街单车。谁也不想回到八十年代慢速生活。

  2. 经济学上有个“报酬定律”,补贴制度注定是不符合市场经济经济的,都会黄掉。

那单车到底有没有用户需求?

我只能说,作为“衣食住行”的一个环节,共享单车算不算需求!?好吧,说点实际的,共享单车这些用户群体的使用场景,参照我自己和周围同事朋友,基本有以下几点:

上班离地铁大概有两三公里,等公交可能等待的时间长,打的又太贵,还有可能堵车,直接走过去又太浪费时间,骑车只要五六分钟就可以到地铁站了,还很便宜。(通勤)
一天上班都坐着,就只有通勤的路上可能多走几步或者站一会,骑车相当于多运动一会。(运动)
超市离家还是有段距离,直接骑车过去比较方便省时间。(生活)
到附近的电影院看电影,或者到附近的商场购物,或者去网吧开黑,骑车相对而言很方便。周末空气很好,一起骑车去公园。(娱乐)
有个客户离公司很近,直接骑车去就可以了。(工作)
如果按照这种需求分析的话,单车使用频次为平均一天使用一到三次,相比一天吃饭三次这种频次,单车对于我和我周边的朋友而言可以说是硬需求了,如果继续推及他人的话,以我们小区为例,“单车停车位置”在工作日,甚至周末都有不断的流动迹象。(我问过小区的保安,单车确实使用挺频繁的)

当然你也可以反驳我,你自己就不用单车,而且现在一直免费,这样算不对。那就得说下一个问题了,如果是有一定“硬需求”的产品,前期补贴会换回用户习惯吗?

以前期补贴巨大的饿了么和美团外卖举例,美团外面日订单已经超过千万,当然最近ofo也宣布自己也日订单超千万。去年11月份饿了么CEO被采访时也谈及现在为了省时间大多都不做饭,改订外卖的居多。基于此,我有理由相信单车未来如果不补贴也会形成大规模的用户习惯。

简单的做一个PEST分析。国家政策上对待单车目前相对保守,可能会对单车进行相关法律法规的限制,但也为了用户的安全使用,如果以十三五推行环保方针的话,未来政策总体还是利好共享单车的;单车们目前估值百亿,摩拜和 ofo 都融资了近30亿元,而大多数单车用户是有比较稳定收入的群体,对单车接受度也很高;国内的技术生产能力较高,代工厂也很多,单车的技术会越来越先进,用户体验会越来越好。

前面我说共享单车的用户群体主要是80和90后的学生、白领等目前主力消费人群是根据目前我自己的观察得出的结论,不过想想扫码、押金等这些操作对于其它群体而言确实有门槛,基于此也可以推断出这个结论。

当我们得出单车的用户群体是社会主力消费人群的结论,那单车的商业模式就有想象空间了,接下来我们谈谈除了租金外,单车还有哪些盈利模式。

下面可就是脑洞大开环节了。

周一我骑了一个小时的车,然后锁车的时候,APP提示我获得了一个红包,我一看是《金刚2》的兑换券,这个兑换券可以在公司附近的电影院使用。因为我骑行了超过100公里,然后可以直接用积分兑换一张电影票(通用积分),就这样我还约了妹纸就看了场电影。

因为我是这个单车的会员,这个月我可以无限次的使用,还有专线客服通道。(增值服务)

接着公司微信群内,我的同事给发了一个单车红包的链接,除了有单车骑行券之外,在领红包的页面上还有最新肯德基的优惠券(异业合作),前天正好我在肯德基消费过一次(用户消费数据),因为我留下了我的手机号还成了他们的会员。

周末的时候,我参加了单车们和Keep(泛指移动健身软件)的线上单车越野比赛,因为那天吃的比较好,骑得比较快,我获得了第一名,奖品是700Bike提供的单车一辆。(异业合作)

我记得昨天我在这个红包链接还看到我家爱豆要在工体开演唱会的消息,那得去呀,在这个红包页面上我还看到可以直接订票的信息。(广告合作)

第二天,我打开支付宝蚂蚁森林,因为昨天骑了10公里,就这样今天我能为我的小树苗加300g能量,这颗虚拟树满18kg就会在现实中种下一颗。为环保做了贡献,还挺自豪的。(公益金融)

好了,这些脑洞都可能会实现。在我写这篇文章的时候,摩拜单车已经做了一个类似 PokemonGo 的应用,叫做摩拜红包车,如果我们再思考一下这个方向,这不就是很好的结合了线上线下成为了一个有巨大想象力的入口吗?

最后谈谈那买车比单车划算吗?

如果我们仅仅用钱来衡量划算不换算,一天使用两三次,使用半年差不多就能买个能自行车,那买车很划算。不过如果加上单车占有空间的话,可能就不那么划算了,如果我们按照北上广深的租金来算占用空间的成本 ,可想而知并那么划算。好吧,我们不放在室内,放在公共地方,为了防止有被盗的风险,我们还得放个好点的锁头。如果在通勤路上车坏了,你会放心的直接放在路边吗?这里不仅仅包括维护成本,还有我们为此所付出的心理和时间成本。

本文仅仅抛砖引玉,如果你有更好的想法可以在下面留言。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.