黄总

黄总 查看完整档案

广州编辑佛山职业技术学院  |  修电脑 编辑自由人  |  扫地 编辑 fastdlabs.com 编辑
编辑

不能因为菜刀能砍人你就以为菜刀只能砍人

个人动态

黄总 赞了回答 · 2019-10-08

解决前端如何实现图片防盗链的破解

<meta name="referrer" content="never">

关注 6 回答 4

黄总 评论了文章 · 2018-12-29

PHP、Android、iOS 的恩恩怨怨

其实应该更多的是互相的磨合与学习,希望身边的人可以有自己的经验分享,与理解,互相进步才是大家需要的,作为一个 "年老" (我也是90后) 的开发者,我觉得一代胜一代,未来才有胜算。额,好了,我不充当老师的角色了,去正题。

1. 安卓中 a 标签的坑

在和客户端交互的过程中,往往都有跳转的,而在咱们 Web 开发中,默认的 href 属性通常是 #,然后通过获取标签绑定动作触发事件,这里有个坑,在与安卓交互过程中会发现。

<a href="#">click me</a>
// include zepto or jquery or other.
$(function () {
    $('a').on('tap, click', function () {
        alert('test');
        return false;
    });
});

上述代码中,会引起安卓交互中的一个坑,就是没点击一次,安卓都会在计数器上+1, 也就是,点击第一次,弹一次窗,点击第二次,会弹两次窗,如此类推。

解决方法:

<a href="javascript:void(0);">click me</a>

Fxied!!

2. 安卓中交互的坑

我丢,安卓这个坑爹,在 js 交互中,无法传递对象,匿名函数等等的类型。也就是说,如果你的参数是接受一个对象的,你必须将她转成 String,而且安卓中的返回值也是只能返回 String,在咱们接受之后需要将字符串转换成对象。

简单 判断客户端类型的:

isiOS: function () {
     if (this.ua.match(/android/i) == "android") {
         return false;
     }
     return true;
 },
 isAndroid: function () {
     if (this.ua.match(/android/i) == "android") {
         return true;
     }
     return false;
 }

解决方法:

