跟随,学习,进步

开源社区贡献者协议介绍

2019-04-20 07:16:09 宋净超

很多从事开源人可能会注意到有些开源项目要求贡献者在提交 PR 前首先签署 CLA,只有签署了 CLA 之后 PR 才可以合并。 开源贡献协议简介 下面列举了开源贡献协


每周分享第 52 期

2019-04-19 02:32:07 阮一峰

这里记录过去一周,我看到的值得分享的东西,每周五发布。 欢迎投稿,或推荐你自己的项目,请前往 GitHub 的 ruanyf/weekly 提交 issue。 据报道,汉王科技开发了一个"课堂呵护系统",已经在北京牛栏山一中、内蒙古赤峰四中等全国七所学校试点。 该系统在黑板上方安装了一个摄像头,上课时每秒对整个班级拍摄一张照片,然后进行人脸识别,判断谁在专心听课,谁在开小差,谁在讲悄悄话,以及谁在睡觉。 老师打开电脑或手机,可以查看统计结果。每个学生名字后面都有一个图形,红色的向上三角形,表示该学生本周专心听课时间上升,绿色的向下三角形表示下降。 该系统单个教室的安装成本是3万元人民币,学校不需要出钱,所有费用由当地教育局提供财政补助,作为在学校推广人工智能和大数据的体现。除了汉王公司,杭州的海康威视也开发了类似的"智能教室行为管理系统",采样频率低一点,每30秒才拍摄一次照片。 我想,以后不仅是学校,政府机关、公司、工厂应该也会安装类似系统,对员工进行不间断的人脸识别,评估他每天有多少时间在安心工作。这比上下班打卡,对企业更有利。 新闻 1、飞机上的摄像头 一位乘客发现,新加坡航空的座椅背面,液晶屏幕下面居然有摄像头。他把照片发到推特,引起一片哗然。新加坡航空不得不出面解释,这只是客机娱乐系统的标配,未来打算用于跟乘客互动,比如识别手势。新加坡航空称,从未启用摄像头,今后也不会用来监视用户。 但是,人们还是担心,黑客有可能控制这些它们,从而掌握乘客的一举一动。 2、开普勒望远镜的最后一张照片 2009年3月,美国发射了开普勒望远镜,用于观察太阳系外的行星。十年来,这架望远镜逐渐失灵,2018年9月25日,它拍摄了最后一张照片(上图),然后就不再工作了。 上图拍摄了水瓶座,缺少一些方格是因为相机的某些部分已经坏了。这个望远镜目前不再跟地球通信,从此永远围绕太阳公转。 3、种植肉 历史上,人类通过养殖动物得到肉类。现在越来越多的团队开始研究,能否像种植植物那样,把肉类种植出来。英国巴斯大学的团队,在叶子上种植了猪肉细胞;美国一家名叫 Just 的公司表示,它能够从鸡肉羽毛提取的细胞中,培养出鸡肉。 种植肉主要通过细胞分裂产生,最终产物是纯肌肉组织,基本上是瘦肉末。理论上,种植肉跟养殖肉的成分是一样的,但是为了得到相同的口味,需要添加脂肪细胞和结缔细胞。一旦种植肉证明在商业上可行,就会得到大规模推广。 4、横跨美国的列车 美国现在没有东西横穿全国的列车,19世纪淘金时代有,现在没有。如果你一定要坐火车,从东岸的纽约直到西岸的洛杉矶,并且愿意忍受中途换车,那么这2,448.8英里(相当于上海到乌鲁木齐)一共需要花费整整三天(67个小时),整趟行程的票价是1,089美元。 5、流媒体超过电视 美国电影协会 MPAA 宣布,2018年流媒体首次超过电视。美国人有52%的时间看网上视频,48%的时间看电视。 全球范围内,流媒体新增了1.312亿用户,用户总数达到6.133亿人,相比之下,有线电视用户下降了2%,达到5.56亿。另外,流媒体也挤压了 DVD 和蓝光光盘,美国的销售量2018年下降了15%。目前看来,五到十年内网络流媒体就会淘汰有线电视。 6、清江古生物化石 中国科学家在湖北省清江流域,发现了一处大型的古生物化石遗址,已经挖掘了2万多块化石。这些化石距今大约5.18亿年,其中是许多是软体生物。它们柔软的身体组织,包括皮肤、眼睛和内脏,都"精美地"保存完好。下图就是水母和节肢动物的化石,保存得极其完好,触须都清晰可见。 这些化石的珍贵之处在于,软体动物(比如水母和蠕虫)通常不会变成化石。大多数化石都是硬体动物,因为较硬的物质(比如骨头),不太可能腐烂和分解。清江生物群可能是由于突然的风暴,被迅速埋在沉积物中,才能使软组织得到很好的保存。 7、监控驾驶员 汽车的人工智能一般只用于判断车外环境,但是沃尔沃汽车反其道行之,将人工智能用于车内。2020年开始,每一辆出厂的沃尔沃汽车都会带有车内摄像头,专门观察驾驶员的眼睛。 如果发现驾驶员分心,没有专心开车,将以声音和视觉的形式发出警告,例如仪表盘闪烁和发出嘟嘟声。如果驾驶员继续不专心,汽车将自行减速。如果依然无效,汽车将自动靠边停车。另外,还有算法判断驾驶员是否饮酒,如果发现有饮酒迹象,将不允许驾驶。 8、一句话新闻 苹果公司宣布,终止对高通公司的所有诉讼,并向其购买 5G 芯片。随后,Intel 公司宣布放弃 5G 研发,因为它的 5G 芯片的唯一客户就是苹果公司,现在也没了。 全世界74亿人口如果都住在一起,最小需要多少空间?历史上,人口密度最大的地方是香港的九龙城寨,1平方公里住了120万人。据此计算,6000多平方公里就够了,相当于上海市的面积。 爱达荷州的太阳能发电创下美国价格最低记录,每度电2.175美分(相当于人民币0.146元)。该价格是发电厂的价格,居民支付的价格会更高一点。 挪威三月份的新车销售总共18,375辆,其中10,732辆为电动汽车,占比58%。电动车比例是全世界最高。 文章 1、魔兽世界的玩家去世以后(中文) Robert Steen (上图)的儿子患有重病,无法行走,不幸在2014年去世,只有25岁。去世以后,父亲发现儿子的笔记本上有《魔兽世界》的密码,才发现儿子是一个资深玩家,他用这个密码登陆,把死讯告诉儿子在游戏里面的好友,结果,葬礼上,欧洲各国的魔兽玩家都来了。 2、为什么亚马逊河不能架桥?(英文) 亚马逊是世界最长的河流之一,但是整条河没有一座桥,这是为什么? 3、什么是 Wayback Machine?(英文) Wayback Machine 是一个庞大的网页数字档案库,为全世界的网页存档。该项目于1996年启动,目前保存了100亿个快照,数据量达到 30PB,另外还有 30PB 备份。 4、类型正在向右移动(英文) 以前的编程语言,类型声明都是写在变量的左边,比如 int count 。但是,现在越来越多的编程语言,将类型声明写在变量的右边,比如 count:int ,这是为什么? 5、运动追踪的红外线加热器(英文) 作者自己动手,将一个普通的红外线加热器,接上了树莓派,加装了一个摄像头,实时捕捉和识别走动的人体。不管人走到哪里,加热器就会自动转到那个方向,对着人进行加热。 6、我作为工程师的报酬(英文) 一个美国工程师回顾自己的薪水增长,2007年他作为 IT 管理员,年薪是4.2万美元,2018年他变成了架构师,年薪是18.9万美元。许多网友看了他的文章,也纷纷留言,写下自己的年薪变化。 7、10个 Homebrew 软件包(英文) Homebrew 是 Mac 系统的软件包管理器,可用于安装 Unix 软件包。本文推荐10个值得安装的软件包。 8、Java 语言的 null 是一个设计错误(英文) Java 语言的 null 值导致了很多问题,本文解释为什么 Java 的设计是错的,而 Kotlin 的设计是对的。 9、如何安装 Alpine Linux 的桌面(英文) Alpine 是一个极度瘦身的 Linux 发行版,只有 5MB 左右,主要用于制作 Docker 镜像文件。本文介绍 Alpine 的基本知识,如何安装一个基于它的桌面开发环境。 10、未来没有 Webpack 的前端开发(英文) 现在的 Web 应用,一般都需要使用 Webpack 打包脚本。但是,浏览器已经支持 ES6 模块,能够自行处理模块的依赖,因此完全可以跳过打包这个步骤。 11、996.icu 事件的可视化(视频) 这段90秒的视频,帮你回顾 996.icu 事件的全过程。(@jdk137 投稿) 12、Edge 变成 Chromium 意味着什么?(英文) 微软的 Edge 浏览器内核从自研变成了 Chromium,现在 Windows 系统预览版已经发布了。与原来相比,到底新增了哪些功能? 软件 1、ink 使用 React 语法开发富交互的命令行应用的 JS 库。 2、QuickChart 通过 URL 生成图表的开源服务。 3、vuepress-theme-reco VuePress 的一个主题,为博客定制。(@recoluan 投稿) 4、koa-mapper koa-router 模块的替代品。(@helloyou2012 投稿) 5、GitPress 文档的 git 仓库直接发布成静态网站的工具。(@pad0van 投稿) 6、code-server 开源的 VS Code 在线版,支持大部分 VS Code 插件 。(@Y024 投稿) 7、UserLAnd 安卓手机安装 Linux 发行版的 App。 8、ArchiveBox 网页离线储存工具,可以将一个网页的所有资源(HTML、JS、 图片、PDF 等)都下载下来,打包成 Web Archive 格式。 9、instagram.css 一个 CSS 开源库,提供纯 CSS 的 Instagram 滤镜实现。(@ifrontend-xyz 投稿) 10、devices.css 一些主要的电子消费产品外观图片的 CSS 实现。(@ifrontend-xyz 投稿) 11、AutoPiano 自由钢琴,HTML5 技术开发的网页钢琴应用。可以自动演奏曲谱,同步显示琴键的位置。(@WarpPrism 投稿) 12、workbase-server 一个国产的开源企业通信套件,包括私有部署的邮件和聊天解决方案,并提供手机端。可以把它当做自建的 Slack。(@wanglian 投稿) 资源 1、中国哲学古籍电子化计划 免费的线上图书馆,提供中国古籍电子版,已收藏超过3万本著作,约50亿字。(@nosarthur 投稿) 2、Chrome 插件英雄榜 该项目收集优秀的 Chrome 浏览器插件,并为它们写中文说明书。(@zhaoolee 投稿) 3、Ops School 运维工程师的培训资料库,介绍各种运维的基础知识。 4、维米尔全部画作 17世纪荷兰画家维米尔以精确还原生活场景而著称,他一共留下了36幅作品,全部收集在这个网页。 5、好奇者的量子计算入门 英文的开源教程,介绍量子计算的基本概念。同时,网站中包含了上百道简单的练习题,可以帮助初学者检验自己的知识掌握程度。(@nosarthur 投稿) 6、2018年 JavaScript 明星项目 该网站列出2018年各个方向上最受关注的 JavaScript 项目。(@StephenWu5 投稿) 文摘 1、为什么隔着玻璃晒太阳没有用? 人体需要晒太阳,一个主要原因是,阳光里面的紫外线,可以让我们的身体产生维生素 D。这种维生素很难从食物中摄取,必须依靠阳光来合成。 维生素 D 可以促进钙元素的吸收,保证骨骼健康。 所以,长期不见阳光会导致缺乏维生素 D,就会产生骨质疏松,以及其他一些问题。 虽然晒太阳是必要的,但是多晒却不行,多晒太阳会导致皮肤损伤。因为紫外线包含两种,一种是紫外线 A(又称UVA),它们渗透到皮肤深层,可能导致过早老化;另一种是紫外线 B(又称 UVB),导致晒伤发红。研究表明,主要是紫外线里面的 UVB,触发了维生素 D 的合成,而 UVA 并不会产生维生素 D。 一般来说,每天晒十分钟太阳,就能产生足够的维生素 D。但是,在室内或车内晒太阳是没用的,因为玻璃会阻挡 UVB 射线。你无法通过坐在阳光明媚的窗前增加维生素 D 水平,而且玻璃会让大部分 UVA 辐射通过,可能会对你的皮肤造成有害影响。 2、测量地球的年龄 二战后,芝加哥大学的化学家帕特森,希望通过测定岩石里的铅,判断岩石的年代。但是,遇到了一个问题:他找不到无铅环境,到处都有铅污染,因为加铅汽油使得铅在空气无处不在。他试图去除样品中的铅污染,擦洗了玻璃器皿,使用蒸馏水。没有办法,铅仍然出现了。 帕特森从头到尾分析了实验的每一步,以确定铅的起源。当时没人知道,加铅汽油有这么严重的后果。"我发现我使用的所有东西都有铅。这是人们以前从未想过的一种污染。" 玻璃器皿、自来水、实验室墙壁上的油漆、桌子、空气中的灰尘、皮肤、衣服、头发,甚至头皮屑都含铅。如果帕特森希望得到准确的结果,别无选择,他只能成为世界上最洁癖的怪人。 (上图:帕特森竭尽全力将铅和其他污染物排出实验室。) 帕特森竭尽全力摆脱铅。他买了耐热玻璃器皿,洗净,用氢氧化钾热水浸泡,然后用双氧水冲洗。他擦了又擦,跪在地上,擦掉地板上任何铅的痕迹。他用干净材料覆盖了他的工作台面,并在实验室的通风橱里安装了额外的空气泵----甚至在它周围建造了一个塑料笼,以防止空气中的灰尘有铅。他戴着面具和长袍,后来用塑料披着他的身体。 这些措施在当时并不常见。当时还没有"超洁净实验室"实验室的概念。帕特森根本不知道典型的实验室周围漂浮着大约300万个微观粒子,每个粒子都是实验结果的障碍。 五年之后,帕特森终于完善了技术。1951年,他设法准备了一个完全未受污染的铅样品,并确认了一个十亿年前的花岗岩块的年龄,这一成就使他获得了博士学位。下一步是使用这种方法,找出地球的年龄。 帕特森后来去了加州理工学院,建立了世界上最干净的实验室。他拆掉建筑里面的铅管,并重新铺设电线(旧电线有含铅的焊料)。他安装了一个排气系统,用于净化空气,并建造了独立的房间,用于研磨岩石,清洗样品,净化水。地质系通过出售收藏的化石资助了本次大修。 1953年,超净实验室已准备就绪。帕特森着手测试岩石样本,目标是发现地球的年龄。他变得越来越挑剔,要求助手每天用小抹布擦洗地板。后来,他禁止普通服装,要求助手穿着科学连体衣。样本准备好之后,帕特森前往国家实验室使用他们的质谱仪。一天晚上,机器吐出了数字。帕特森独自一人在实验室中将它们代入方程式,得出了地球的年龄是45亿年。 图片 1、BMI 指数 BMI 指数是体重除以身高,用来衡量一个人的肥胖程度。过高的 BMI,几乎必然导致心血管疾病,以及糖尿病等。下图纵轴是身高,横轴是体重,可以用来速查你的 BMI,以及肥胖程度。 2、彩色窨井盖 日本的很多窨井盖都是彩色的,已经成为了一种艺术现象,甚至有专门的民间爱好者交流和收集这些窨井盖。 言论 1、 阿里和腾讯都是膨胀的大平台,将用户聚集在一起,创造一个生态系统。我们听多了创业和快速移动,但是实际上,企业集团正在卷土重来,在政府的支持下成为一个可怕的巨头。这样的互联网公司,正成为当今时代和未来的主导。 -- HN 读者评论 2、 我的工位几乎看不到外面,我觉得这座建筑物真的开始吃掉我整天盯着墙壁的灵魂。 -- HN 读者留言 3、 赚钱的商业方式只有两种,一种是捆绑(bundle),另一种是分解(unbundle)。 -- 马克·安德森,Netscape 浏览器创始人 4、 你想尽办法让孩子上贵族学校,他会骑马,会演莎士比亚剧,但就是不了解普通人的想法,那你确信他会过好这一生吗? -- 逻辑思维 5、 一般来说,帮企业赚钱的系统好卖,帮企业省钱的不好卖,因为省钱的系统基本上都要动到既得利益者。 -- 子柳 订阅 这个专栏每周五发布,同步更新在我的个人网站、微信公众号和语雀。 微信搜索"阮一峰的网络日志"或者扫描二维码,即可订阅。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年4月19日