encode: function (data) {
     if ("" == data) {
         return {};
     }
     return JSON.stringify(data).replace(/"/g, '\'');
 },
 decode: function (data) {
     if ("" == data) {
         return "{}";
     }
     return JSON.parse(data.replace(/\'/ig,'\"'));
 }

在调用 iOS 或者 android 的时候,先将参数传递到 encode 处进行过滤。

3. 判断页面是否在应用内打开

其实这个很简单,经常做 web 开发的都应该知道,咱们每天都与 Http 协议打交道,而在 Http 中,有一个很重的的标识,就是 User-Agent,简称 UA,其实这个东西就像咱们的门票一样,有着各种的信息在上面,其实就包括了很多的浏览器内核信息,版本信息,厂商等等......咱们就是从这个地方入手,在客户端中定义自己的版本信息,与微信一样。从此告别什么 url 上加什么破参数啊什么的。

以我的经验来设计的话,一般按照这个格式:

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5 {company} {appname} [{type}]/{version}

如: 腾讯,微信 [海外版本] 6.0.0

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5 Tencent MicroMessager oversase/6.0.0

因为此处我还没太多接触客户端开发,暂时没有客户端代码演示.

us: window.navigator.userAgent.toLowerCase(),
is: function (name) {
    return tools.ua.match(eval("/" + name + "/i")) == name ? true : false;
}

Examples:

if (/* Is app inside */) {
    /* Operation */
} else {
    /* Is app outside */
    /* Operation */
}

Combine: In wechat

if (/* In wechat app */) {
    /* open share guide */
} else {
    if (/* In app */) {
        if (/* Is iOS */) {
            /* share iOS sdk */
        } else {
            /* share android sdk */
        }
    } else {
        /* share operation */
    }
}

4. 请善用你的 Http Status Code

曾几何时,我也是一个懵懂无知的骚年,连接口是干嘛用的都不知道,大概也在 2014/8 月份左右,我对接口都是一种很敬畏的眼光去看待,直到现在,2016年,我更加视接口是一切数据库的来源,其价值是最至高无上的。但是由我接触接口(Application Programing Interface)开发之后,我发现目前的接口有好多问题,一个很明显的就是,为啥每个接口都是 200,不应该啊,那非 200 响应的应该怎么办?有做处理吗?
直到后来,我推翻了这一现象,也说服了各方的人。我举一个 Ajax 的例子:

首先我先问一个问题,为何 jquery 和 zepto 的 ajax 中,都有一个 error 回调?

$.ajax({
    // some code
    success: function () {},
    error: function () {}
});

请不要怀疑设计者的智商与知识,我猜他应该会比你聪明以及牛叉。这么做,肯定有原因的。其实这里的 error 就是为了让非 2xx 状态的时候进入的操作的。

如示例:

{
    status: 1
    content: {}
}

以上例子本身没有错误,仅以自己看法对上述进行评述

其实咱们应该要善用本身已经有的东西,不需要再重新造多一个,吃力不讨好,那你们就开始好好补一补 Http Status code 相关的知识吧。

示例:

Request Method:GET
Status Code:200 OK

200 一般都是成功响应,
3xx
4xx
5xx

根据不同的状态码进行不同的处理机制,无需重复再做这一步骤了,其实设计者也很清晰设计出状态码的意义,应该善用。

5. 判断应用是否安装,如果安装,则打开,否则则跳去下载

其实这个有点无理取闹,但是又不得不去做,首先这个其实原理也是挺绕的

  1. 利用iframe尝试打开自定义scheme

  2. 跳转到下载地址

只是那个判断......

其实我是建议这些操作统一由一个地方去做,比如定义一个域名叫: down.xxx.com/应用id,后台读取应用id 相信信息,统一由一处转发。

function open () {
    var ifr = document.createElement('iframe');
   ifr.src = url;
   ifr.style.display = 'none';
   document.body.appendChild(ifr);
   window.setTimeout(function(){
       document.body.removeChild(ifr);
   }, 3000);
}

注意 iOS9 对这个有点不兼容,所以,谨慎,iOS7,iOS8,安卓均可以实现

获取版本信息:

var getVersion = function () {
  if (tools.client.isAndroid()) {
      return parseFloat(tools.ua.match(/Android\s(.*?);/i)[1]);
  }

  return parseFloat(tools.ua.match(/OS\s(.*?)\slike/i)[1].split('_').join('.'));
};

这里需要判断系统类型及版本:

if (/* iOS */) {
    if (/* iOS version less than 9.0 */) {
        /* try open scheme */
        /* redirect download link */
    } else {
        /* other operate */
    }
} else {
    /* try open url */
    /* redirect download link */
}

所以,由此可见其实这里的判断会很多,很多,很多。所以我墙裂建议都统一到一个地方做分发。

这里其实还需要判断是否微信,是否应用内打开,是否是分享出去的。

结合第 3 点的例子想想,这里的 if ...... 其实还是很恐怖的,我已经无路可退了......

查看原文

黄总 评论了文章 · 2018-11-20

我的 PHP 学习路线

我的 PHP 学习路线

1. PHP 入门

PHP 入门没啥好说的,会基本编码,基本的开发结构(通常指MVC,呵呵哒),类与对象,就差不多了,可以说是入门了。

1.1 OOP

写 PHP 最多目前无非就是 OOP,面向对象,说时迟那时快。不开玩笑地说,与我共事的某些前辈是连 OOP 都搞不清的,这里我就不多说了。

其实不是说一定要会,要去理解 OOP,只是如果你理解这个玩意,对于你后面的工作已经学习会非常的有好处。

其实面向对象也没有那么复杂,只要理解一点,单一职责,其实就是一个对象越简单越好。

也就是说,是自己该做就由自己做,不该由自己做的就不要自己做。

1.2 MVC

老梗了,所谓 MVC 很多人会说 Model, View, Controller, 其实这样说没错的,只是这样说不会让你更好地理解结构以及扩展性。

MVC 我当前的理解是:调用(度),也很简单,其他框架也差不多这个原理,当然每个框架的实现方式都不一样。

基本流程:

+--------------+      +-----------+      +--------------+                  +--------------+
|              |  ----+  request  +----> |              |  ------------>   |              |
|              |      +-----------+      |              |                  |              |
|   Request    |                         | Route Match  |                  |    Handle    |
|              |      +-----------+      |              |   +----------+   |              |
|              | <----+ Response  +----- |              | <-+ Response +-- |              |
+--------------+      +-----------+      +--------------+   +----------+   +--------------+

大致列了下最基础的框架底层原理,实际上咱们开发中 90% 接触的只是在 Handle 处的工作,至于 RequestMatchRoute 等基础的对象或者数据,框架早已经封装好了,也无需过度纠结和头疼这方面的事情,先要把业务功能处理好,并且容错处理好即可。

简单总结一句话:知其然而不知其所以然


2. PHP 进阶

进阶这个真是个头疼的问题,啥叫进阶,我的理解是,做一些之前没有做过的(指本领域:PHP),例如:设计模式,SPL,缓存设计(Cache),研究框架,开发规范,单元测试,行为驱动开发,组件(包括自己着手开发的),Composer 等等的东西,都可以理解为进阶。

框架推荐:

  1. Symfony
  2. Laravel
  3. Yaf

PHP 开发规范(PSR):

  1. PHP FIG

PHPUnit & TDD/BDD:

  1. PHPUnit
  2. PHP spec

设计模式:

  1. 设计模式

SPL:

  1. PHP SPL

Composer:

  1. Composer

欢迎补充

2.1 设计模式

设计模式,一个在软件设计中占有重要角色的课程,而我们又不得不去了解。而对于设计模式来说,很多人是抗拒的,因为他和普通的开发者有着不一样的思维方式,一个很明显的提升就是: 设计,而设计应该是根据发展的变化而变化,业务的变化而变化,模式也一样,不会是永恒不变的。唯一不变的是,基础,这些技巧与思维少不了的是需要良好的基础。

所以说,基础是多么重要的,任何一切的一切都是建立与基础之上,这叫积累。如同盖楼。

在这些已有基础,我们需要学习并且还需要学会各种推陈出新,这样才可以让自己让他人走得更远。

设计模式学习推荐: 设计模式

2.2 资源节省

当今互联网,每秒钟都是钱,能节省的,绝对不能浪费,而且节省还可以一定地提高服务的质量。

一般我们说的资源是:

  1. 内存
  2. 带宽
  3. 磁盘
  4. CPU

而这些之间其实是有一定的关联的,和代码质量和容错机制也有一定关系。

上述每一个都很重要,决定着你的服务质量。

能少占用内存就少占用内存,图片、媒体资源能压缩就压缩,减少无用的存储,降低代码的复杂度。

2.3 容错

比较常见的是: file_get_contentsconnection,有时候我们会很自然地遗忘这里其实会有一定几率出现超时,最严重的就是造成服务无响应,如下代码:

file_get_contents('https://www.google.com/');

这代码分分钟被打,活生生将程序毁了。

如果发生超时,会占用大量 CPU,严重可能会导致服务无响应,危害极大。

容错是每个开发者在开发过程中必须要考虑的地方,没有代码没有 “八阿哥”,总会有意外的地方,做好容错可以最大程度地减少对用户的伤害以及可以有效提高在出错时的用户体验。百利而无一害。

2.4 日志

日志,一个很容易被无视而又非常非常重要的环节,可以说,这一环节比你做的任何一个地方的业务代码都要重要。

日志的好处:

  1. 记录,跟踪
  2. 调试
  3. 恢复
  4. 分析
  5. 调优
  6. 等等...

好处有好多,但在我们开发者当中,其日志最重要的功能之一就是,记录问题,调试代码,优化架构。

不得不说日志的重要性,请你好好重视这一个容易被忽略的环节。

而日志的设计需要考虑性能,不能因为日志而影响服务质量哦。所以在日的环节在完整性和效率上要做好权衡。

2.5 缓存设计

缓存必须是针对业务情况而设计,不能生搬硬套。大公司的不一定适合你,开源方案也不一定不适合你,一定要找到自己合适的方案。

而在缓存设计方面,我个人推荐这一系列的文章: 缓存使用与设计

通俗简单地说,缓存的目的是为了提高服务的响应速度以及质量,不能因为缓存的添加而导致服务异常。

2.6 原理理解 (这里说到框架的研究,说得不好的地方,请多多批评和教导)

我们平时开发接触不同的开发工具,操作,甚至是监控,那么他们其中的原理,你又理解么?

其实我们每天接触的东西都有它的实现原理,算法等等的东西,但我们一直都在使用,并没有很好地去理解他们当中的奥秘。时候有空去接触一下了。

首先,开发,编码我觉得就是将现实生活搬到互联网中,我举个例子:

为什么人访问量上来了,咱们就要扩容,去扩展呢?原理很简单,看看咱们超市里面的收银台就知道了。咱们超市里面所有收银台不是每天每个位置都有人的,根据人流(流量)动态扩容,而且有些收一台的一个位置上设置有两个人(多线程/多进程,看个人理解),这个设计挺妙的。当人一多,就会开多各个位置收银台,和增加人手。那他是怎么知道人多的呢?也很简单,就是经理(Manager/Master进程或者是运维,看理解),他知道,内部调度安排人手。

大致举了这么一个例子来说明扩展的原理。

回到正题: 框架

相信大家都有接触过很多不同的框架,CI, TP, Symfony, Yii, Laravel, Slim等等,最深刻,最相似的地方在哪里呢?可能有些没有,但是,有一点可以肯定的,就是,都是有一系列 Http 封装,Route 处理。因为这两是灵魂,剩下的是不是业务和结构。

剩下的就是考验框架代码质量的时候了,这里有一系列的框架,有的轻量,有的重量,有的灵活,有的高效。其实说到这里很多朋友都大概了解框架的运行原理。

我看过Symfony、Laravel、CI、Silex和ThinkPHP的代码,当然很粗略地看看。里面实现的大部分代码都是将各个处理模块 “粘合” 一起,也就是 "Bridge"。

大致流程图:

   +----------+           +-------------+                      +------------+                          
   |          |           |             |                      |            |                          
   |  Client  |---------->| Application |--------------------->|   Start    |                          
   |          |           |             |                      |            |                          
   +----------+           +-------------+                      +------------+                          
         ^                                                            |                                
         |                                                            |                                
         |                                                            v                                
         |                         +-------------+             +-------------+                         
         |                         |             |             |             |                         
         |                         |  Container  |------------>|  Bootstrap  |-----+                   
         |                         |             |             |             |     |                   
         |                         +-------------+             +-------------+     |                   
         |                                ^                                        |     +------------+
         |                        +-------+--------+                               |     |            |
         |                        |                |                               +---->|  Request   |
         |                  +-----------+    +-----------+                               |            |
         |                  |           |    |           |                               +------------+
         |                  |   Route   |    |  Service  |                                      |      
         |                  |           |    |           |                                      |      
+----------------+          +-----------+    +-----------+       +-------------+                |      
|                |                                               |             |                |      
|    Response    |                                               | Dispatcher  |                |      
|                |<----------------------------------------------|             |<---------------+      
|                |                                               |             |                       
+----------------+                                               +-------------+                       
                                                                        ^                              
                                                                        |                              
                                                                        +--------------+               
                                                                        |              |               
                                                                        |              v               
                                                                        |        +----------+          
                                                                        |        |          |          
                                                                        +--------|Controller|          
                                                                                 |          |          
                                                                                 +----------+          

当你了解了这些流程以及所需的组建,用先用的组件的话都是可以很方便地组合出自己想要的框架。

其实我这里希望更多的初学者多看看 ThinkPHP 的代码,然后也看看其他开源框架的代码,你会发现,除了 ThinkPHP 之外,你还可以发现更多新奇好玩的东西。

最终其实还是离不开自己动手开发一个。

具体框架开发系列我会找个时间与大家分享。框架的理解可谓到一段落,下次我会分享我对其他服务器的理解。

来到这个阶段的,应该始终有一个意识:服务质量高于一切,就是不能因为添加服务而影响原有的服务

简单总结一下。大量动手实践自己的猜想,分析自己做过的项目并且优化自己觉得不足的地方。

总结: 知其然并且知其所以然

3. PHP 高手模式

我相信经过九九八十一难,能来到这个模式的人已经不多了。我自己还是菜鸟,不敢在这里胡说,这里会记录我所有的 PHP 底层学习的经过,这里的故事,我想我等不到下一个故事了。

  1. Unix 环境高级编程
  2. tcp/ip 网络编程
  3. PHP 扩展开发
  4. 颈椎病康复指南
  5. 活着

3.1 Unix 环境高级编程

为什么要理解并学习这一方面的知识?若果你是一名有追求的 PHP 开发者,最终还是应该将精力落入到 “系统” 处,因为真正处理 PHP 程序的,正正是 “系统”,如何可以让自己的 PHP 做得更好,如何可以让自己的服务做的更好,如何可以让后端支持更加强大,灵活,高效,你就应该关注到底层系统的实现当中,但平时也不要忘了 PHP 的开发规范。

此处的文章和笔记,我将会在以后的 Unix 学习一系列当中给大家呈现。

3.2 tcp/ip 网络编程

在日常生活中,Http 已经离不开大家了,从平时打开应用,打开浏览器,搜索,都是需要使用 Http,应该没有比这个接触更多了吧。但是里面的奥秘你又知道多少?没关系,和我一起探索 TCP/IP 的奥秘吧。

文章和笔记,以后会在 TCP/IP 章节中给大家呈现.

3.3 PHP 扩展开发

学习扩展开发和学习 PHP 是一样一样的,根据 PHP 手册上的流程...

  1. 语言参考
  2. 基本语法
  3. 类型
  4. 变量
  5. 常量
  6. 表达式
  7. 运算符
  8. 流程控制
  9. 函数
  10. 类与对象
  11. 命名空间
  12. Errors
  13. 异常处理
  14. 生成器
  15. 引用的解释
  16. 预定义变量
  17. 预定义异常
  18. 预定义接口
  19. 上下文(Context)选项和参数
  20. 支持的协议和封装协议

看到这里应该要懂得举一反三的了,后面的看你们的造化了......

此处的文章和笔记,我将会在以后的 PHP 扩展开发 学习一系列当中给大家呈现。

预告

我目前已经开始做了: http://blog.fastdlabs.com/tag...

查看原文

黄总 评论了文章 · 2018-07-20

我的 PHP 学习路线

我的 PHP 学习路线

1. PHP 入门

PHP 入门没啥好说的,会基本编码,基本的开发结构(通常指MVC,呵呵哒),类与对象,就差不多了,可以说是入门了。

1.1 OOP

写 PHP 最多目前无非就是 OOP,面向对象,说时迟那时快。不开玩笑地说,与我共事的某些前辈是连 OOP 都搞不清的,这里我就不多说了。

其实不是说一定要会,要去理解 OOP,只是如果你理解这个玩意,对于你后面的工作已经学习会非常的有好处。

其实面向对象也没有那么复杂,只要理解一点,单一职责,其实就是一个对象越简单越好。

也就是说,是自己该做就由自己做,不该由自己做的就不要自己做。

1.2 MVC

老梗了,所谓 MVC 很多人会说 Model, View, Controller, 其实这样说没错的,只是这样说不会让你更好地理解结构以及扩展性。

MVC 我当前的理解是:调用(度),也很简单,其他框架也差不多这个原理,当然每个框架的实现方式都不一样。

基本流程:

+--------------+      +-----------+      +--------------+                  +--------------+
|              |  ----+  request  +----> |              |  ------------>   |              |
|              |      +-----------+      |              |                  |              |
|   Request    |                         | Route Match  |                  |    Handle    |
|              |      +-----------+      |              |   +----------+   |              |
|              | <----+ Response  +----- |              | <-+ Response +-- |              |
+--------------+      +-----------+      +--------------+   +----------+   +--------------+

大致列了下最基础的框架底层原理,实际上咱们开发中 90% 接触的只是在 Handle 处的工作,至于 RequestMatchRoute 等基础的对象或者数据,框架早已经封装好了,也无需过度纠结和头疼这方面的事情,先要把业务功能处理好,并且容错处理好即可。

简单总结一句话:知其然而不知其所以然


2. PHP 进阶

进阶这个真是个头疼的问题,啥叫进阶,我的理解是,做一些之前没有做过的(指本领域:PHP),例如:设计模式,SPL,缓存设计(Cache),研究框架,开发规范,单元测试,行为驱动开发,组件(包括自己着手开发的),Composer 等等的东西,都可以理解为进阶。

框架推荐:

  1. Symfony
  2. Laravel
  3. Yaf

PHP 开发规范(PSR):

  1. PHP FIG

PHPUnit & TDD/BDD:

  1. PHPUnit
  2. PHP spec

设计模式:

  1. 设计模式

SPL:

  1. PHP SPL

Composer:

  1. Composer

欢迎补充

2.1 设计模式

设计模式,一个在软件设计中占有重要角色的课程,而我们又不得不去了解。而对于设计模式来说,很多人是抗拒的,因为他和普通的开发者有着不一样的思维方式,一个很明显的提升就是: 设计,而设计应该是根据发展的变化而变化,业务的变化而变化,模式也一样,不会是永恒不变的。唯一不变的是,基础,这些技巧与思维少不了的是需要良好的基础。

所以说,基础是多么重要的,任何一切的一切都是建立与基础之上,这叫积累。如同盖楼。

在这些已有基础,我们需要学习并且还需要学会各种推陈出新,这样才可以让自己让他人走得更远。

设计模式学习推荐: 设计模式

2.2 资源节省

当今互联网,每秒钟都是钱,能节省的,绝对不能浪费,而且节省还可以一定地提高服务的质量。

一般我们说的资源是:

  1. 内存
  2. 带宽
  3. 磁盘
  4. CPU

而这些之间其实是有一定的关联的,和代码质量和容错机制也有一定关系。

上述每一个都很重要,决定着你的服务质量。

能少占用内存就少占用内存,图片、媒体资源能压缩就压缩,减少无用的存储,降低代码的复杂度。

2.3 容错

比较常见的是: file_get_contentsconnection,有时候我们会很自然地遗忘这里其实会有一定几率出现超时,最严重的就是造成服务无响应,如下代码:

file_get_contents('https://www.google.com/');

这代码分分钟被打,活生生将程序毁了。

如果发生超时,会占用大量 CPU,严重可能会导致服务无响应,危害极大。

容错是每个开发者在开发过程中必须要考虑的地方,没有代码没有 “八阿哥”,总会有意外的地方,做好容错可以最大程度地减少对用户的伤害以及可以有效提高在出错时的用户体验。百利而无一害。

2.4 日志

日志,一个很容易被无视而又非常非常重要的环节,可以说,这一环节比你做的任何一个地方的业务代码都要重要。

日志的好处:

  1. 记录,跟踪
  2. 调试
  3. 恢复
  4. 分析
  5. 调优
  6. 等等...

好处有好多,但在我们开发者当中,其日志最重要的功能之一就是,记录问题,调试代码,优化架构。

不得不说日志的重要性,请你好好重视这一个容易被忽略的环节。

而日志的设计需要考虑性能,不能因为日志而影响服务质量哦。所以在日的环节在完整性和效率上要做好权衡。

2.5 缓存设计

缓存必须是针对业务情况而设计,不能生搬硬套。大公司的不一定适合你,开源方案也不一定不适合你,一定要找到自己合适的方案。

而在缓存设计方面,我个人推荐这一系列的文章: 缓存使用与设计

通俗简单地说,缓存的目的是为了提高服务的响应速度以及质量,不能因为缓存的添加而导致服务异常。

2.6 原理理解 (这里说到框架的研究,说得不好的地方,请多多批评和教导)

我们平时开发接触不同的开发工具,操作,甚至是监控,那么他们其中的原理,你又理解么?

其实我们每天接触的东西都有它的实现原理,算法等等的东西,但我们一直都在使用,并没有很好地去理解他们当中的奥秘。时候有空去接触一下了。

首先,开发,编码我觉得就是将现实生活搬到互联网中,我举个例子:

为什么人访问量上来了,咱们就要扩容,去扩展呢?原理很简单,看看咱们超市里面的收银台就知道了。咱们超市里面所有收银台不是每天每个位置都有人的,根据人流(流量)动态扩容,而且有些收一台的一个位置上设置有两个人(多线程/多进程,看个人理解),这个设计挺妙的。当人一多,就会开多各个位置收银台,和增加人手。那他是怎么知道人多的呢?也很简单,就是经理(Manager/Master进程或者是运维,看理解),他知道,内部调度安排人手。

大致举了这么一个例子来说明扩展的原理。

回到正题: 框架

相信大家都有接触过很多不同的框架,CI, TP, Symfony, Yii, Laravel, Slim等等,最深刻,最相似的地方在哪里呢?可能有些没有,但是,有一点可以肯定的,就是,都是有一系列 Http 封装,Route 处理。因为这两是灵魂,剩下的是不是业务和结构。

剩下的就是考验框架代码质量的时候了,这里有一系列的框架,有的轻量,有的重量,有的灵活,有的高效。其实说到这里很多朋友都大概了解框架的运行原理。

我看过Symfony、Laravel、CI、Silex和ThinkPHP的代码,当然很粗略地看看。里面实现的大部分代码都是将各个处理模块 “粘合” 一起,也就是 "Bridge"。

大致流程图:

   +----------+           +-------------+                      +------------+                          
   |          |           |             |                      |            |                          
   |  Client  |---------->| Application |--------------------->|   Start    |                          
   |          |           |             |                      |            |                          
   +----------+           +-------------+                      +------------+                          
         ^                                                            |                                
         |                                                            |                                
         |                                                            v                                
         |                         +-------------+             +-------------+                         
         |                         |             |             |             |                         
         |                         |  Container  |------------>|  Bootstrap  |-----+                   
         |                         |             |             |             |     |                   
         |                         +-------------+             +-------------+     |                   
         |                                ^                                        |     +------------+
         |                        +-------+--------+                               |     |            |
         |                        |                |                               +---->|  Request   |
         |                  +-----------+    +-----------+                               |            |
         |                  |           |    |           |                               +------------+
         |                  |   Route   |    |  Service  |                                      |      
         |                  |           |    |           |                                      |      
+----------------+          +-----------+    +-----------+       +-------------+                |      
|                |                                               |             |                |      
|    Response    |                                               | Dispatcher  |                |      
|                |<----------------------------------------------|             |<---------------+      
|                |                                               |             |                       
+----------------+                                               +-------------+                       
                                                                        ^                              
                                                                        |                              
                                                                        +--------------+               
                                                                        |              |               
                                                                        |              v               
                                                                        |        +----------+          
                                                                        |        |          |          
                                                                        +--------|Controller|          
                                                                                 |          |          
                                                                                 +----------+          

当你了解了这些流程以及所需的组建,用先用的组件的话都是可以很方便地组合出自己想要的框架。

其实我这里希望更多的初学者多看看 ThinkPHP 的代码,然后也看看其他开源框架的代码,你会发现,除了 ThinkPHP 之外,你还可以发现更多新奇好玩的东西。

最终其实还是离不开自己动手开发一个。

具体框架开发系列我会找个时间与大家分享。框架的理解可谓到一段落,下次我会分享我对其他服务器的理解。

来到这个阶段的,应该始终有一个意识:服务质量高于一切,就是不能因为添加服务而影响原有的服务

简单总结一下。大量动手实践自己的猜想,分析自己做过的项目并且优化自己觉得不足的地方。

总结: 知其然并且知其所以然

3. PHP 高手模式

我相信经过九九八十一难,能来到这个模式的人已经不多了。我自己还是菜鸟,不敢在这里胡说,这里会记录我所有的 PHP 底层学习的经过,这里的故事,我想我等不到下一个故事了。

  1. Unix 环境高级编程
  2. tcp/ip 网络编程
  3. PHP 扩展开发
  4. 颈椎病康复指南
  5. 活着

3.1 Unix 环境高级编程

为什么要理解并学习这一方面的知识?若果你是一名有追求的 PHP 开发者,最终还是应该将精力落入到 “系统” 处,因为真正处理 PHP 程序的,正正是 “系统”,如何可以让自己的 PHP 做得更好,如何可以让自己的服务做的更好,如何可以让后端支持更加强大,灵活,高效,你就应该关注到底层系统的实现当中,但平时也不要忘了 PHP 的开发规范。

此处的文章和笔记,我将会在以后的 Unix 学习一系列当中给大家呈现。

3.2 tcp/ip 网络编程

在日常生活中,Http 已经离不开大家了,从平时打开应用,打开浏览器,搜索,都是需要使用 Http,应该没有比这个接触更多了吧。但是里面的奥秘你又知道多少?没关系,和我一起探索 TCP/IP 的奥秘吧。

文章和笔记,以后会在 TCP/IP 章节中给大家呈现.

3.3 PHP 扩展开发

学习扩展开发和学习 PHP 是一样一样的,根据 PHP 手册上的流程...

  1. 语言参考
  2. 基本语法
  3. 类型
  4. 变量
  5. 常量
  6. 表达式
  7. 运算符
  8. 流程控制
  9. 函数
  10. 类与对象
  11. 命名空间
  12. Errors
  13. 异常处理
  14. 生成器
  15. 引用的解释
  16. 预定义变量
  17. 预定义异常
  18. 预定义接口
  19. 上下文(Context)选项和参数
  20. 支持的协议和封装协议

看到这里应该要懂得举一反三的了,后面的看你们的造化了......

此处的文章和笔记,我将会在以后的 PHP 扩展开发 学习一系列当中给大家呈现。

预告

我目前已经开始做了: http://blog.fastdlabs.com/tag...

查看原文

黄总 评论了文章 · 2018-07-08

fastd3.2 稳定版发布

继3.1版本之后,经过半年断断续续的迭代,现在3.2版本终于迎来第一个稳定版,未来会继续对其进行研发,除了本身的功能特性外,还会对其能够提供的体系,生态进行完善。

新特性

  • 新增进程管理命令,新增 process.php 配置文件。支持自定义命令,守护进程。
  • 新增 FastDLoggerFormatterStashForamtter 日志格式,支持 logstash。点击前往: 教程
  • 新增 FastDServiceProviderMoltenServiceProvider,支持 zipkin 调用链。点击前往: 教程
  • 替换 migration 为 fastd/migration
  • 新增 version,forward 等辅助函数
  • 新增 mysql 查询构建器
  • 恢复时区配置
  • 完善周边服务

移除

  • 移除 basic auth 默认依赖,扩展成服务提供器
  • 移除 cache middleware 默认依赖,扩展成服务提供器

Bug修复

  • 修复 ArrayObject merge 覆盖的 bug
  • 修复错误与异常无法显示的bug

除了新增了部分功能之外,完善开发体验外,更加支持了其他组件的兼容,完善了周边的服务。

方向

fastd 给人的感觉仅仅是一个PHP框架,但是我想除了,框架,我们还可以分享更多,于是在2017年我们实践了一套结合fastd的一套开发体系,也是我们未来发展的一个方向。

clipboard.png

虽然说PHP能做的事情有限,但是结合其他工具一起去做,那就有无限的可能。我做框架不仅仅是想提供一个开发的工具,更像提供一个从开发开始,到部署,监控一个体系下来的解决方案,就算不能很好解决问题,也能提供个思路摸索。

也希望业界各个兄弟能够指出产品的不足以及建议.

查看原文

黄总 评论了文章 · 2018-06-27

fastd3.2 稳定版发布

继3.1版本之后,经过半年断断续续的迭代,现在3.2版本终于迎来第一个稳定版,未来会继续对其进行研发,除了本身的功能特性外,还会对其能够提供的体系,生态进行完善。

新特性

  • 新增进程管理命令,新增 process.php 配置文件。支持自定义命令,守护进程。
  • 新增 FastDLoggerFormatterStashForamtter 日志格式,支持 logstash。点击前往: 教程
  • 新增 FastDServiceProviderMoltenServiceProvider,支持 zipkin 调用链。点击前往: 教程
  • 替换 migration 为 fastd/migration
  • 新增 version,forward 等辅助函数
  • 新增 mysql 查询构建器
  • 恢复时区配置
  • 完善周边服务

移除

  • 移除 basic auth 默认依赖,扩展成服务提供器
  • 移除 cache middleware 默认依赖,扩展成服务提供器

Bug修复

  • 修复 ArrayObject merge 覆盖的 bug
  • 修复错误与异常无法显示的bug

除了新增了部分功能之外,完善开发体验外,更加支持了其他组件的兼容,完善了周边的服务。

方向

fastd 给人的感觉仅仅是一个PHP框架,但是我想除了,框架,我们还可以分享更多,于是在2017年我们实践了一套结合fastd的一套开发体系,也是我们未来发展的一个方向。

clipboard.png

虽然说PHP能做的事情有限,但是结合其他工具一起去做,那就有无限的可能。我做框架不仅仅是想提供一个开发的工具,更像提供一个从开发开始,到部署,监控一个体系下来的解决方案,就算不能很好解决问题,也能提供个思路摸索。

也希望业界各个兄弟能够指出产品的不足以及建议.

查看原文

黄总 发布了文章 · 2018-03-12

fastd3.2 稳定版发布

继3.1版本之后,经过半年断断续续的迭代,现在3.2版本终于迎来第一个稳定版,未来会继续对其进行研发,除了本身的功能特性外,还会对其能够提供的体系,生态进行完善。

新特性

  • 新增进程管理命令,新增 process.php 配置文件。支持自定义命令,守护进程。
  • 新增 FastDLoggerFormatterStashForamtter 日志格式,支持 logstash。点击前往: 教程
  • 新增 FastDServiceProviderMoltenServiceProvider,支持 zipkin 调用链。点击前往: 教程
  • 替换 migration 为 fastd/migration
  • 新增 version,forward 等辅助函数
  • 新增 mysql 查询构建器
  • 恢复时区配置
  • 完善周边服务

移除

  • 移除 basic auth 默认依赖,扩展成服务提供器
  • 移除 cache middleware 默认依赖,扩展成服务提供器

Bug修复

  • 修复 ArrayObject merge 覆盖的 bug
  • 修复错误与异常无法显示的bug

除了新增了部分功能之外,完善开发体验外,更加支持了其他组件的兼容,完善了周边的服务。

方向

fastd 给人的感觉仅仅是一个PHP框架,但是我想除了,框架,我们还可以分享更多,于是在2017年我们实践了一套结合fastd的一套开发体系,也是我们未来发展的一个方向。

clipboard.png

虽然说PHP能做的事情有限,但是结合其他工具一起去做,那就有无限的可能。我做框架不仅仅是想提供一个开发的工具,更像提供一个从开发开始,到部署,监控一个体系下来的解决方案,就算不能很好解决问题,也能提供个思路摸索。

也希望业界各个兄弟能够指出产品的不足以及建议.

查看原文

赞 1 收藏 0 评论 4

黄总 收藏了文章 · 2018-02-23

面试的信心来源于过硬的基础

在过去的一年很多人不满于公司没有福利、人际关系不好相处、没有发展前途的境遇等等,想着在开年来换一份工作来重新开始自己,那么 你 准备好了吗?

下面是本人整理的一份面试材料,本想自己用的,但是新年第一天 公司突然给了我个惊喜,涨工资了!!!

1、 viewport

    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
    // width    设置viewport宽度,为一个正整数,或字符串‘device-width’
    // device-width  设备宽度
    // height   设置viewport高度,一般设置了宽度,会自动解析出高度,可以不用设置
    // initial-scale    默认缩放比例(初始缩放比例),为一个数字,可以带小数
    // minimum-scale    允许用户最小缩放比例,为一个数字,可以带小数
    // maximum-scale    允许用户最大缩放比例,为一个数字,可以带小数
    // user-scalable    是否允许手动缩放

延伸 提问

怎样处理 移动端 1px 被 渲染成 2px 问题


    1 局部处理
        meta标签中的 viewport属性 ,initial-scale 设置为 1 
        rem 按照设计稿标准走,外加利用transfrome 的scale(0.5) 缩小一倍即可;
    2 全局处理
        meta标签中的 viewport属性 ,initial-scale 设置为 0.5
        rem 按照设计稿标准走即可

2、跨域的几种方式

首先了解下浏览器的同源策略
同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

那么怎样解决跨域问题的呢?

    1 通过jsonp跨域
        1.)原生实现:
         <script>
            var script = document.createElement('script');
            script.type = 'text/javascript';
        
            // 传参并指定回调执行函数为onBack
            script.src = 'http://www.....:8080/login?user=admin&callback=onBack';
            document.head.appendChild(script);
        
            // 回调执行函数
            function onBack(res) {
                alert(JSON.stringify(res));
            }
         </script>
    2、 document.domain + iframe跨域  
        此方案仅限主域相同,子域不同的跨域应用场景。
        1.)父窗口:(http://www.domain.com/a.html)

            <iframe id="iframe" data-original="http://child.domain.com/b.html"></iframe>
            <script>
                document.domain = 'domain.com';
                var user = 'admin';
            </script>
            2.)子窗口:(http://child.domain.com/b.html)
            
            <script>
                document.domain = 'domain.com';
                // 获取父窗口中变量
                alert('get js data from parent ---> ' + window.parent.user);
            </script>

        弊端:请看下面渲染加载优化

    3、 nginx代理跨域
    4、 nodejs中间件代理跨域
    5、 后端在头部信息里面设置安全域名
    
    更多跨域的具体内容请看  https://segmentfault.com/a/1190000011145364
    

3、 渲染优化

    1.禁止使用iframe(阻塞父文档onload事件);
        *iframe会阻塞主页面的Onload事件;
        *搜索引擎的检索程序无法解读这种页面,不利于SEO;
        *iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载。

        使用iframe之前需要考虑这两个缺点。如果需要使用iframe,最好是通过javascript
        动态给iframe添加src属性值,这样可以绕开以上两个问题。

    2.禁止使用gif图片实现loading效果(降低CPU消耗,提升渲染性能);
    3、使用CSS3代码代替JS动画(尽可能避免重绘重排以及回流);
    4、对于一些小图标,可以使用base64位编码,以减少网络请求。但不建议大图使用,比较耗费CPU;
            小图标优势在于:
                1.减少HTTP请求;
                2.避免文件跨域;
                3.修改及时生效;

    5、页面头部的<style></style> 会阻塞页面;(因为 Renderer进程中 JS线程和渲染线程是互斥的);
    6、页面头部<script</script> 会阻塞页面;(因为 Renderer进程中 JS线程和渲染线程是互斥的);
    7、页面中空的 href 和 src 会阻塞页面其他资源的加载 (阻塞下载进程);
    
    8、网页Gzip,CDN托管,data缓存 ,图片服务器;
    9、前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
    10、用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
    11、当需要设置的样式很多时设置className而不是直接操作style。
    12、少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。
    13、避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。
    14、图片预加载,将样式表放在顶部,将脚本放在底部  加上时间戳。

    15、 避免在页面的主体布局中使用table,table要等其中的内容完全下载之后才会显示出来,显示比div+css布局慢。
        对普通的网站有一个统一的思路,就是尽量向前端优化、减少数据库操作、减少磁盘IO。
            向前端优化指的是,在不影响功能和体验的情况下,能在浏览器执行的不要在服务端执行,
            能在缓存服务器上直接返回的不要到应用服务器,程序能直接取得的结果不要到外部取得,
            本机内能取得的数据不要到远程取,内存能取到的不要到磁盘取,缓存中有的不要去数据库查询。
            减少数据库操作指减少更新次数、缓存结果减少查询次数、将数据库执行的操作尽可能的让你的程序完成(例如join查询),
            减少磁盘IO指尽量不使用文件系统作为缓存、减少读写文件次数等。程序优化永远要优化慢的部分,换语言是无法“优化”的。
            

4、事件的各个阶段

1:捕获阶段 ---> 2:目标阶段 ---> 3:冒泡阶段
document   ---> target目标 ----> document

由此,addEventListener的第三个参数设置为true和false的区别已经非常清晰了:

true表示该元素在事件的“捕获阶段”(由外往内传递时)响应事件;

false表示该元素在事件的“冒泡阶段”(由内向外传递时)响应事件。

5、let var const

let 允许你声明一个作用域被限制在块级中的变量、语句或者表达式
    let绑定不受变量提升的约束,这意味着let声明不会被提升到当前
    该变量处于从块开始到初始化处理的“暂存死区”。

var 声明变量的作用域限制在其声明位置的上下文中,而非声明变量总是全局的
    由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明
    
const 声明创建一个值的只读引用 (即指针)
    这里就要介绍下 JS 常用类型 
    String、Number、Boolean、Array、Object、Null、Undefined
    其中基本类型 有 Undefined、Null、Boolean、Number、String,保存在栈中;
    复合类型 有 Array、Object ,保存在堆中;
    
    基本数据当值发生改变时,那么其对应的指针也将发生改变,故造成 const申明基本数据类型时,
    再将其值改变时,将会造成报错, 例如 const a = 3 ; a = 5 时 将会报错;
    但是如果是复合类型时,如果只改变复合类型的其中某个Value项时, 将还是正常使用;

6、箭头函数

    语法比函数表达式更短,并且不绑定自己的this,arguments,super或 new.target。这些函数表达式最适合用于非方法函数,并且它们不能用作构造函数。
    

7、快速的让一个数组乱序

    var arr = [1,2,3,4,5,6,7,8,9,10];
    arr.sort(function(){
        return Math.random() - 0.5;
    })
    console.log(arr);

此处解释:(语言组织能力不足,请勿吐槽)

首先: 当return 的值

    小于 0 ,那么 a 会被排列到 b 之前;
    等于 0 , a 和 b 的相对位置不变;
    大于 0 , b 会被排列到 a 之前;

这里你会 发现起始 的时候数组是正序排列,每当进行一次排列的时候, 都会先随机一个随机数 
(注意这里的每一次排列 指 每一个红框指一次排列, 共9次排列 , 一次排列中可能存在多次比较);

当一次排列的 随机数大于0.5 时 将会进行第二次比较, 当第二次随机数 仍然大于0.5 时 ,
    将会再 进行一次比较, 直到 随机数大于0.5 或者排列到第一位;

当一次排列的 随机数 小于0.5时 当前比较的两项 索引将不会改变 ,继续下一次 的排列;

8、字体font-family

    @ 宋体      SimSun
    @ 黑体      SimHei
    @ 微信雅黑   Microsoft Yahei
    @ 微软正黑体 Microsoft JhengHei
    @ 新宋体    NSimSun
    @ 新细明体  MingLiU
    @ 细明体    MingLiU
    @ 标楷体    DFKai-SB
    @ 仿宋     FangSong
    @ 楷体     KaiTi
    @ 仿宋_GB2312  FangSong_GB2312
    @ 楷体_GB2312  KaiTi_GB2312  
    @
    @ 说明:中文字体多数使用宋体、雅黑,英文用Helvetica
    
    body { font-family: Microsoft Yahei,SimSun,Helvetica; } 

9、可能用到的meta标签

    
    <!-- 设置缩放 -->
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui" />
    <!-- 可隐藏地址栏,仅针对IOS的Safari(注:IOS7.0版本以后,safari上已看不到效果) -->
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <!-- 仅针对IOS的Safari顶端状态条的样式(可选default/black/black-translucent ) -->
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    <!-- IOS中禁用将数字识别为电话号码/忽略Android平台中对邮箱地址的识别 -->
    <meta name="format-detection"content="telephone=no, email=no" />

    其他meta标签
    <!-- 启用360浏览器的极速模式(webkit) -->
    <meta name="renderer" content="webkit">
    <!-- 避免IE使用兼容模式 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 -->
    <meta name="HandheldFriendly" content="true">
    <!-- 微软的老式浏览器 -->
    <meta name="MobileOptimized" content="320">
    <!-- uc强制竖屏 -->
    <meta name="screen-orientation" content="portrait">
    <!-- QQ强制竖屏 -->
    <meta name="x5-orientation" content="portrait">
    <!-- UC强制全屏 -->
    <meta name="full-screen" content="yes">
    <!-- QQ强制全屏 -->
    <meta name="x5-fullscreen" content="true">
    <!-- UC应用模式 -->
    <meta name="browsermode" content="application">
    <!-- QQ应用模式 -->
    <meta name="x5-page-mode" content="app">
    <!-- windows phone 点击无高光 -->
    <meta name="msapplication-tap-highlight" content="no">

10、消除transition闪屏

    .css {
        -webkit-transform-style: preserve-3d;
        -webkit-backface-visibility: hidden;
        -webkit-perspective: 1000;
    }
    过渡动画(在没有启动硬件加速的情况下)会出现抖动的现象, 以上的 解决方案只是改变 视角 来启动硬件加速的一种方式;
    启动硬件加速的 另外一种方式: 
        .css {
            -webkit-transform: translate3d(0,0,0);
            -moz-transform: translate3d(0,0,0);
            -ms-transform: translate3d(0,0,0);
            transform: translate3d(0,0,0);
        }
    
    启动硬件加速
    最常用的方式:translate3d、translateZ、transform

    opacity属性/过渡动画(需要动画执行的过程中才会创建合成层,动画没有开始或结束后元素还会回到之前的状态)

    will-chang属性(这个比较偏僻),一般配合opacity与translate使用(而且经测试,除了上述可以引发硬件加速的属性外,
    其它属性并不会变成复合层),

    弊端: 硬件加速会导致 CPU性能占用量过大,电池电量消耗加大 ;因此 尽量避免泛滥使用硬件加速。

11、android 4.x bug

    1.三星 Galaxy S4中自带浏览器不支持border-radius缩写
    2.同时设置border-radius和背景色的时候,背景色会溢出到圆角以外部分
    3.部分手机(如三星),a链接支持鼠标:visited事件,也就是说链接访问后文字变为紫色
    4.android无法同时播放多音频audio
    5.oppo 的border-radius 会失效

12、JS 判断设备来源

    function deviceType(){
        var ua = navigator.userAgent;
        var agent = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];    
        for(var i=0; i<len,len = agent.length; i++){
            if(ua.indexOf(agent[i])>0){         
                break;
            }
        }
    }
    deviceType();
    window.addEventListener('resize', function(){
        deviceType();
    })


    微信的 有些不太一样
    function isWeixin(){
        var ua = navigator.userAgent.toLowerCase();
        if(ua.match(/MicroMessenger/i)=='micromessenger'){
            return true;
        }else{
            return false;
        }
    }

13、audio元素和video元素在ios和andriod中无法自动播放

    
    原因: 因为各大浏览器都为了节省流量,做出了优化,在用户没有行为动作时(交互)不予许自动播放;

    /音频,写法一
    <audio data-original="music/bg.mp3" autoplay loop controls>你的浏览器还不支持哦</audio>
    
    //音频,写法二
    <audio controls="controls"> 
        <source data-original="music/bg.ogg" type="audio/ogg"></source>
        <source data-original="music/bg.mp3" type="audio/mpeg"></source>
        优先播放音乐bg.ogg,不支持在播放bg.mp3
    </audio>
    
    //JS绑定自动播放(操作window时,播放音乐)
    $(window).one('touchstart', function(){
        music.play();
    })
    
    //微信下兼容处理
    document.addEventListener("WeixinJSBridgeReady", function () {
        music.play();
    }, false);
    
    //小结
    //1.audio元素的autoplay属性在IOS及Android上无法使用,在PC端正常;
    //2.audio元素没有设置controls时,在IOS及Android会占据空间大小,而在PC端Chrome是不会占据任何空间;
    //3.注意不要遗漏微信的兼容处理需要引用微信JS;

14、css实现单行文本溢出显示 ...

直接上效果:相对于多行文本溢出做处理, 单行要简单多,且更容易理解。

实现方法

overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
当然还需要加宽度width属来兼容部分浏览。

15、实现多行文本溢出显示...

效果:

实现方法:

display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;

适用范围:

因使用了WebKit的CSS扩展属性,该方法适用于WebKit浏览器及移动端;

注:

1、-webkit-line-clamp用来限制在一个块元素显示的文本的行数。 为了实现该效果,它需要组合其他的WebKit属性。常见结合属性:
2、display: -webkit-box; 必须结合的属性 ,将对象作为弹性伸缩盒子模型显示 。
3、-webkit-box-orient 必须结合的属性 ,设置或检索伸缩盒对象的子元素的排列方式 。

如果你觉着这样还不够美观, 那么就接着往下看:

效果:

这样 是不是你想要的呢?

实现方法:

div {
    position: relative;
    line-height: 20px;
    max-height: 40px;
    overflow: hidden;
}

div:after {
    content: "..."; position: absolute; bottom: 0; right: 0; padding-left: 40px;
    background: -webkit-linear-gradient(left, transparent, #fff 55%);
    background: -o-linear-gradient(right, transparent, #fff 55%);
    background: -moz-linear-gradient(right, transparent, #fff 55%);
    background: linear-gradient(to right, transparent, #fff 55%);
}

不要只顾着吃,要注意胃口,此方法有个弊端 那就是 【未超出行的情况下也会出现省略号】 ,这样会不会很挫!!! 没办法,只能结合JS 进行优化该方法了。

注:


1、将height设置为line-height的整数倍,防止超出的文字露出。
2、给p::after添加渐变背景可避免文字只显示一半。
3、由于ie6-7不显示content内容,所以要添加标签兼容ie6-7(如:<span>…<span/>);兼容ie8需要将::after替换成:after。

16、让图文不可复制

这点应该大家 都很熟悉了, 某些时候【你懂的】为了快捷搜索答案,可是打死也不让你复制

-webkit-user-select: none; 
-ms-user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
user-select: none;

那有些网页为了尊重原创,复制的文本 都会被加上一段来源说明,是如何做到的呢?问的好! 等的就是你这个问题 -_- 。

大致思路:


1、答案区域监听copy事件,并阻止这个事件的默认行为。
2、获取选中的内容(window.getSelection())加上版权信息,然后设置到剪切板(clipboarddata.setData())。

17、盒子垂直水平居中

这个问题好像面试必问的吔!反正我是必问的,哈哈!!! 其实无关多少种实现思路,只要你能实现就可以!

提供4种方法

1、定位 盒子宽高已知, position: absolute; left: 50%; top: 50%; margin-left:-自身一半宽度; margin-top: -自身一半高度;

2、table-cell布局 父级 display: table-cell; vertical-align: middle;  子级 margin: 0 auto;

3、定位 + transform ; 适用于 子盒子 宽高不定时; (这里是本人常用方法)
    
    position: relative / absolute;
    /*top和left偏移各为50%*/
       top: 50%;
       left: 50%;
    /*translate(-50%,-50%) 偏移自身的宽和高的-50%*/
    transform: translate(-50%, -50%); 注意这里启动了3D硬件加速哦 会增加耗电量的 (至于何是3D加速 请看浏览器进程与线程篇)

4、flex 布局
    父级: 
        /*flex 布局*/
        display: flex;
        /*实现垂直居中*/
        align-items: center;
        /*实现水平居中*/
        justify-content: center;

再加一种水平方向上居中 :margin-left : 50% ; transform: translateX(-50%);

18、改变placeholder的字体颜色大小

其实这个方法也就在PC端可以,真机上屁用都没有,当时我就哭了。 但 还是贴出来吧

input::-webkit-input-placeholder { 
    /* WebKit browsers */ 
    font-size:14px;
    color: #333;
} 
input::-moz-placeholder { 
    /* Mozilla Firefox 19+ */ 
    font-size:14px;
    color: #333;
} 
input:-ms-input-placeholder { 
    /* Internet Explorer 10+ */ 
    font-size:14px;
    color: #333;
}

19、最快捷的数组求最大值

    var arr = [ 1,5,1,7,5,9];
    Math.max(...arr)  // 9 

20、更短的数组去重写法

    [...new Set([2,"12",2,12,1,2,1,6,12,13,6])]
    
    // [2, "12", 12, 1, 6, 13]

21、 vue 父子组件嵌套时,组件内部的各个生命周期钩子触发先后顺序

首先 我们可以把 子组件当做function函数来看待,当父组件 import 子组件的时候, 就当是声明了 并加载了这个函数,
在调用的时候才会去执行这个函数(子组件)。那么父子组件中的各个声明周期钩子触发的先后顺序是怎样的呢?
如下图:

下图带222 的 是为子组件,所以一次顺序是为 先创建父组件,然后才穿件子组件,当子组件创建完成并且实体dom挂载完成后父组件才挂载完成

注:资源来源于自己长期收集整理而来,如有和其他网站和论坛相同部分,在此抱歉!

查看原文

黄总 赞了文章 · 2018-02-03

Ant Design Pro 上手备忘录

本文基于 Ant Design Pro 1.1.0 版本,参考前请注意版本信息。

Ant Design Pro 是蚂蚁金服团队在 Ant Design 的设计规范与组件库基础上推出的一套 React 实现的企业级中后台前端/设计解决方案。

上手

使用方法是直接 clone 其 GitHub 仓库然后执行 npm install,或是安装官方提供的 cli 工具创建项目(但在这过程中也会涉及到 clone 其 GitHub 仓库)。新项目创建后,自带模板页面和工具链,可以快速更改。

git clone --depth=1 https://github.com/ant-design/ant-design-pro.git my-project
cd my-project
npm install

对于开发者而言,要做的当然是将项目快速适配自己的需求。官方提供了中文文档,但其中内容组织较为零碎。在这里和大家简单地以示例页面中的标准列表为例子,做一个整理,希望能帮助到大家快速上手这个框架。

官方示例中的code标准列表/code

安装完成后,我们运行 npm run start 来启动本地开发服务器,稍等片刻脚本就会自动完成打包。Ant Design Pro 默认通过只需浏览器单方面就可处理的 HashHistory 来完成路由。如果要切换为 BrowserHistory,那在 src/index.js 中也有对应的内容可以直接修改,但需要在后端服务器进行相应路由配置。

从路由到组件

我们在左侧的导航栏点击 列表页 > 标准列表 后,可以进入到上面截图所示的页面。导航栏的内容在 src/common/menu.js 中,

/* 导航栏记录
 * src/common/menu.js
 */

{
  name: '列表页',
  icon: 'table',
  path: 'list',
  children: [{
    name: '查询表格',
    path: 'table-list',
  }, {
    name: '标准列表',
    path: 'basic-list',
  }
  ...],
}

全局的路由关系是这样一个走向:src/index.js 中通过 app.router(require('./router').default);,将 src/router.js 绑定到 dva 实例的 router 方法上。而在 src/router.js 中又引入了 src/common/router.js 中的 getRouterData 作为数据源。如果有点绕,不太能一下子看明白,那就直接记下面的结论:

因而,src/common/menu.jspath 所指向的路径对应于 src/common/router.js 中的路由记录。

/* 路由记录
 * src/common/router.js
 */

export const getRouterData = (app) => {
  const routerConfig = {
    ...,
    '/list/basic-list': {
      component: dynamicWrapper(app, ['list'], () => import('../routes/List/BasicList')),
    },
    ...,
  };
  ...
}

这里调用了同文件内的 lazy-loading 的动态加载函数 dynamicWrapper,有 3 个参数,app 为全局 dva 实例,models 为一个带有相关 dva Model 1 的 Array,component 即为该路由记录对应的实际组件。

const dynamicWrapper = (app, models, component) => {...};

顺藤摸瓜,我们打开 src/routes/List/BasicList.js,开始考察具体组件。

import React, { PureComponent } from 'react';
import { connect } from 'dva';
import PageHeaderLayout from '../../layouts/PageHeaderLayout';

@connect(({ list, loading }) => ({
  list,
  loading: loading.models.list,
}))
export default class BasicList extends PureComponent {
  componentDidMount() {
    this.props.dispatch({
      type: 'list/fetch',
      payload: {
        count: 5,
      },
    });
  }

  render() {
    return (
      <PageHeaderLayout>{/* 具体页面内容 */}</PageHeaderLayout>
    );
  }
}

@connect 装饰器

首先的组件写法中调用了 dva 所封装的 react-redux@connect 装饰器,用来接收绑定的 list 这个 model 对应的 redux store。注意到这里的装饰器实际除了 app.state.list 以外还实际接收 app.state.loading 作为参数,这个 loading 的来源是 src/index.js 中调用的 dva-loading2 这个插件。

/*
* src/index.js
*/
import createLoading from 'dva-loading';
app.use(createLoading());

它返回的信息包含了 global、model 和 effect 的异步加载完成情况。

{
  "global": true,
  "models": {
    "list": false,
    "user": true,
    "rule": false
  },
  "effects": {
    "list/fetch": false,
    "user/fetchCurrent": true,
    "rule/fetch": false
  }
}

我们注意到在这里带上 {count: 5} 这个 payload 向 store 进行了一个类型为 list/fetch 的 dispatch,那我们到 src/models/list.js 中就可以找到具体的对应操作。

import { queryFakeList } from '../services/api';

export default {
  namespace: 'list',

  state: {
    list: [],
  },

  effects: {
    *fetch({ payload }, { call, put }) {
      const response = yield call(queryFakeList, payload);
      yield put({
        type: 'queryList',
        payload: Array.isArray(response) ? response : [],
      });
    },
    /* ... */
  },

  reducers: {
    queryList(state, action) {
      return {
        ...state,
        list: action.payload,
      };
    },
    /* ... */
  },
};

后端模拟数据

通过上面的分析,我们可以看到 list/fetch 会造成带上 payload 的对 src/services/apiqueryFakeList 的一次异步请求。

export async function queryFakeList(params) {
  return request(`/api/fake_list?${stringify(params)}`);
}

走到这一步的时候,后端交互开始产生了。我们退到根目录下的 .roadhogrc.mock.js 这个文件。Ant Design Pro 直接沿用了 roadhog 中自带的 mock 功能,在这里我们简单搜索一下就能看到具体的 mock 转发配置。

import { getActivities, getNotice, getFakeList } from './mock/api';

const proxy = {
  // ...,
  'GET /api/fake_list': getFakeList,
};

那我们转进 mock/api.js 就可以看到 JSON 内容的生成了。

在开发环境中,前后端开发服务器常常部署在 localhost 的不同端口,这个问题常常困扰前后端分离范式的开发者。但有了 roadhog 之后,对上述的 .roadhogrc.mock.js 稍做修改就可以在前端的开发服务器上“构建”一个本地反代,轻松避免这个问题。

本地开发中的跨域问题

大多数浏览器要求 fetch 通过 HTTPS 进行,但对 localhost 有本地赦免,HTTP 下的 fetch 请求并不会遇到问题。(但是如果你给 localhost 做了 hosts 规则那本地开发赦免就不适用了。)

另外,对于本地,浏览器依旧强制执行 CORS 跨域检查,后端端口如果不设置 Access-Control-Allow-Origin 响应头依旧会遇到跨域安全问题。roadhog 提供的这个功能就良好解决了本地开发调试的跨域问题。

// FROM https://github.com/sorrycc/roadhog#proxy
"proxy": {
  "/api": {
    "target": "http://localhost:8080",
    "changeOrigin": true,
    "pathRewrite": { "^/api" : "" }
  }
}

结语

create-react-app 预先配置了基本的工具链,让我们能很快上手纯前端的项目。而 Ant Design Pro 这个脚手架预先配置了更为完整的开发工具链,让我们能快速进行前后端交互的开发。上手的主要难点是理解庞大的工程结构,以及了解更为庞大的依赖链。

作者水平有限,如有纰漏请尽管指出。


  1. 关于 dva 中 Model 的概念,可以参见 Andt Design 项目实践 — 定义 Model,以及 关于dva实际应用的一些经验以及疑惑
  2. 关于 dva-loading,可见 dva-loading 实践用法
查看原文

赞 28 收藏 46 评论 3

认证与成就

  • 获得 130 次点赞
  • 获得 12 枚徽章 获得 0 枚金徽章, 获得 3 枚银徽章, 获得 9 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

  • FastD

    高性能API开发框架

注册于 2013-12-06
个人主页被 2.3k 人浏览