Go 语言中的 make 和 new

2019-04-18 01:02:00 Draveness

当我们想要在 Go 语言中初始化一个结构时,其实会使用到两个完全不同的关键字,也就是 make 和 new,同时出现两个用于『初始化』的关键字对于初学者来说可能会感到非常困惑,不过它们两者有着却完全不同的作用。


“努力就会成功”

2019-04-17 01:12:27 陈皓

那一年,我加入了某知名公司的某知名部门,在办公室中,我看到了到处都挂着——“努力就会成功”的条幅,这个部门中大多数员工的邮件签名都会有“努力就会成功”,我感到一... Read More Read More

tags: 技术管理,杂项资源,Programmer,程序员


为什么我们需要use_cases

2019-04-17 00:00:00 黄药师

我一直以为,在写rails的时候使用use_case是一种很常见的意识。但是我发现还是有一部分人从来没用过或者没听说过use_case,出于让自己也更仔细的思考这种用法的目的,记录一下。 事情的起因是因为一次code review, 我很庆幸我们团队内部的code review做的一直都不错,大家都很认真的给彼此的代码做认真的检查,并且都能从中学到很多东西。 我封装了一个use_case,并且在model的callback里面去调用了这个use_case。这个做法遭到了给我做code review同事的质疑,然后我才知道原来还有部分道友还不知道use_case的用法。 当然我也并不是说我这样的做法就是最好的,但是这种既不属于model,也很难成为一个公用lib class的,并且单一职责,逻辑简单的玩意儿,随着项目的成长随时可能改变的东西,封装为一个use_case绝对是一个不错的选择。 试想我们有一个表单,需要给用户发验证码,并且在用户输入验证码以后比对验证码,才能允许用户正常提交。假设这个方法叫做send_code,我们创建一个发验证码的module叫做Postman。 我们的发验证码的controller长这样: class AuthController < ApplicationController def create auth_code = AuthCode.create(sms_params) if svc.success? render json: { sid: auth_code.sid } else render json: { status: 500 }, status: 500 end end private def sms_params params.require(:verification).permit(:phone_number, :code) end end model长这样: class AuthCode < ActiveRecord::Base before_create :generate_code after_create :send_code def send_code Postman.new(phone_number, verify_code).perform end private def generate_code self.verify_code = rand.to_s[2..5].to_s end end 这样我的controller只用关心验证码的创建就好,发不发/怎么发都是model的事儿,AuthCode记录创建好以后会通过callback去发送,这里的Postman就是我们前面提到的一个use_case: class Postman include UseCase def initialize(phone_number, message) @phone_number = phone_number @message = message end def perform SMS::Client.new.messages.create( to: @phone_number, body: @message ) end end 而UseCase可以理解为一个接口定义,描述了所有use_case都需要遵循的规则,便于维护和自描述: module UseCase extend ActiveSupport::Concern include ActiveModel::Validations # extented class should contains these methods module ClassMethods # The perform method of a UseCase should always return itself def perform(*args) new(*args).tap(&:perform) end end # implement all the steps required to complete this use case def perform raise NotImplementedError end # inside of perform, add errors if the use case did not succeed def success? errors.none? end end 这里有几点需要注意的: 每个use_case只有一个public的实例方法 (perform) 每个use_case只有一个职责,也就是只做一件事(发短信) 因为上一条,所以测试也很容易写 有一个Gem叫做caze可以让use_case的调用更优雅一些,不必像我这样显式的调用: Postman.new(phone_number, verify_code).perform 具体可以看看caze的文档。 顺便发一下代码的结构: ├── app │   ├── controllers │   │   ├── application_controller.rb │   │   ├── auth_controller.rb │   │   └── users │   ├── models │   │   ├── user.rb │   │   └── auth_code.rb │   ├── use_cases │   │   ├── postman.rb │   │   └── use_case.rb 这样一来,我们就: 把程序有什么 models 比如user, auth_code 等等不怎么变化很稳定的东西。 和程序做什么 业务逻辑 和 use cases 会随着项目的成长不停改变。 分开了。 那问题来了, 我们什么时候需要 use_case 呢? 当你需要管理resources,你就必须用rails的方式,也就是面向resource的方式去做,model啦,presenter啦,抽象类啦,都是很方便且有道理的。 但是,当你的业务里面有一个很特殊的功能,它不属于你的主营业务逻辑,且职责单一,随时可以变化甚至移除,那么你就可以考虑使用use_case,就像上面的代码那样。 总结 一万个程序员眼里有一万种最佳实践,use_case不是所有的场景都适用。但是当你有这样的思维以后,对于如何组织你的use_case,如何保持代码结构整洁肯定是有一定帮助的。 Referreces Architecture the Lost Years by Robert Martin Clean architecture on rails by Fabiano Beselga caze gem use case examples

tags: Notes,use case,rails,ruby,cleancode


如何将一个开源项目加入CNCF?

2019-04-15 11:37:02 宋净超

前段时间看了一篇文章为什么中国没有 Apache 基金会这样的组织?,二叉树视频中采访了开源社的理事长老刘,他的一番话也让我很受启发,在关注和参与 CNCF 基金会


如何用网页脚本追踪用户

2019-04-15 00:16:40 阮一峰

本文介绍如何编写 JavaScript 脚本,将用户数据发回服务器。 我做了一个代码仓库,包含了下面所有的例子,可以运行查看效果。 一、同步 AJAX 数据发回服务器的常见做法是,将收集好的用户数据,放在unload事件里面,用 AJAX 请求发回服务器。 但是,异步 AJAX 在unload事件里面不一定能成功,因为网页已经处于卸载中,浏览器可能发送,也可能不发送。所以,要改成同步 AJAX 请求。 window.addEventListener('unload', function (event) { let xhr = new XMLHttpRequest(); xhr.open('post', '/log', false); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('foo=bar'); }); 上面代码中,xhr.open()方法的第三个参数是false,表示同步请求。 这种方法最大的问题在于,浏览器逐步将不允许在主线程上面,使用同步 AJAX。所以,上面代码实际上不能用。 二、异步 AJAX 异步 AJAX 其实是能用的。前提是unload事件里面,必须有一些很耗时的同步操作。这样就能留出足够的时间,保证异步 AJAX 能够发送成功。 function log() { let xhr = new XMLHttpRequest(); xhr.open('post', '/log', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('foo=bar'); } window.addEventListener('unload', function(event) { log(); // a time-consuming operation for (let i = 1; i 上面代码中,强制执行了一次双重循环,拖长了unload事件的执行时间,导致异步 AJAX 能够发送成功。 三、追踪用户点击 setTimeout也能拖延页面卸载,保证异步请求发送成功。下面是一个例子,追踪用户点击。 // HTML 代码如下 // click const clickTime = 350; const theLink = document.getElementById('target'); function log() { let xhr = new XMLHttpRequest(); xhr.open('post', '/log', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('foo=bar'); } theLink.addEventListener('click', function (event) { event.preventDefault(); log(); setTimeout(function () { window.location.href = theLink.getAttribute('href'); }, clickTime); }); 上面代码使用setTimeout,拖延了350毫秒,才让页面跳转,因此使得异步 AJAX 有时间发出。 四、反弹追踪 追踪用户点击,还可以使用反弹追踪(bounce tracking)。 所谓"反弹追踪",就是网页跳转时,先跳到一个或多个中间网址,以便收集信息,然后再跳转到原来的目标网址。 // HTML 代码如下 // click const theLink = document.getElementById('target'); theLink.addEventListener('click', function (event) { event.preventDefault(); window.location.href = '/jump?url=' + encodeURIComponent(theLink.getAttribute('href')); }); 上面代码中,用户点击的时候,会强制跳到一个中间网址,将信息携带过去,处理完毕以后,再跳到原始的目标网址。 谷歌和百度现在都是这样做,点击搜索结果时,会反弹多次,才跳到目标网址。 五、Beacon API 上面这些做法,都会延缓网页卸载,严重影响用户体验。 为了解决网页卸载时,异步请求无法成功的问题,浏览器特别实现了一个 Beacon API,允许异步请求脱离当前主线程,放到浏览器进程里面发出,这样可以保证一定能发出。 window.addEventListener('unload', function (event) { navigator.sendBeacon('/log', 'foo=bar'); }); 上面代码中,navigator.sendBeacon()方法可以保证,异步请求一定会发出。第一个参数是请求的网址,第二个参数是发送的数据。 注意,Beacon API 发出的是 POST 请求。 六、ping 属性 HTML 的标签有一个ping属性,只要用户点击,就会向该属性指定的网址,发出一个 POST 请求。 click 上面代码中,用户点击跳转时,会向/log这个网址发一个 POST 请求。 ping属性无法指定数据体,似乎只能通过 URL 的查询字符串携带信息。 七、参考链接 Link Click Analytics and Privacy, John Wilander ping Attribute, David Walsh (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年4月15日


谈谈 panic 和 recover 的原理

2019-04-13 03:40:00 Draveness

这一节中我们将介绍 Go 语言中两个经常成对出现的关键字 panic 和 recover 的实现原理,我们在上一节关注的 defer 与这里介绍的两个关键字其实也有着比较大的关系,我们会在剩下的部分展开介绍相关的内容,没有阅读 上一节 的读者还是需要补充一下相关知识,这样才能更好地了解 panic 和 recover 关键字的原理。


每周分享第 51 期

2019-04-12 02:33:27 阮一峰

这里记录过去一周,我看到的值得分享的东西,每周五发布。 欢迎投稿,或推荐你自己的项目,请前往 GitHub 的 ruanyf/weekly 提交 issue。 一个程序员的 Macbook 送修了,他只好重新使用10年前的笔记本电脑(上图)。结果意外地发现,虽然有点慢,但是不影响使用。10年前的电脑依然能够满足日常工作。 如果2009年的时候,让你去使用1999年的电脑,那是不可想象的,根本没有实用性。但是,2019年的时候,去使用2009年的电脑,却是完全可行的。 这说明,过去十年的硬件进展不太大,导致10年前的硬件不是那么过时。过去十年,进展主要体现在软件上面:软件功能更强大、使用更友好、界面更美观。 经济有一个定理,叫做"边际收益递减",意思是,发展到比较成熟的阶段以后,以后每一步的进展会越来越小。硬件就是如此,摩尔定理到了尽头以后,就已经开始慢下来了。我估计,硬件之后就是软件,随着软件开发技术的成熟,以后软件的进展也会放缓,总有一天,我们使用十年以前的软件,也会觉得还可以接受,当然现在还没到这一步。 软件之后的发展重点,我认为将是算法和数据,以后的进步更多会体现在算法优化和数据训练上面。 新闻 1、程序员的专用座椅 美国一家创业公司推出了程序员专用座椅,可以躺着使用三块屏幕,还有按摩功能,可以一边敲代码,一边按摩。由于这个椅子可以140度斜躺,还有脚凳和椅灯,所以也可以在上面睡觉。它的售价是3600美元。 2、世界上最短的高速公路 世界最短的高速公路就在罗马尼亚,长度为1米。当地的一个快餐店老板自费4500欧元,建造了这条1米的四车道高速公路。他是为了抗议政府忽视公路建设,"他们说这个地区不适合建设高速公路,我就造1米给他们看看。"罗马尼亚的面积与英国相当,但是高速公路只有806公里,大约是英国五分之一。 3、海上隔离 美国海军军舰麦克亨利号(US McHenry)在波斯湾执行任务时,全舰700多名官兵中有25人感染了腮腺炎。结果,全舰就被隔离在海上,整整两个月不得靠岸,所有人都没法下船,补给由其他船只运送过来。看上去,以后对于那些高传染性的疾病,海上隔离似乎是一个可行的方案。 4、发光滑雪板 美国一家公司推出了会发光的滑雪板,售价500美元。不过,该公司没说,这是白天用的,还是夜晚用的。如果是夜晚使用,是为了观众能看清楚滑雪的轨迹吗? 5、刷脸乘地铁 3月8日,深圳地铁公司在福田站,开通了"刷脸乘地铁"的测试通道。乘客可以先在地铁公司登记,然后进站时,不需任何动作,只需将脸正对一个平板电脑的摄像头,就能刷脸扣款。目前还不知道,该服务何时会在深圳地铁的其他站点使用。 6、柔软的机器手 机器手臂通常都是钢铁材质,牢牢抓取物体的时候,很容易造成物体损伤。为了解决这个问题,麻省理工学院的科学家发明了柔软的机器手。它是一个橡胶做的套子,可以像花朵一样打开和关闭。 当它套住物体的时候,会泵出里面的气体,通过气密性,使得大气压将套子牢牢压在物体上面,从而能够在不损伤物体的情况下,拾取精细的物品。它能够抓起自身重量100倍的物体。 7、雨伞发电 台湾和美国的科学家研发出一种可以发电的雨伞。这种雨伞利用雨和风与伞面产生的摩擦电能,进行发电。伞和雨衣上的纳米发电机可以收集水滴的冲击能量,将其转化为电能。 这种面料可用于开发自供电的照明雨具,以帮助防止雨天发生交通事故。在125毫升/秒的降雨量下,纳米发电机在5分钟内将 1μF 电容充电至 9V 左右。重复洗涤也不会降低这种面料的性能。 8、环卫工人的手环 有消息称,南京市河西区的环卫工人被要求佩戴 GPS 跟踪智能手环,这会随时监控他们的位置,而且如果他们停止移动超过20分钟,手环就会发出提醒"请继续工作"。 报道披露后,公众压力使得当地环卫公司决定稍微让步,现在如果环卫工人留在一个地方,手环不再发出提醒"请继续工作",但仍然会跟踪工人的移动。 9、787 飞机的 GPS 授时错误 GPS 卫星发送的信息包含时间字段,其中表示"周数"的字段只有10个二进制位,导致该字段每20年会发生一次溢出,自动归零。2019年4月6日,该字段就发生了本世纪第一次溢出。 所有依赖 GPS 授时的设备,都可能因此发生计时错误。波音公司的喷气式飞机就是这样,现在已经出现多架 787 客机的系统时间回到了20年前的1999年(上图红框处)。 10、一句话新闻 华纳音乐签约了一个音乐算法,将发行该算法生成的五张唱片。它主要生成轻音乐,供睡前播放,itunes 上面有试听。 IBM 公司在过去6年中,已经解雇了超过2万名40岁以上的美国员工。报道称,该公司有内部政策,更严厉地评估长期服务的员工,使用负面评估对他们进行裁员。 人的大脑保存的信息,研究认为,以英语表示的话大约是 1.5MB。 英国和加拿大决定,不再新建任何燃煤电厂,现有的燃煤电厂也将逐步放弃。因为燃煤会产生大量二氧化碳。 文章 1、刘慈欣:释放想象力(中英对照) 2018年11月,刘慈欣在克拉克想象力服务社会奖颁奖仪式上的演说。 2、Java 开发者需要知道的20个库(英文) 本文介绍 Java 语言20个常用的库,比如 log4j、JUnit、JSoup 等。 3、与死亡一线之隔的完美(中文) Free Solo 是一部《国家地理》杂志拍摄的纪录片,讲述了徒手独攀优胜美地國家公園內、全世界最難攀爬的酋长岩的故事。它得到了 2019奧斯卡最佳紀錄片獎。本文讲述了这部纪录片背后的故事,为什么有人愿意冒着生命危险去攀岩,他又是怎么爬上去的。 4、再见 Docker(英文) 作者认为,Docker 作为一家公司已经失败,作为一种技术,也即将被其他容器技术取代。 5、关于 EOF(英文) EOF 是一个很容易混淆的概念。Windows 系统的文本文件,结尾可以有 EOF 终止符;C / C++ 语言有一个表示读取终止的特殊值 EOF,还有测试读取是否终止的 eof() 和 feof() 函数。 6、使用 AV1 编解码器(英文) AV1 是一个新的开源的视频编码和解码标准,本文介绍 AV1 的基本知识,以及如何把视频压缩成 av1 格式。 7、无 JavaScript 的前端(英文) 作者呼吁 HTML 语言内置更多的功能,从而使得只用 HTML 就可以写出可交互的页面,减少 JavaScript 的使用。 8、线程的基本知识(英文) 一篇写得非常好的科普文章,通俗地详尽解释了进程和线程的相关知识。 9、如何使用 React Hooks 获取数据?(英文) 本文由浅入深一步步介绍,如何使用 React Hooks 的 useEffect 从远程服务器获取数据。 10、浏览器内置的 KV Storage(英文) 浏览器提供的键值对存储 localStorage API 是同步操作,有时候很慢。为了解决这个问题,Chrome 浏览器开始提供异步键值对存储的 API。 11、浏览器原生的图片懒加载(英文) Chrome 75 将原生支持图片的懒加载,写成 ,就可以滚动到视口加载图片。 软件 1、node-five 一个基于 QT 的 Nodejs 框架,用于开发 Node 应用的图形界面。 2、Learn anything 一个学习资源的搜索引擎,可以搜索各种主题,返回相应的教程。(@Paleless 投稿) 3、Gckit-CLI 命令行下使用一行命令,生成Swift、Objective-C等项目的模板代码。(@SeongBrave 投稿) 4、php-lisp 一个使用 PHP 写的 Lisp 代码解释器。(@wujunze 投稿) 5、Paste to Markdown 粘贴到该窗口的任何文本内容,都会自动转为 Markdown 格式。(@AidySun 投稿) 6、RCT 一个通过解析 rdb 文件对 redis 内存结构分析的一站式平台。(@TrumanDu 投稿) 7、squoosh 谷歌开源的图像压缩服务。(@ifrontend-xyz 投稿) 8、Whoer.net 查看你的 HTTP 请求携带多少个人信息的网站。(@xcuYao 投稿) 9、chunkwm Mac 电脑的多窗口平铺式管理器。 10、StreamSaver.js 流媒体保存成本地文件的浏览器库。(@ifrontend-xyz 投稿) 11、你的电脑有多快? 一个小游戏,提供一系列常见任务的 Python 脚本,让你猜计算机在1秒内可以执行多少次。(@NeoTse 投稿) 12、morec 一个 Flutter 制作的电影 App,用于学习 Flutter。(@Mayandev 投稿) 资源 1、Generative.fm 该网站专门收集软件生成的音乐。比较奇特的是,这些音乐可以无限播放,并且每次听都不一样。暂停以后重新播放,你会听到跟前面不同的音乐。 2、Star Wars Asciimation ASCII 码的形式演绎整部《星球大战》,可以使用 telnet towel.blinkenlights.nl 在命令行观看,也可以在网页观看。(@linkoln 投稿) 3、Test-Driven Web Development with Python 免费的英文电子书,介绍如何以 TDD 的方式开发互联网应用,使用 Django 框架举例。(@nosarthur 投稿) 4、算法 开源英文电子书,作者是美国伊利诺伊大学的教师,本书是他的讲课笔记,偏重于数学。(@nosarthur 投稿) 5、Killed by Google 该网站收集谷歌关闭的所有自家产品。(@murongsihua 投稿) 6、航班实时追踪 国内做的全球航班实时位置展示,国内航班的覆盖是全球最好的。(@cq0206 投稿) 文摘 1、为什么我放弃 Amazon 年薪50万美元的工作? 上周,我辞掉了8年的亚马逊工作。尽管一再得到奖励和表彰,但我没有足够的动力再干一年。 当年,加入亚马逊时,我是初级工程师。5年内,我晋升了两次,现在是高级工程师。如果我留下来,几乎可以肯定今年会再次晋升,成为首席工程师。我被告知,我在公司有很大的潜力。公司里,人们对我的尊重不断增长,我被视为所在领域的专家和领导者。 我在亚马逊的第一年赚了75,000美元。去年,我赚了511,000美元。如果再呆几年,我的年薪应该可以到100万美元。 我的工作不算很忙,也不再需要证明自己。我可以在一周40小时内完成所有工作,而且我的团队每周一天在家工作。晚上或周末,我很少打开笔记本电脑。我总共有三位主管,他们人都很好,有很多同理心。 尽管一切都很好,但每天早上,我上班的动机都在减少。 最初的几年,我主要与另一个同事,一起开发一个内部工具。各种限制很少,我有很大的独立性,直接与用户交谈,然后发布更新,开展测试等等。只要我觉得这件事是重要的,通常就可以去做。大多数时候,工作的方向是我们自己控制的。 后面的几年却完全不同。我领导着部门历史上最重要的项目,有许多利益相关者和复杂的目标。我能做的事情受到了很大的限制,通常取决于我能否说服所有相关人员,而我想做的是实现目标的最佳方式,却不一定能做。 我在公司总是处理其他人的要求或条件,开始时很简单,但随着时间的流逝而变得越来越复杂,因为必须满足所有利益相关者。这种情况迫使我做一些不愿意做的事情,或者我愿意做的事情没法做。 2、善于销售 成功需要自信,但是仅有自信是不够的,你还必须能够让别人相信你的主张。 某种程度上,所有伟大的职业都包含销售工作。您必须向客户、员工、媒体、投资者宣传你的计划。这需要鼓舞人心的愿景,强大的沟通技巧,魅力,以及执行能力的证据。 善于沟通,特别是善于书面沟通,是值得培养的一种能力。如果要达到明确沟通,我的建议是,首先要确保你的思路清晰,然后使用简洁明了的语言,表达出你的想法。 销售的最佳方式是真正相信你所销售的产品。卖你真正相信的东西感觉很棒,试图卖自己都不相信的产品,感觉很糟糕。 我的另一个销售建议是,重要的时候,你最好亲自出现。我刚开始做销售的时候,我总是愿意上飞机,自己去一趟。这通常是不必要的,打电话也可以解决。但其中有三次导致了我的职业生涯转折点,如果我不是亲自去,我的人生本来会走另一条路。 3、Youtube 的热门频道统计 Youtube 有2000多万个活跃频道,2018年底,359个频道有超过1000万个订阅者。其中,87个频道是2018年创建的,在一年内就达到了1000万订阅,相比2017年的47个频道增长了185%。 这87个频道平均需要167天才能达到1000万订户。其中,最快的是墨西哥的 Kenia OS 只用了5天,其次是另一个墨西哥频道 Juki Dog,花了20天。这87个频道的国籍分布是,14个墨西哥频道,12个美国频道,11个印度频道,5个土耳其,4个印度尼西亚频道。 娱乐类频道(电影和娱乐,音乐)是增长最快的频道,其次是生活频道和游戏频道。烹饪、健康、体育类频道也有快速增长。 根据统计,这些热门频道在周五和周六上传了更多视频,这两天发布的视频在观看和订阅方面,要比其他时间更高。 图片 1、打印 DNA 有人把 DNA 上面23亿个碱基对,用打孔机打印出来。打印了一个星期,还不到 DNA 的5%。 2、带名字的手术帽 动手术的时候,医生戴着口罩,穿着手术服和帽子,很难分清谁是谁。一位澳大利亚医生正在互联网上,发起一场运动,倡议医生在帽子上标识自己的名字。 3、各语言的域名分布 截止2019年2月,互联网上共有93,482,546个有内容的域名,其中68%是英文站点,12%是中文站点,3%是西班牙语站点。 言论 1、 随着在线服务的激增,每个用户2007年大约有25个密码,2015年增加到130个,预计到2020年将增长到207个。 -- 《密码管理器研究》 2、 每家公司都说:"我们非常重视您的隐私和安全。"请不要再说这种话了,大多数公司并不关心数据的隐私或安全,而是为了数据被盗时,他们有一个向客户解释的说辞。 -- 《别说"我们严肃对待你的隐私和安全"》 3、 最好的故事是不完美的。当一个故事有点奇怪时,它会吸引你,人们会谈论那些没有按照预期发展的事情。那些出乎意料的东西会让你念念不忘。 -- 《马尔科姆·格拉德威尔的写作课》 4、 思考某事和讲述某事是不同的事情。我们思考事物的方式很复杂,有时甚至是不连贯的,而且经常是矛盾的。但是讲述时,我们必须把某事表达得很清晰,可以在很短的时间内说得出来。 -- 《马尔科姆·格拉德威尔的写作课》 5、 过去七年,谷歌平均每周收购两家公司。 -- Patrick Pichette,谷歌前首席财务官 6、 技术正在发展一定程度的自治,它好像正在以某种方式利用人类来创造它自己。 -- Paul Kingsnorth 订阅 这个专栏每周五发布,同步更新在我的个人网站、微信公众号和语雀。 微信搜索"阮一峰的网络日志"或者扫描二维码,即可订阅。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年4月12日


OAuth 2.0 的四种方式

2019-04-09 02:47:31 阮一峰

上一篇文章介绍了 OAuth 2.0 是一种授权机制,主要用来颁发令牌(token)。本文接着介绍颁发令牌的实务操作。 下面我假定,你已经理解了 OAuth 2.0 的含义和设计思想,否则请先阅读这个系列的上一篇文章。 进入正文之前,插播一则活动消息。 本周一(4月8日)到周日(4月14日),每天晚上八点都有两小时的免费直播课,体系化介绍高级前端开发知识,网易云课堂主办。详细介绍请看本文结尾,欢迎关注。 RFC 6749 OAuth 2.0 的标准是 RFC 6749 文件。该文件先解释了 OAuth 是什么。 OAuth 引入了一个授权层,用来分离两种不同的角色:客户端和资源所有者。......资源所有者同意以后,资源服务器可以向客户端颁发令牌。客户端通过令牌,去请求数据。 这段话的意思就是,OAuth 的核心就是向第三方应用颁发令牌。然后,RFC 6749 接着写道: (由于互联网有多种场景,)本标准定义了获得令牌的四种授权方式(authorization grant )。 也就是说,OAuth 2.0 规定了四种获得令牌的流程。你可以选择最适合自己的那一种,向第三方应用颁发令牌。下面就是这四种授权方式。 授权码(authorization-code) 隐藏式(implicit) 密码式(password): 客户端凭证(client credentials) 注意,不管哪一种授权方式,第三方应用申请令牌之前,都必须先到系统备案,说明自己的身份,然后会拿到两个身份识别码:客户端 ID(client ID)和客户端密钥(client secret)。这是为了防止令牌被滥用,没有备案过的第三方应用,是不会拿到令牌的。 第一种授权方式:授权码 授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。 这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。 第一步,A 网站提供一个链接,用户点击后就会跳转到 B 网站,授权用户数据给 A 网站使用。下面就是 A 网站跳转 B 网站的一个示意链接。 https://b.com/oauth/authorize? response_type=code& client_id=CLIENT_ID& redirect_uri=CALLBACK_URL& scope=read 上面 URL 中,response_type参数表示要求返回授权码(code),client_id参数让 B 知道是谁在请求,redirect_uri参数是 B 接受或拒绝请求后的跳转网址,scope参数表示要求的授权范围(这里是只读)。 第二步,用户跳转后,B 网站会要求用户登录,然后询问是否同意给予 A 网站授权。用户表示同意,这时 B 网站就会跳回redirect_uri参数指定的网址。跳转时,会传回一个授权码,就像下面这样。 https://a.com/callback?code=AUTHORIZATION_CODE 上面 URL 中,code参数就是授权码。 第三步,A 网站拿到授权码以后,就可以在后端,向 B 网站请求令牌。 https://b.com/oauth/token? client_id=CLIENT_ID& client_secret=CLIENT_SECRET& grant_type=authorization_code& code=AUTHORIZATION_CODE& redirect_uri=CALLBACK_URL 上面 URL 中,client_id参数和client_secret参数用来让 B 确认 A 的身份(client_secret参数是保密的,因此只能在后端发请求),grant_type参数的值是AUTHORIZATION_CODE,表示采用的授权方式是授权码,code参数是上一步拿到的授权码,redirect_uri参数是令牌颁发后的回调网址。 第四步,B 网站收到请求以后,就会颁发令牌。具体做法是向redirect_uri指定的网址,发送一段 JSON 数据。 { "access_token":"ACCESS_TOKEN", "token_type":"bearer", "expires_in":2592000, "refresh_token":"REFRESH_TOKEN", "scope":"read", "uid":100101, "info":{...} } 上面 JSON 数据中,access_token字段就是令牌,A 网站在后端拿到了。 第二种方式:隐藏式 有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。 第一步,A 网站提供一个链接,要求用户跳转到 B 网站,授权用户数据给 A 网站使用。 https://b.com/oauth/authorize? response_type=token& client_id=CLIENT_ID& redirect_uri=CALLBACK_URL& scope=read 上面 URL 中,response_type参数为token,表示要求直接返回令牌。 第二步,用户跳转到 B 网站,登录后同意给予 A 网站授权。这时,B 网站就会跳回redirect_uri参数指定的跳转网址,并且把令牌作为 URL 参数,传给 A 网站。 https://a.com/callback?token=ACCESS_TOKEN 上面 URL 中,token参数就是令牌。A 网站因此直接在前端拿到令牌。 这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。 第三种方式:密码式 如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。 第一步,A 网站要求用户提供 B 网站的用户名和密码。拿到以后,A 就直接向 B 请求令牌。 https://oauth.b.com/token? grant_type=password& username=USERNAME& password=PASSWORD& client_id=CLIENT_ID 上面 URL 中,grant_type参数是授权方式,这里的password表示"密码式",username和password是 B 的用户名和密码。 第二步,B 网站验证身份通过后,直接给出令牌。注意,这时不需要跳转,而是把令牌放在 JSON 数据里面,作为 HTTP 回应,A 因此拿到令牌。 这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。 第四种方式:凭证式 最后一种方式是凭证式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌。 第一步,A 应用在命令行向 B 发出请求。 https://oauth.b.com/token? grant_type=client_credentials& client_id=CLIENT_ID& client_secret=CLIENT_SECRET 上面 URL 中,grant_type参数等于client_credentials表示采用凭证式,client_id和client_secret用来让 B 确认 A 的身份。 第二步,B 网站验证通过以后,直接返回令牌。 这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。 令牌的使用 A 网站拿到令牌以后,就可以向 B 网站的 API 请求数据了。 此时,每个发到 API 的请求,都必须带有令牌。具体做法是在请求的头信息,加上一个Authorization字段,令牌就放在这个字段里面。 curl -H "Authorization: Bearer ACCESS_TOKEN" \ "https://api.b.com" 上面命令中,ACCESS_TOKEN就是拿到的令牌。 更新令牌 令牌的有效期到了,如果让用户重新走一遍上面的流程,再申请一个新的令牌,很可能体验不好,而且也没有必要。OAuth 2.0 允许用户自动更新令牌。 具体方法是,B 网站颁发令牌的时候,一次性颁发两个令牌,一个用于获取数据,另一个用于获取新的令牌(refresh token 字段)。令牌到期前,用户使用 refresh token 发一个请求,去更新令牌。 https://b.com/oauth/token? grant_type=refresh_token& client_id=CLIENT_ID& client_secret=CLIENT_SECRET& refresh_token=REFRESH_TOKEN 上面 URL 中,grant_type参数为refresh_token表示要求更新令牌,client_id参数和client_secret参数用于确认身份,refresh_token参数就是用于更新令牌的令牌。 B 网站验证通过以后,就会颁发新的令牌。 写到这里,颁发令牌的四种方式就介绍完了。下一篇文章会编写一个真实的 Demo,演示如何通过 OAuth 2.0 向 GitHub 的 API 申请令牌,然后再用令牌获取数据。 (正文完) 前端高级开发工程师免费直播课 经过多年的发展,前端工程师的地位日益提升,越来越多的人想往前端的方向发展。 但是,市场对前端工程师的要求也越来越高,深入掌握底层技术的高级前端,才能在市场上找到自己立足之地。 为了帮助大家深入了解高级前端的学习要点,本周一(4月8日)到周日(4月14日),网易云课堂推出了前端进阶免费直播课。 (更多介绍点击这里) 他们邀请了网易资深前端工程师,免费直播分享实战中的经验方法。内容涉及网易内部自定组件库工具分享,前端开发相关知识,深度剖析 JavaScript 等。 这个直播面向前端初、中级开发工程师,每天2个小时,都是一些干货分享并且不收费,建议想进阶的同学坚持学习。大家可以微信扫码,添加助教,获取听课地址。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年4月 9日


理解 Go 语言 defer 关键字的原理

2019-04-07 15:25:00 Draveness

现在很多现代的编程语言中其实都有用于在作用域结束之后执行函数的关键字,Go 语言中的 defer 就可以用来实现这一功能,它的主要作用就是在当前函数或者方法返回之前调用一些用于收尾的函数,例如关闭文件描述符、关闭数据库连接以及解锁资源。


基于Kubernetes 构建.NET Core 的技术体系

2019-04-07 05:24:16 李强

很多公司技术支持岗位的工作,如配置域名,部署环境,修改复位配置,服务重启,扩容缩容,梳理和完善监控,根据开发的需要查找日志等工作,需要和开发进行大量的沟通,如什么是外网域名,什么是内网域名、A name、C name,防火墙规则该如何设定,操作系统等基础环境需要什么依赖。因为很多研发不了解运维的术语和知识点,导致沟通困难,效率很低。

tags: 容器和Docker


每周分享第 50 期

2019-04-05 02:57:42 阮一峰

这里记录过去一周,我看到的值得分享的东西,每周五发布。 欢迎投稿,或推荐你自己的项目,请前往 GitHub 的 ruanyf/weekly 提交 issue。 (题图:杭州,2018) 前几天,我听一个广播节目。主持人问,现在很多人开网约车,这样能赚多少钱,能够赚到大钱吗? 这个问题很容易回答,答案就是不能。出租车司机的收入,主要由营业时间的长短决定。基本上,一天开12个小时,就是比开6个小时,收入高出一倍。每天只有24个小时,因此收入存在上限,不可能偏离平均水平很远。 出租车是"时间换收入"的典型行业,投入的时间越多,收入越高,在家休息就没收入。很多行业都属于"时间换收入",所有此类行业都赚不到大钱。因为你能用来交换的时间是有限的,而且进入中年以后,你就拿不出更多的时间来交换。开出租车赚零花钱,或者作为短期过渡,这是没问题的,但作为终身职业是很糟糕的。 我觉得,越来越多的程序员正在落入这个陷井,用编码的时间换取收入。只有不停地做项目,才能拿到钱。项目做得越多,收入越高。这个项目开发完了,公司又让他去干下一个项目。 忙了好几年,项目完成了一大堆,但是自己什么也没留下,以后的收入还要取决于从零开始的新项目。这样的话,你跟出租车司机有何两样,哪一天你不写代码了,不是照样没收入。 那些赚到大钱的人,没有一个是靠时间换取收入的。他们要么通过积累资产致富,要么购买他人的时间,为自己创造财富。你应该警惕,不要落入"时间换取收入"的陷井,不要只顾着为别人生产代码,而要注意积累自己的资产,以及适时开展属于自己的业务。 新闻 1、银行模仿科技公司 银行通常给人一种严肃保守的感觉。丹麦一家银行决定改变这种印象,向科技公司学习,让银行也变得轻松随便。它重新装修了办公楼,允许员工穿便服,还采用了开放式办公室。 2、霍金教授的纪念硬币 英国皇家造币厂为了纪念去年去世的霍金教授,推出了一枚纪念硬币,面值为50便士。这枚硬币中间有一个洞,象征霍金对黑洞的研究成果。 3、删除 Facebook WhatsApp 于2014年以193亿美元的价格,被 Facebook 收购。但是,2019年3月13日,WhatsApp的联合创始人布莱恩·阿克顿(Brian Acton,上图最右边)在斯坦福大学的一个讲座上,公开呼吁学生删除 Facebook。 他解释说,收购完全是资本的需要,他本人是无可奈何。"我有50名员工,我不得不考虑他们,以及他们从这笔交易中赚到的钱。我不得不考虑我们的投资者,我不得不考虑我的少数股权。即使我想拒绝收购,我也没有完全的影响力来否决。" 4、月球岩石 1969年到1972年,阿波罗计划的宇航员多次登录月球,一共采集了382公斤月球岩石,其中大部分都公开了,但是有三个样本一直是保密的。今年是人类登陆月球50周年,美国宇航局决定将所有样本都公开。 科学家已经决定,采用最先进的手段,彻底检查这些样本。因为月球被发现存在固态水,这些岩石中可能有氧化物,科学家想知道有无可能从月球岩石提取氧气。 5、圆周率的最新记录 3月14日是国际圆周率日,谷歌宣布,日本的谷歌员工 Emma Haruka Iwao 打破了世界记录,将圆周率计算到了31万亿位数,远远超过之前的22万亿记录。整个计算使用虚拟机,花了121天才完成。这个新的圆周率保存在硬盘上,需要 170TB 的空间。 6、VR 电影 今年的美国 SXSW 艺术节,推出了 VR 电影体验。观众一人一套设备,每套设备都有很长的电线,以便观看时可以适度的移动。这次展映了20多部 VR 电影,每部长度都在10分钟~15分钟。不同的电影有不同的观看设备,上图是坐在轮椅上观看,观众表示体验还不错。 VR 电影的优势是沉浸式体验,可以360度观看。下面的这部电影讲述第一次世界大战时,一个英国士兵的经历。他走进一所老宅,然后是战地医院,最后在战地营房里,到处是他无法寄出去的明信片。 另一部 VR 电影则是观看一对夫妻的故事。 7、苹果取消 AirPower 苹果公司宣布,取消 AirPower 这个产品,理由是无法达到该公司的产品要求。AirPower 是2017年宣布的,它是一个椭圆型的无线充电器,可以同时为三个设备进行无线充电。原定2018年上市,但被推迟了,现在终于宣布放弃。 外界猜测,真正的原因是物理学的限制,导致这个产品很难实现。主要的障碍有两个,一个是无线充电通过感应电流实现,会有一部分电量泄漏出来,AirPower 内部有多个线圈,如果同时充电,多个感应电流会互相加强,泄漏电量的强度可能会影响到心脏起博器和助听器这样的设备。另一个障碍是,无线充电的效率不是很高,多个设备同时充电,需要很大的功率,内部会有大电流,过热无法避免。 8、一句话新闻 GPS 传送的数据采用10个二进制位表示"周数",4月6日午夜这个字段将会溢出,重新归零。那些采用 GPS 授时的设备,可能将会出现时间错误。 欧洲议会通过决议,建议成员国2021年废止实行夏令时。此前,欧盟强制所有成员国实行夏令时。 法国与中国签署协议,参与2023-2024年实施的嫦娥六号探月计划,准备在嫦娥六号上搭载15千克的法方设备,包括一台照相机和一台分析仪。 抖音被美国联邦贸易委员会罚款570万美元,因为是没有经过监护人同意,就保存13岁以下儿童的信息。 文章 1、我的 Linux 桌面配置(英文) 一个高级程序员介绍他的 Linux 桌面开发环境,以及他的各种软件选择。 2、我们不再需要 Chrome(英文) Chrome 已经垄断了浏览器市场,作者论证为什么这种情况对互联网是不利的。 3、React Hooks 入门教程(英文) 一篇很好的 React Hooks 的入门介绍文章。 4、Kanban 与 Scrum 的比较(英文) Kanban 和 Scrum 都是敏捷开发的具体实现方法,本文讨论它们的异同。 5、在特斯拉工作的感受(中文) 在马斯克的影响下,特斯拉公司上下极其激进、残酷冰冷、毫无感情,你的工作不仅压力超级大,而且很有可能因为表现不好被开除。但是为什么还有员工没辞职呢? 6、LFU 算法的一种实现(英文) LFU 是常用的删除过期缓存的算法,本文介绍了它的一种代码实现。 7、重新设计 UI 基本上是浪费时间(英文) 作者认为,95%情况下,你不需要重新设计 UI。 8、中国超高压电网(英文) 中国已经建成了全国性的超高压电网,用来将西部的电力输送到东部。这是世界上前所未有的,IEEE 的这篇报道进行了长篇介绍。 9、State of CSS 2019(英文) 针对全世界开发者的 CSS 调查。(@lanlejiudunle 投稿) 10、业余无线电爱好者入门(中文) 如何在国内拥有一个个人的无线电台。 软件 1、syncthing 多台电脑之间自动同步文件夹的工具,可以在命令行作为服务运行,也提供图形界面。 2、snailjs 一个同时包括前端和后端的 Web 框架,采用 node + react,可以用作架构参考。 3、subsync 有时,srt 字幕文件跟视频不同步,该工具可以自动让其同步。它的原理是,从视频里面检测出,何时有语音,然后将字幕与其对齐。 4、Zero server 一个 JS 的后端框架,设计很有意思,每个文件(HTML / JSX / JS)自动成为可访问的路径,不需要其他任何配置。 5、pi-hole 一个基于树莓派的家用 DNS 服务器,自带屏蔽广告功能。 6、dbdiagram.io 制作数据库关系图的在线工具。(@linlicro 投稿) 6、pagedraw 一个浏览器里面的 UI 生成器,可以通过拖曳组件来设计 UI,然后自动生成 JSX 代码。 7、EditorConfig 生成编辑器配置文件,以便整个团队有同样的编辑器设置。 8、Pika 一个只能搜索 npm 上面的 ES6 模块的搜索引擎。 9、BashUpload 一个可以从命令行上传文件的网站,文件上传后可以保存七天,其间可以无限次下载。 10、dead.io 一个显示你是否还活着的 API,做法是它每隔一段时间向你发一封邮件,如果你连续多次没有回复,它就认为你已经死了。你可以通过这个 API,设置一些死了以后需要触发的动作。 11、colorise 一个为黑白照片着色的在线服务。(@bikmanwei 投稿) 12、dust3d 开源的 3D 建模软件,适用于游戏开发,3D打印等。(@huxingyi 投稿) 资源 1、React 教程 一个 React 的30天开源教程。(@CharlesCCC 投稿) 2、PC Assembly Language 介绍汇编语言的本科生入门教材,有中文译本,免费下载。 3、ARM 汇编语言简介 通过树莓派介绍 ARM 汇编语言的开源教材。 4、Visu Algo 各种算法的动态演示网站。(@wyzlove 投稿) 5、7DRL Challenge 2019 这是一个地图探险类(rogue like)游戏的比赛,全世界开发者都可以将自己的作品上传,唯一的条件是该游戏必须是在七天内开发完成。目前,已经有100多个作品,各个平台都有,其中将近一半可以在浏览器里面运行,都可以免费下载。 6、name-suggestion-index 这个项目收集各类商品的著名品牌,作为 OpenStreetMap 的自动拼写建议。比如,你在地图上要标识一家"名牌鞋专卖店",它会自动提示59个牌子的鞋子。 图片 1、建筑物的水平线和垂直线 以前的建筑物追求庞大威严,因此更看重高度和垂直感,会有很多垂直线。但是,现在的建筑物越来越多的是水平线。下图左边是以前的建筑,右边是当代建筑。 2、纯 CSS 图片 下面图片不是照片,而是纯粹用 CSS 生成的。(@beiyeqingteng 投稿) 3、佛罗里达钓鱼比赛 美国佛罗里达州每年举办出海钓鱼比赛。下图是1957年的比赛成果。 下图是80年代初的比赛成果。  最后是2007年。 可以看到,五十年间,鱼变得越来越小,种类也越来越少。 文摘 1、SQL 是最有价值的技能之一 我的职业生涯学到了很多技能,但没有比 SQL 更有用的技术技能。由于以下几个原因,SQL 对我来说是最有价值的技能。 (1)SQL 适用很多方面。 作为产品经理,你需要从数据库看数据。知道如何使用 SQL 查看原始数据,可以为你节省大量的精力,无需向其他人询问数字。 作为一名工程师,SQL 通常可以让我更快地获取我想要的信息,而不需要用 Ruby 或 Python 编写脚本。Web 应用变得缓慢时,了解所执行的 SQL 以及优化它的方法是不可或缺的。 (2)SQL 只需学习它一次,且不需要重新学习。 过去20年,SQL 并没有真正改变。当然,有一些新的改进,但是比起其他语言,它算是毫无变化。是的,每隔几年 SQL 会有一个新的标准,偶尔会出现一些新东西,但 SQL 的基础知识是非常永久的。学习 SQL 一次将允许您在职业生涯中重复使用它,而无需重新学习。 不要误会我的意思,我喜欢学习新的东西,但我宁愿学习一些真正新的东西,而不仅仅是另一种完成同样任务的方法。 (3)SQL 很酷。 熟练掌握 SQL 人并不多,大多数开发者跳过它,很少有人真正了解 SQL,所以掌握 SQL 的人可能看起来比实际更像精英。过去在一家拥有数百名工程师的公司中,我每周会收到多个同样的请求,来自从初级工程师到主要工程师各种人:"嘿,你能帮忙写一个查询吗?"因为你很擅长这样的事情,可以帮助其他人。 2、ARM 公司的蓝图 ARM 是一家芯片公司,但它自己不制造芯片,而是销售芯片的设计图纸。它是地球上最受欢迎的芯片公司,自1990年成立以来,根据它的图纸制造和销售的芯片高达1300亿片,苹果、华为、高通等巨头都购买 ARM 的设计,然后制造的每一块芯片都会向 ARM 支付版税。 2016年,孙正义的软银公司以320亿美元收购了 ARM。这是软银最大的收购,也是最昂贵的收购之一(比 ARM 的市值高出43%)。ARM 原来是一家很赚钱的公司,但是孙正义要求它将利润降至零,全力以赴扩展业务领域,争取收入的快速增长,而不是利润的增长。 收购之前的2015年,ARM 收入高达5.9亿英镑,利润5.39亿英镑。收购之后,2017年它的利润下降至3.25亿英镑,收入为13亿英镑。 ARM 重点关注的一个领域是汽车,它认为未来几年,越来越多的处理器将用于汽车。ARM 现在只占汽车芯片市场的20%份额。由于车内的电子设备越来越多,汽车制造商开始要求将多个控制电路做进一个芯片,以节省空间并消除电路的复杂性。随着自动驾驶汽车的出现,将需要更多的芯片。自动驾驶需要的计算能力是手机的10倍,这意味着每辆自动驾驶汽车,可能会让 ARM 收到十倍的特许费。ARM 预计,汽车芯片市场将变得与手机芯片市场一样大。 ARM 另一个重点领域是网络设备。ARM 认为世界将需要更多的网络设备,来有效地传送数据,并保证网络安全。ARM 在这个市场的份额从2011年的5%,已经增加到20%。 ARM 最弱的地方是服务器,这是一个几乎由英特尔垄断的市场,ARM 的份额不到1%。不过,去年11月,亚马逊宣布已经将 ARM 芯片用于服务器,开始提供云服务。主导云计算的巨型公司,希望能够有 ARM 服务器,这样就可以避免英特尔对他们索取垄断高价。 ARM 公司的一个障碍可能是开源芯片,任何企业都可以免费使用,从而放弃使用 ARM 芯片,比如 RISC-V 芯片就是开源的。 言论 1、 全周期工程师就是一个人负责完整的软件生命周期:设计,开发,测试,部署,操作和支持。 -- 《从全栈工程师到全周期工程师》 2、 只有大型工业,才会让人口大量聚集在一小块地方,愿意不干净地挤在一起生活。 -- T.E.劳伦斯《智慧七柱》 3、 磁带储存数据有一个好处,要是断了,只要把两头再连起来,依然可以读取文件,只丢了断掉的那部分。 -- 《CERN 见闻》 4、 互联网公司的时间是狗年。狗的一年,据说相当于人的七年。一家开张两年的互联网公司,就像经营了二十年的传统行业公司。 -- 某微信公号 5、 任何一种专门服务小企业的软件都很糟糕。对于大众软件来说,客户获取成本低,开发成本可以分散在数百万人身上,因此即使价格低,也有巨大的利润潜力。对于大企业软件而言,客户获取成本很高,但报酬也很高。对于小企业软件而言,客户获取成本仍然很昂贵(面对面的个人销售和售后支持),但销售价格仍然很低。 --《从零到一》 订阅 这个专栏每周五发布,同步更新在我的个人网站、微信公众号和语雀。 微信搜索"阮一峰的网络日志"或者扫描二维码,即可订阅。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年4月 5日


OAuth 2.0 的一个简单解释

2019-04-04 00:18:04 阮一峰

OAuth 2.0 是目前最流行的授权机制,用来授权第三方应用,获取用户数据。 这个标准比较抽象,使用了很多术语,初学者不容易理解。其实说起来并不复杂,下面我就通过一个简单的类比,帮助大家轻松理解,OAuth 2.0 到底是什么。 一、快递员问题 我住在一个大型的居民小区。 小区有门禁系统。 进入的时候需要输入密码。 我经常网购和外卖,每天都有快递员来送货。我必须找到一个办法,让快递员通过门禁系统,进入小区。 如果我把自己的密码,告诉快递员,他就拥有了与我同样的权限,这样好像不太合适。万一我想取消他进入小区的权力,也很麻烦,我自己的密码也得跟着改了,还得通知其他的快递员。 有没有一种办法,让快递员能够自由进入小区,又不必知道小区居民的密码,而且他的唯一权限就是送货,其他需要密码的场合,他都没有权限? 二、授权机制的设计 于是,我设计了一套授权机制。 第一步,门禁系统的密码输入器下面,增加一个按钮,叫做"获取授权"。快递员需要首先按这个按钮,去申请授权。 第二步,他按下按钮以后,屋主(也就是我)的手机就会跳出对话框:有人正在要求授权。系统还会显示该快递员的姓名、工号和所属的快递公司。 我确认请求属实,就点击按钮,告诉门禁系统,我同意给予他进入小区的授权。 第三步,门禁系统得到我的确认以后,向快递员显示一个进入小区的令牌(access token)。令牌就是类似密码的一串数字,只在短期内(比如七天)有效。 第四步,快递员向门禁系统输入令牌,进入小区。 有人可能会问,为什么不是远程为快递员开门,而要为他单独生成一个令牌?这是因为快递员可能每天都会来送货,第二天他还可以复用这个令牌。另外,有的小区有多重门禁,快递员可以使用同一个令牌通过它们。 三、互联网场景 我们把上面的例子搬到互联网,就是 OAuth 的设计了。 首先,居民小区就是储存用户数据的网络服务。比如,微信储存了我的好友信息,获取这些信息,就必须经过微信的"门禁系统"。 其次,快递员(或者说快递公司)就是第三方应用,想要穿过门禁系统,进入小区。 最后,我就是用户本人,同意授权第三方应用进入小区,获取我的数据。 简单说,OAuth 就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。 四、令牌与密码 令牌(token)与密码(password)的作用是一样的,都可以进入系统,但是有三点差异。 (1)令牌是短期的,到期会自动失效,用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。 (2)令牌可以被数据所有者撤销,会立即失效。以上例而言,屋主可以随时取消快递员的令牌。密码一般不允许被他人撤销。 (3)令牌有权限范围(scope),比如只能进小区的二号门。对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。 上面这些设计,保证了令牌既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全。这就是 OAuth 2.0 的优点。 注意,只要知道了令牌,就能进入系统。系统一般不会再次确认身份,所以令牌必须保密,泄漏令牌与泄漏密码的后果是一样的。 这也是为什么令牌的有效期,一般都设置得很短的原因。 OAuth 2.0 对于如何颁发令牌的细节,规定得非常详细。具体来说,一共分成四种授权类型(authorization grant),即四种颁发令牌的方式,适用于不同的互联网场景。下一篇文章,我就来介绍这四种类型,并给出代码实例。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年4月 4日


把运维和开发放一起就是DevOps?还差得远!

2019-03-31 08:10:45 李强

DevOps倡导“谁开发,谁运维”和开发运维一体化。那么是不是简单地把开发和运维人员放在一起就完事了呢?

tags: DevOps


浅谈 Go 语言 select 的实现原理

2019-03-30 08:22:00 Draveness

很多 C 语言或者 Unix 开发者听到 select 想到的都是系统调用,而谈到 I/O 模型时最终大都会提到基于 select、poll 和 epoll 等函数构建的 IO 多路复用模型,我们在这一节中即将介绍的 Go 语言中的 select 关键字其实就与 C 语言中的 select 有比较相似的功能。


每周分享第 49 期

2019-03-29 02:39:00 阮一峰

这里记录过去一周,我看到的值得分享的东西,每周五发布。 欢迎投稿,或推荐你自己的项目,请前往 GitHub 的 ruanyf/weekly 提交 issue。 (题图:千岛湖,浙江,2018) 一个美国程序员分享自己的工作方法,其中有一条是 "要么不做,要做就做完"。 他的意思是,不要给自己留下做了一半的活。因为这意味着你需要再回来,继续把它做完;你会挂念这件事情,它就像一个钟摆,过一段时间就会重新出现在你的脑海,时不时烦扰着你。 你的目标应该是,当天就把这件事情做完,从此不必再去碰它,第二天继续做下一件事就行了。如果遇到一天做不完的大项目,那就把它分解成一个个小步骤,每天完成一个步骤。 我觉得他说得很好,但是这句话比较重要的,其实是前半句:有些事情不要去做。事情是做不完的,而你的时间和精力是有限的,不要只想着如何才能把事情做完,还要学会不做那些不应该做的事情。 某种程度上,不做比做完更困难。因为通常来说,做完一件事,多多少少都有一些好处,不做意味着你要放弃一些眼前的好处,这并不容易。 最糟糕的一种情况是,某个项目不值得做,但是你已经做了,为了不要浪费已经投入的成本,于是你进一步投入,在泥坑里面越陷越深。等到项目最后失败的时候,你大伤元气,一蹶不振。项目管理有一个很重要的原则,叫做"尽快失败",就是为了防止这种情况。胡适先生原来学农科,专业是果树栽培,他觉得实在没意思,大学读到一半就改学哲学,后来当上了北大校长。如果他没有放弃,想着拿完农科文凭再说,那他大概就不会有以后的成就了。总之,对于那些没希望的项目,放弃得越早越好。 新闻 1、胰岛素胶囊 糖尿病的病人需要注射胰岛素,而胰岛素只能血液给药(注射),不能通过口服,因为无法进入血液。麻省理工学院开发了一种胰岛素胶囊,可以通过口服补充胰岛素,大大方便了患者。 它的做法是,胶囊里面带有弹簧和一个可降解的小针,针头由压缩的冷冻干燥的胰岛素制成。当胶囊进入胃中,胃酸溶解了外层的糖壳,弹簧就会舒张,针头射到胃壁上,药物穿透胃壁,溶解进入血液。胃壁没有神经,因此患者感受不到疼痛。 2、气候科学家的遗言 2月中旬,美国著名气候科学家 Wallace Smith Broecker 录制了遗言。一周后,他就去世了。 遗言中,他认为由于过度排放二氧化碳,气候灾难已经无法避免,下一步人类将不得不采用一些极端的措施,比如在地球大气层中建立一个巨大的太阳光屏障,防止地球温度太高。最坏的情况下,我们需要让喷气式飞机,在地表以上约70,000英尺的大气中,释放大量二氧化硫。这跟大规模火山喷发的效果相似,1991年菲律宾的皮纳图博火山爆发,喷出的硫磺气体在整整一年的时间里,让地球冷却了一摄氏度。 3、白鲸回归海洋 上海长风海洋世界白鲸馆内的两头明星小白鲸"小白"和"小灰",2月28日进行了最后一次表演。这次表演结束后,这对白鲸姐妹将结束15年的表演生涯,重回大海怀抱。 为了帮它们找到一个合适回归的地方,团队实地考察了俄罗斯、北美洲、挪威和苏格兰等地。最终,位于冰岛南部海岸赫马岛的 Klettdvik 海湾,成为放归目的地,而它们也将成为该保护区首批住客。这个由默林娱乐集团创立的海洋生物基金会(SEA LIFE TRUST)打造的全球首个大型鲸目动物保护区,水域广达32000平方米、深达10米,非常适合鲸类生活。 为了让这趟回归之旅更加安全舒适,来自欧洲的卢森堡货运航空公司,为小白和小灰赞助了一架"私人飞机"。"私人飞机"为波音747-400ERF货机,足足有大半个足球场那么大。飞机表面还喷绘了小白小灰的可爱笑脸。 4、沃尔沃的安全措施 沃尔沃汽车宣布,从2020年开始,将提升旗下产品的安全等级。最主要的措施是,沃尔沃汽车的最高速度只能到180公里/小时,任何情况下都无法超出这个速度。另外,每辆汽车都自带数字地图,当行驶在学校、医院、行人密集的区域时,汽车行驶速度将自动放慢,无法加速。该功能被称为地理围栏。 5、AI 预测老年相貌 美国和加拿大的一组科学家开发了一个 AI 系统,可以根据照片和视频,生成该人老年时的相貌。科学家说,该系统的一个用途是寻找多年前失踪的儿童。 6、TensorFlow 的廉价硬件 TensorFlow 是谷歌的机器学习库,通常需要运行在昂贵的硬件上面。为了降低对硬件的要求,谷歌推出了 TensorFlow Lite 1.0,可以运行在嵌入式硬件上面。上图是一个 Cortex-M4 主板,可以运行简单的语音识别任务。这块主板具有 384KB RAM 和 1MB 闪存存储,售价只有15美元,功耗极低,使用一颗纽扣电池就可以运行数天。人工智能的硬件要求越来越低,以后越来越多的设备将具备"智能"。 7、隼鸟2号的难题 日本隼鸟2号(Hayabusa2)探测器,于2019年2月22日成功登陆小行星"龙宫"(Ryugu)。按照计划,它将于4月在小行星表面制造一次爆炸,然后抓取爆炸产生的地层内部碎片,2019年12月返回地球。 但是,这个计划现在遇到了一个问题。小行星"龙宫"非常小,大约是一个直径1公里的球体。这意味着,它的引力也非常小,任何速度高于每秒38厘米的物体都具备了逃逸速度,可以摆脱它的引力,飞向宇宙深处。这个速度大约就是企鹅的前进速度。那么爆炸产生的碎片会不会都脱离小行星,飞向宇宙?日本研究人员表示,他们还没有考虑这个问题,目前无法判断结果会是怎样。 8、MySpace 丢失数据 MySpace 宣布,用户在2003年~2015年上传到该网站的照片、音乐、视频,都已经丢失,无法找回。很显然,该网站没有备份。2006年,MySpace 曾经一度超过谷歌,成为美国访问量最大的网站。 这件事情的教训就是,永远不要相信,网站会永久保存你上传的数据。 9、一句话新闻 Intuit 是美国最畅销的报税软件,现在被发现,过去五年它花了1150万美元,游说政府不要减税。 美国政府正在考虑 6G 和 7G 的频谱分配,范围是 95GHz 到 3THz。作为参考,5G 的频谱范围大约 2GHz 到 60GHz。 挪威立法禁止砍伐森林,并且禁止采购任何与砍伐森林相关的产品。比如,砍伐森林改种果树,那么这些水果将无法向挪威出口。 中国已经成为全世界出国旅游人数最多的国家,尽管只有7%的中国人(9700万)有护照。 文章 1、JavaScript 模块简史(英文) 本文介绍历史上 JavaScript 各种模块方案的演变。 2、广告 ID 的现状(英文) 通常,网站用 Cookie 设置 ID,以便追踪用户。用户可以通过清除 Cookie,防止被追踪。但是手机上,App 可以通过无法重置的硬件 ID 追踪用户,比如 IMEI、网卡 MAC 地址,SIM 卡序列号等。为了解决这个问题,iPhone 和安卓都提供广告 ID 功能,既可以表示身份,又可以被用户重置。 3、SSD 硬盘是否可靠?(英文) 本文介绍了固态硬盘 SSD 的一些知识,以及与传统硬盘可靠性的对比。 4、磁力链接介绍(英文) 磁力链接是下载和共享 bittorrent 文件的一种方式,本文介绍了磁力链接的基本知识,以及与 Torrent 文件的关系。 5、单页应用的二进制打包(英文) 本文介绍了一种方法,将网站打包成一个 Go 语言的二进制程序。启动网站,就是运行这个程序。 6、抽象的成本(英文) 重复的代码通常会被抽象掉,本文讨论抽象带来的额外成本。 7、JSX 的替代方案(英文) JSX 是前端框架中书写网页代码的一种形式,本文介绍了 JSX 的替代方案,如果不用它,你有什么选择,以加深理解。 8、创建你的第一个 npm 包(英文) 入门文章,针对新手介绍如何创建一个 npm 模块。 9、App 的实验数据(英文) 很多 App 会进行 A/B 测试和新功能实验,将数据传回服务器,本文分析了 Airbnb、Pinterest 等 App 传回服务器的数据。 10、每行80个字符是很好的标准(英文) 作者谈了为什么每行80个字符的长度非常合理有用。 11、独立运行的 WebAssembly(英文) Mozilla 宣布发布独立的、跟 Web 无关的 WebAssembly 运行时,即 WASM 代码现在可以直接在各个操作系统运行。 软件 1、AssemblyScript 一个将 TypeScript 编译成 WebAssembly 的工具。 2、gitmoji-cli 在 git commit message 里面使用 emoji 的工具。(@LanjianNUll 投稿) 3、How old is it 该网站可以查询各种技术存在了多久,用来供 HR 招聘时了解,有些技术岗位要求五年经验是不现实的。 4、WorldWideWeb 世界第一个浏览器的模拟器,还原了欧洲核子研究中心发明的 WWW 服务。 5、uncss 去除样式表里面没有用到的 CSS 规则的工具。(@IceBay 投稿) 6、Bookworm 电子书阅读软件,目前只能在 Linux 系统安装。 7、EmailBin 向该网站发送 Email,你的 Email 会变成一个网页,所有人都可以访问。 8、ICONSVG 一套可以定制的 SVG 图标。 9、ayvri 根据行进路线,生成 3D 可视化的行程视频。 10、day.js 一个 2KB 的 JS 日期时间库,和 Moment.js 的 API 设计保持完全一样. 如果您曾经用过 Moment.js, 那么您已经知道如何使用 Day.js。(@xxyuk 投稿) 11、WordPress 版微信小程序 将 WordPress 应用转为微信小程序。(@Y024 投稿) 12、greendns 一个防止 DNS 污染且 CDN 友好的开源 DNS 服务端。(@faicker 投稿) 13、996.icu 一个程序员制作的抗议 996 工作制的网站。(@9527q 投稿) 资源 1、OCaml 语言在线教程 OCaml 语言教程,从最简单的讲起。 2、Qt5 教程 开源电子书,介绍如何使用 Qt5,开发图形界面。 3、Python 数据科学手册 使用 Python 工具进行数据科学研究的教程,现在全书开源了。 4、WikiHow 一个收集如何解决生活中各种问题的网站,比如"如何换轮胎"、"如何调整电脑字体大小"等等。(@xcuYao 投稿) 5、互动式计算机语言学习网站 该网站提供近10种常用语言(C、Python、JS、Java 等等)的实例教程。(@baibm 投稿) 6、计算机理论导论 哈佛大学本科生的《计算机理论》课程的教材,已经开源。 7、Japan Dev Jobs 一个分享日本技术工作机会的邮件列表,想去日本工作的开发者可关注。(@roujiangzailushang 投稿) 图片 1、密码雕塑 美国 CIA 总部内部有一件雕塑品,上面是四段加密文字。这是1989年一位雕塑家创作的。目前,其中三段已经被破解了,但是最后一段依然无法破解。 2、红衫树桩 1890年,美国加州砍伐了一棵红衫之后,人们的合影。 3、月亮照片 一位爱好者拍摄了近5万张夜空图像,然后合成了一张81万像素的月球图像。 文摘 1、为什么你应该停止阅读新闻? 今天的新闻业与以前有很大不同。 (1)新闻传播的速度大大提高。现在,新闻在发生后的几秒内,就开始传播,每个人在很短时间内,就会知道发生了什么事。 (2)新闻的产出成本大幅下降。现在,有人可以每天写12篇报道,一年就是近3000篇,这还只是一个人的产量。这么快的产出速度,几乎不可能在一个主题有一些深思熟虑的东西。由于产出成本已降至接近零,因此新闻业存在很多竞争。 (3)新闻业企图给读者洗脑。今天的新闻不再强调客观,而是充满了主观看法,企图用个性吸引读者。 (4)点击量成了主要目标。由于竞争激烈,大多数新闻媒体都不得不提供免费新闻,因此必须依靠广告产生收入。广告收入的高低直接依赖于点击量。创造很多耸人听闻的新闻,最容易获得点击。 总之,今天网上的大部分新闻都毫无意义,对你的生活并不重要,不会帮助你做出更好的决定,也不会帮助你理解世界,与周围的人建立联系。它们只会消耗你的注意力,造成你的注意力不足。你被大量信息包围,感到不知所措,为了赶上这一切,内心承受了压力。完全不看新闻,可能是更好的做法。 2、研究也是一种债务 大多数研究就像爬山一样。 有抱负的研究人员必须努力理解摆在他们面前的大量工作,学习各种技巧,攀登现有知识的顶峰。到达顶峰后,研究人员开始做新的工作,将新的石头扔到山顶上,让接下来的人可以爬得更高一点。 数学就是一个鲜明的例子。几个世纪以来,无数学者攀登了数学山脉,并在顶部铺设了新的巨石。随着时间的推移,形成了不同的山峰,建立在美丽的数学定理之上。当代数学的高峰是如此众多和陡峭,以至于任何人都无法全部攀爬它们。即使经过一生的努力,数学家也只能享受其中的一些景观。 人们期望攀登变得艰难,这反映了数学的巨大进步和数学家的努力。攀登被视为一次智力朝圣,是一种晋级的仪式。但是,攀登本身并不值得骄傲。 科学的山峰越来越高,攀登越来越难,这并不是单纯的进步,而是留给后人的一堆债务。 言论 1、 我们这个时代的痛苦在于,那些愚蠢的人都非常自信,那些有想象力和理解能力的人充满了怀疑和犹豫不决。 -- 《关于愚蠢》 2、 他拥有在一件事成为现实之前,就发现它的本事。对他显而易见的事情,其他人要等到十年之后,才觉得显而易见。 -- 《孙正义的故事》 3、 社交媒体的问题是永不结束。它只让你看最新的东西,就像在轮子上奔跑的仓鼠一样,我们生活在消耗短暂内容的无限循环中,结果我们失去了历史感。 -- 《此时此刻永无止尽》 4、 可乐不会形成味道的记忆。你可以在上午9点,上午11点,下午5点各喝一杯,而不会对它的味道厌倦,其他饮料都做不到,一段时间后你会厌倦它们。普通人每天饮用64盎司的液体,你可以将所有64盎司的液体都换成可乐。 -- 巴菲特解释他为什么投资可口可乐 5、 创业公司的一个好处是,一切都如此混乱,如果你不小心搞砸了某事,没有人会注意到。 -- HN 读者留言 订阅 这个专栏每周五发布,同步更新在我的个人网站、微信公众号和语雀。 微信搜索"阮一峰的网络日志"或者扫描二维码,即可订阅。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年3月29日


解锁卡片分类全过程

2019-03-28 08:00:42 Shia

从线下执行至线上分析一站教学式搞定

tags: 读书分享,卡片分类


商业画布初体验

2019-03-27 08:46:23 李强

本期向大家介绍一个在产品设计中的重要工具——商业画布。在产品研发中,产品经理常常将精力重点放在用户体验部分,设计了貌似完美的功能和极其花哨的界面,而在产品上线后却发现用户寥寥无几。究其根源,是因为对产品的商业模式没有一个清晰的认知和规划,在设计产品时没能找到正确的途径。本文将简要介绍商业画布这一工具及其绘制思想与方法,帮助我们避免陷入产品叫好不叫座的尴尬局面。

tags: 随笔


Grid 布局教程

2019-03-25 13:07:27 阮一峰

一、概述 网格布局(Grid)是最强大的 CSS 布局方案。 它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。以前,只能通过复杂的 CSS 框架达到的效果,现在浏览器内置了。 上图这样的布局,就是 Grid 布局的拿手好戏。 Grid 布局与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但是,它们也存在重大区别。 Flex 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大。 二、基本概念 学习 Grid 布局之前,需要了解一些基本概念。 2.1 容器和项目 采用网格布局的区域,称为"容器"(container)。容器内部采用网格定位的子元素,称为"项目"(item)。

1

2

3

上面代码中,最外层的
元素就是容器,内层的三个
元素就是项目。 注意:项目只能是容器的顶层子元素,不包含项目的子元素,比如上面代码的

元素就不是项目。Grid 布局只对项目生效。 2.2 行和列 容器里面的水平区域称为"行"(row),垂直区域称为"列"(column)。 上图中,水平的深色区域就是"行",垂直的深色区域就是"列"。 2.3 单元格 行和列的交叉区域,称为"单元格"(cell)。 正常情况下,n行和m列会产生n x m个单元格。比如,3行3列会产生9个单元格。 2.4 网格线 划分网格的线,称为"网格线"(grid line)。水平网格线划分出行,垂直网格线划分出列。 正常情况下,n行有n + 1根水平网格线,m列有m + 1根垂直网格线,比如三行就有四根水平网格线。 上图是一个 4 x 4 的网格,共有5根水平网格线和5根垂直网格线。 三、容器属性 Grid 布局的属性分成两类。一类定义在容器上面,称为容器属性;另一类定义在项目上面,称为项目属性。这部分先介绍容器属性。 3.1 display 属性 display: grid指定一个容器采用网格布局。 div { display: grid; } 上图是display: grid的效果。 默认情况下,容器元素都是块级元素,但也可以设成行内元素。 div { display: inline-grid; } 上面代码指定div是一个行内元素,该元素内部采用网格布局。 上图是display: inline-grid的效果。 注意,设为网格布局以后,容器的float、display: inline-block、display: table-cell、vertical-align和column-*等设置都将失效。 3.2 grid-template-columns 属性,grid-template-rows 属性 容器指定了网格布局以后,接着就要划分行和列。grid-template-columns属性定义每一列的列宽,grid-template-rows属性定义每一行的行高。 .container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; } 上面代码指定了一个三行三列的网格,列宽和行高都是100px。 除了使用绝对单位,也可以使用百分比。 .container { display: grid; grid-template-columns: 33.33% 33.33% 33.33%; grid-template-rows: 33.33% 33.33% 33.33%; } (1)repeat() 有时候,重复写同样的值非常麻烦,尤其网格很多时。这时,可以使用repeat()函数,简化重复的值。上面的代码用repeat()改写如下。 .container { display: grid; grid-template-columns: repeat(3, 33.33%); grid-template-rows: repeat(3, 33.33%); } repeat()接受两个参数,第一个参数是重复的次数(上例是3),第二个参数是所要重复的值。 repeat()重复某种模式也是可以的。 grid-template-columns: repeat(2, 100px 20px 80px); 上面代码定义了6列,第一列和第四列的宽度为100px,第二列和第五列为20px,第三列和第六列为80px。 (2)auto-fill 关键字 有时,单元格的大小是固定的,但是容器的大小不确定。如果希望每一行(或每一列)容纳尽可能多的单元格,这时可以使用auto-fill关键字表示自动填充。 .container { display: grid; grid-template-columns: repeat(auto-fill, 100px); } 上面代码表示每列宽度100px,然后自动填充,直到容器不能放置更多的列。 (3)fr 关键字 为了方便表示比例关系,网格布局提供了fr关键字(fraction 的缩写,意为"片段")。如果两列的宽度分别为1fr和2fr,就表示后者是前者的两倍。 .container { display: grid; grid-template-columns: 1fr 1fr; } 上面代码表示两个相同宽度的列。 fr可以与绝对长度的单位结合使用,这时会非常方便。 .container { display: grid; grid-template-columns: 150px 1fr 2fr; } 上面代码表示,第一列的宽度为150像素,第二列的宽度是第三列的一半。 (4)minmax() minmax()函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。 grid-template-columns: 1fr 1fr minmax(100px, 1fr); 上面代码中,minmax(100px, 1fr)表示列宽不小于100px,不大于1fr。 (5)auto 关键字 auto关键字表示由浏览器自己决定长度。 grid-template-columns: 100px auto 100px; 上面代码中,第二列的宽度,基本上等于该列单元格的最大宽度,除非单元格内容设置了min-width,且这个值大于最大宽度。 (6)网格线的名称 grid-template-columns属性和grid-template-rows属性里面,还可以使用方括号,指定每一根网格线的名字,方便以后的引用。 .container { display: grid; grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4]; grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4]; } 上面代码指定网格布局为3行 x 3列,因此有4根垂直网格线和4根水平网格线。方括号里面依次是这八根线的名字。 网格布局允许同一根线有多个名字,比如[fifth-line row-5]。 (7)布局实例 grid-template-columns属性对于网页布局非常有用。两栏式布局只需要一行代码。 .wrapper { display: grid; grid-template-columns: 70% 30%; } 上面代码将左边栏设为70%,右边栏设为30%。 传统的十二网格布局,写起来也很容器。 grid-template-columns: repeat(12, 1fr); 3.3 grid-row-gap 属性,grid-column-gap 属性,grid-gap 属性 grid-row-gap属性设置行与行的间隔(行间距),grid-column-gap属性设置列与列的间隔(列间距)。 .container { grid-row-gap: 20px; grid-column-gap: 20px; } 上面代码中,grid-row-gap用于设置行间距,grid-column-gap用于设置列间距。 grid-gap属性是grid-column-gap和grid-row-gap的合并简写形式,语法如下。 grid-gap: ; 因此,上面一段 CSS 代码等同于下面的代码。 .container { grid-gap: 20px 20px; } 如果grid-gap省略了第二个值,浏览器认为第二个值等于第一个值。 根据最新标准,上面三个属性名的grid-前缀已经删除,grid-column-gap和grid-row-gap写成column-gap和row-gap,grid-gap写成gap。 3.4 grid-template-areas 属性 网格布局允许指定"区域"(area),一个区域由单个或多个单元格组成。grid-template-areas属性用于定义区域。 .container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-template-areas: 'a b c' 'd e f' 'g h i'; } 上面代码先划分出9个单元格,然后将其定名为a到i的九个区域,分别对应这九个单元格。 多个单元格合并成一个区域的写法如下。 grid-template-areas: 'a a a' 'b b b' 'c c c'; 上面代码将9个单元格分成a、b、c三个区域。 下面是一个布局实例。 grid-template-areas: "header header header" "main main sidebar" "footer footer footer"; 上面代码中,顶部是页眉区域header,底部是页脚区域footer,中间部分则为main和sidebar。 如果某些区域不需要利用,则使用"点"(.)表示。 grid-template-areas: 'a . c' 'd . f' 'g . i'; 上面代码中,中间一列为点,表示没有用到该单元格,或者该单元格不属于任何区域。 注意,区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为区域名-start,终止网格线自动命名为区域名-end。 比如,区域名为header,则起始位置的水平网格线和垂直网格线叫做header-start,终止位置的水平网格线和垂直网格线叫做header-end。 3.5 grid-auto-flow 属性 划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,即下图数字的顺序。 这个顺序由grid-auto-flow属性决定,默认值是row,即"先行后列"。也可以将它设成column,变成"先列后行"。 grid-auto-flow: column; 上面代码设置了column以后,放置顺序就变成了下图。 grid-auto-flow属性除了设置成row和column,还可以设成row dense和column dense。这两个值主要用于,某些项目指定位置以后,剩下的项目怎么自动放置。 下面的例子让1号项目和2号项目各占据两个单元格,然后在默认的grid-auto-flow: row情况下,会产生下面这样的布局。 上图中,1号项目后面的位置是空的,这是因为3号项目默认跟着2号项目,所以会排在2号项目后面。 现在修改设置,设为row dense,表示"先行后列",并且尽可能紧密填满,尽量不出现空格。 grid-auto-flow: row dense; 上面代码的效果如下。 上图会先填满第一行,再填满第二行,所以3号项目就会紧跟在1号项目的后面。8号项目和9号项目就会排到第四行。 如果将设置改为column dense,表示"先列后行",并且尽量填满空格。 grid-auto-flow: column dense; 上面代码的效果如下。 上图会先填满第一列,再填满第2列,所以3号项目在第一列,4号项目在第二列。8号项目和9号项目被挤到了第四列。 3.6 justify-items 属性,align-items 属性,place-items 属性 justify-items属性设置单元格内容的水平位置(左中右),align-items属性设置单元格内容的垂直位置(上中下)。 .container { justify-items: start | end | center | stretch; align-items: start | end | center | stretch; } 这两个属性的写法完全相同,都可以取下面这些值。 start:对齐单元格的起始边缘。 end:对齐单元格的结束边缘。 center:单元格内部居中。 stretch:拉伸,占满单元格的整个宽度(默认值)。 .container { justify-items: start; } 上面代码表示,单元格的内容左对齐,效果如下图。 .container { align-items: start; } 上面代码表示,单元格的内容头部对齐,效果如下图。 place-items属性是align-items属性和justify-items属性的合并简写形式。 place-items: ; 下面是一个例子。 place-items: start end; 如果省略第二个值,则浏览器认为与第一个值相等。 3.7 justify-content 属性,align-content 属性,place-content 属性 justify-content属性是整个内容区域在容器里面的水平位置(左中右),align-content属性是整个内容区域的垂直位置(上中下)。 .container { justify-content: start | end | center | stretch | space-around | space-between | space-evenly; align-content: start | end | center | stretch | space-around | space-between | space-evenly; } 这两个属性的写法完全相同,都可以取下面这些值。(下面的图都以justify-content属性为例,align-content属性的图完全一样,只是将水平方向改成垂直方向。) start - 对齐容器的起始边框。 end - 对齐容器的结束边框。 center - 容器内部居中。 stretch - 项目大小没有指定时,拉伸占据整个网格容器。 space-around - 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。 space-between - 项目与项目的间隔相等,项目与容器边框之间没有间隔。 space-evenly - 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。 place-content属性是align-content属性和justify-content属性的合并简写形式。 place-content: 下面是一个例子。 place-content: space-around space-evenly; 如果省略第二个值,浏览器就会假定第二个值等于第一个值。 3.8 grid-auto-columns 属性,grid-auto-rows 属性 有时候,一些项目的指定位置,在现有网格的外部。比如网格只有3列,但是某一个项目指定在第5行。这时,浏览器会自动生成多余的网格,以便放置项目。 grid-auto-columns属性和grid-auto-rows属性用来设置,浏览器自动创建的多余网格的列宽和行高。它们的写法与grid-template-columns和grid-template-rows完全相同。如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。 下面的例子里面,划分好的网格是3行 x 3列,但是,8号项目指定在第4行,9号项目指定在第5行。 .container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-auto-rows: 50px; } 上面代码指定新增的行高统一为50px(原始的行高为100px)。 3.9 grid-template 属性,grid 属性 grid-template属性是grid-template-columns、grid-template-rows和grid-template-areas这三个属性的合并简写形式。 grid属性是grid-template-rows、grid-template-columns、grid-template-areas、 grid-auto-rows、grid-auto-columns、grid-auto-flow这六个属性的合并简写形式。 从易读易写的角度考虑,还是建议不要合并属性,所以这里就不详细介绍这两个属性了。 四、项目属性 下面这些属性定义在项目上面。 4.1 grid-column-start 属性,grid-column-end 属性,grid-row-start 属性,grid-row-end 属性 项目的位置是可以指定的,具体方法就是指定项目的四个边框,分别定位在哪根网格线。 grid-column-start属性:左边框所在的垂直网格线 grid-column-end属性:右边框所在的垂直网格线 grid-row-start属性:上边框所在的水平网格线 grid-row-end属性:下边框所在的水平网格线 .item-1 { grid-column-start: 2; grid-column-end: 4; } 上面代码指定,1号项目的左边框是第二根垂直网格线,右边框是第四根垂直网格线。 上图中,只指定了1号项目的左右边框,没有指定上下边框,所以会采用默认位置,即上边框是第一根水平网格线,下边框是第二根水平网格线。 除了1号项目以外,其他项目都没有指定位置,由浏览器自动布局,这时它们的位置由容器的grid-auto-flow属性决定,这个属性的默认值是row,因此会"先行后列"进行排列。读者可以把这个属性的值分别改成column、row dense和column dense,看看其他项目的位置发生了怎样的变化。 下面的例子是指定四个边框位置的效果。 .item-1 { grid-column-start: 1; grid-column-end: 3; grid-row-start: 2; grid-row-end: 4; } 这四个属性的值,除了指定为第几个网格线,还可以指定为网格线的名字。 .item-1 { grid-column-start: header-start; grid-column-end: header-end; } 上面代码中,左边框和右边框的位置,都指定为网格线的名字。 这四个属性的值还可以使用span关键字,表示"跨越",即左右边框(上下边框)之间跨越多少个网格。 .item-1 { grid-column-start: span 2; } 上面代码表示,1号项目的左边框距离右边框跨越2个网格。 这与下面的代码效果完全一样。 .item-1 { grid-column-end: span 2; } 使用这四个属性,如果产生了项目的重叠,则使用z-index属性指定项目的重叠顺序。 4.2 grid-column 属性,grid-row 属性 grid-column属性是grid-column-start和grid-column-end的合并简写形式,grid-row属性是grid-row-start属性和grid-row-end的合并简写形式。 .item { grid-column: / ; grid-row: / ; } 下面是一个例子。 .item-1 { grid-column: 1 / 3; grid-row: 1 / 2; } /* 等同于 */ .item-1 { grid-column-start: 1; grid-column-end: 3; grid-row-start: 1; grid-row-end: 2; } 上面代码中,项目item-1占据第一行,从第一根列线到第三根列线。 这两个属性之中,也可以使用span关键字,表示跨越多少个网格。 .item-1 { background: #b03532; grid-column: 1 / 3; grid-row: 1 / 3; } /* 等同于 */ .item-1 { background: #b03532; grid-column: 1 / span 2; grid-row: 1 / span 2; } 上面代码中,项目item-1占据的区域,包括第一行 + 第二行、第一列 + 第二列。 斜杠以及后面的部分可以省略,默认跨越一个网格。 .item-1 { grid-column: 1; grid-row: 1; } 上面代码中,项目item-1占据左上角第一个网格。 4.3 grid-area 属性 grid-area属性指定项目放在哪一个区域。 .item-1 { grid-area: e; } 上面代码中,1号项目位于e区域,效果如下图。 grid-area属性还可用作grid-row-start、grid-column-start、grid-row-end、grid-column-end的合并简写形式,直接指定项目的位置。 .item { grid-area: / / / ; } 下面是一个例子。 .item-1 { grid-area: 1 / 1 / 3 / 3; } 4.4 justify-self 属性,align-self 属性,place-self 属性 justify-self属性设置单元格内容的水平位置(左中右),跟justify-items属性的用法完全一致,但只作用于单个项目。 align-self属性设置单元格内容的垂直位置(上中下),跟align-items属性的用法完全一致,也是只作用于单个项目。 .item { justify-self: start | end | center | stretch; align-self: start | end | center | stretch; } 这两个属性都可以取下面四个值。 start:对齐单元格的起始边缘。 end:对齐单元格的结束边缘。 center:单元格内部居中。 stretch:拉伸,占满单元格的整个宽度(默认值)。 下面是justify-self: start的例子。 .item-1 { justify-self: start; } place-self属性是align-self属性和justify-self属性的合并简写形式。 place-self: ; 下面是一个例子。 place-self: center center; 如果省略第二个值,place-self属性会认为这两个值相等。 五、参考链接 A Complete Guide to Grid, by Chris House Understanding the CSS Grid Layout Module, by Ian Yates How to Build an Off-Canvas Navigation With CSS Grid, Ian Yates Introduction to the CSS Grid Layout With Examples, Dogacan Bilgili Learn CSS Grid, Jonathan Suh How I stopped using Bootstrap's layout thanks to CSS Grid, Cédric Kui (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年3月25日