Git Product home page Git Product logo

annewanghy.github.io's Introduction

Hi there 👋👋👋

  • 😃 Who am I : My name is anne wang, I'm a girl 👩🏼, my chinese name is WangHuiying 🇨🇳
  • 🧐 What I'm working on: frontend
  • 😘 What I enjoy: friends, movies, music🎻, and eat fruits🍎🍅🍐🍉🍇
  • 🎁 Stay healthy and keep studing: 🤸🚴🏌

annewanghy.github.io's People

Contributors

annewanghy avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

annewanghy.github.io's Issues

Node.js框架

原文:Koa 框架教程 - 阮一峰的网络日志
学习阮一峰对于Koa框架的心得体会:

  1. context对象, 表示一次http对话的上下文,包含context.requestcontext.response, 缩写为ctxContext.response.body是发送给用户的内容.
  2. ctx.response.type, 默认是text/plain, 可以指定返回类型,比如ctx.response.type = 'html';
  3. 指定网页模板,利用fs的读文件流, ctx.response.body = fs.createReadStream('./demos/template.html')
  4. 路由处理, ctx.request.path获取用户请求的路由; 使用koa-route模块,app.use(route.get('/', main));
  5. 静态资源,koa-static模块访问静态资源,path模块处理路径
const path = require('path');
const serve = require('koa-static');

const main = serve(path.join(__dirname));
app.use(main);
  1. 路由重定向ctx.response.redirect()
  2. 中间件middleware
const logger = (ctx, next) => {
  console.log(`${Date.now()} ${ctx.request.method} ${ctx.request.url}`);
  next();
}
app.use(logger);

像上面代码中的logger函数就叫做 "中间件"(middleware),因为它处在 HTTP RequestHTTP Response 中间,用来实现某种中间功能。app.use()用来加载中间件。
基本上,Koa 所有的功能都是通过中间件实现的。每个中间件默认接受两个参数,第一个参数是 Context 对象,第二个参数是next函数。只要调用next函数,就可以把执行权转交给下一个中间件.
8. 中间件栈middle stack, 以 "先进后出"(first-in-last-out)的顺序执行

最外层的中间件首先执行。
调用next函数,把执行权交给下一个中间件。
...
最内层的中间件最后执行。
执行结束后,把执行权交回上一层的中间件。
...
最外层的中间件收回执行权之后,执行next函数后面的代码。
  1. 异步中间件, asyncawait两个关键字
    fs.readFile是一个异步操作,必须写成await fs.readFile(),然后中间件必须写成async 函数。
const fs = require('fs.promised');
const Koa = require('koa');
const app = new Koa();

const main = async function (ctx, next) {
  ctx.response.type = 'html';
  ctx.response.body = await fs.readFile('./demos/template.html', 'utf8');
};

app.use(main);
app.listen(3000);
  1. koa-compose中间件的合成
const compose = require('koa-compose');
const middlewares = compose([logger, main]);
app.use(middlewares);
  1. 错误处理, ctx.throw(), 404错误可以通过设置ctx.response.status为404.
  2. try...catch处理错误
const handler = async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    ctx.response.status = err.statusCode || err.status || 500;
    ctx.response.body = {
      message: err.message
    };
  }
};

const main = ctx => {
  ctx.throw(500);
};

app.use(handler);
app.use(main);
  1. 监听error事件
app.on('error', (err, ctx) =>
  console.error('server error', err);
);
  1. emit手动释放error事件
const handler = async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    ctx.response.status = err.statusCode || err.status || 500;
    ctx.response.type = 'html';
    ctx.response.body = '<p>Something wrong, please contact administrator.</p>';
    ctx.app.emit('error', err, ctx);  # 释放
  }
};

const main = ctx => {
  ctx.throw(500);
};

app.on('error', function(err) {
  console.log('logging error ', err.message);
  console.log(err);
});
  1. Cookie处理,使用ctx.cookie读写Cookie
  2. 使用koa-body读取页面上的信息
const koaBody = require('koa-body');

const main = async function(ctx) {
  const body = ctx.request.body;
  if (!body.name) ctx.throw(400, '.name required');
  ctx.body = { name: body.name };
};

app.use(koaBody());
  1. koa-body获取页面内容,os取得文件目录,path获取文件路径, fs.createReadStream文件读入流, fs.createWriteStream文件写入流,pipe()管道处理,实现表单上传, 特别要注意multipart值为true
const os = require('os');
const path = require('path');
const koaBody = require('koa-body');

const main = async function(ctx) {
  const tmpdir = os.tmpdir();
  const filePaths = [];
  const files = ctx.request.body.files || {};

  for (let key in files) {
    const file = files[key];
    const filePath = path.join(tmpdir, file.name);
    const reader = fs.createReadStream(file.path);
    const writer = fs.createWriteStream(filePath);
    reader.pipe(writer);
    filePaths.push(filePath);
  }

  ctx.body = filePaths;
};

app.use(koaBody({ multipart: true }));

常用API

豆瓣电影API开发文档-https://developers.douban.com/wiki/?title=movie_v2
使用方法, 比如电影战狼-http://api.douban.com/v2/movie/subject/26363254
其中的数字就是
https://movie.douban.com/subject/26363254/?from=showing

{"rating": 
    {"max": 10, "average": 7.5, "stars": "40", "min": 0},
    "reviews_count": 6185, 
    "wish_count": 42078, 
    "douban_site": "", 
    "year": "2017", 
    "images": {
        "small": "http://img7.doubanio.com\/view\/movie_poster_cover\/ipst\/public\/p2485983612.webp", 
        "large": "http://img7.doubanio.com\/view\/movie_poster_cover\/lpst\/public\/p2485983612.webp", 
        "medium": "http://img7.doubanio.com\/view\/movie_poster_cover\/spst\/public\/p2485983612.webp"
    }, 
    "alt": "https:\/\/movie.douban.com\/subject\/26363254\/", 
    "id": "26363254", 
    "mobile_url": "https:\/\/movie.douban.com\/subject\/26363254\/mobile", "title": "\u6218\u72fc2", "do_count": null, 
    "share_url": "http:\/\/m.douban.com\/movie\/subject\/26363254", "seasons_count": null, "schedule_url": "https:\/\/movie.douban.com\/subject\/26363254\/cinema\/", 
    "episodes_count": null, 
    "countries": ["\u4e2d\u56fd\u5927\u9646"], 
    "genres": ["\u52a8\u4f5c"], 
    "collect_count": 246104, 
    "casts": [{
        "alt": "https:\/\/movie.douban.com\/celebrity\/1000525\/", 
        "avatars": {
            "small": "http://img7.doubanio.com\/img\/celebrity\/small\/39105.jpg", 
            "large": "http://img7.doubanio.com\/img\/celebrity\/large\/39105.jpg", 
            "medium": "http://img7.doubanio.com\/img\/celebrity\/medium\/39105.jpg"
        }, 
        "name": "\u5434\u4eac", 
        "id": "1000525"
    }, 
    {
        "alt": "https:\/\/movie.douban.com\/celebrity\/1100321\/", 
        "avatars": {
            "small": "http://img3.doubanio.com\/img\/celebrity\/small\/1415801312.29.jpg", 
            "large": "http://img3.doubanio.com\/img\/celebrity\/large\/1415801312.29.jpg", 
            "medium": "http://img3.doubanio.com\/img\/celebrity\/medium\/1415801312.29.jpg"
            }, 
        "name": "\u5f17\u5170\u514b\u00b7\u683c\u91cc\u7f57", 
        "id": "1100321"
    }, 
    {
        "alt": "https:\/\/movie.douban.com\/celebrity\/1274840\/", 
        "avatars": {
            "small": "http://img7.doubanio.com\/img\/celebrity\/small\/1401440361.14.jpg", 
            "large": "http://img7.doubanio.com\/img\/celebrity\/large\/1401440361.14.jpg", 
            "medium": "http://img7.doubanio.com\/img\/celebrity\/medium\/1401440361.14.jpg"
        }, 
        "name": "\u5434\u521a", 
        "id": "1274840"
    }, 
    {
        "alt": "https:\/\/movie.douban.com\/celebrity\/1031500\/", 
        "avatars": {
            "small": "http://img3.doubanio.com\/img\/celebrity\/small\/1408604480.79.jpg", 
            "large": "http://img3.doubanio.com\/img\/celebrity\/large\/1408604480.79.jpg", 
            "medium": "http://img3.doubanio.com\/img\/celebrity\/medium\/1408604480.79.jpg"
        }, 
        "name": "\u5f20\u7ff0", 
        "id": "1031500"
    }], 
    "current_season": null, 
    "original_title": "\u6218\u72fc2", 
    "summary": "\u6545\u4e8b\u53d1\u751f\u5728\u975e\u6d32\u9644\u8fd1\u7684\u5927\u6d77\u4e0a\uff0c\u4e3b\u4eba\u516c\u51b7\u950b\uff08\u5434\u4eac \u9970\uff09\u906d\u9047\u4eba\u751f\u6ed1\u94c1\u5362\uff0c\u88ab\u201c\u5f00\u9664\u519b\u7c4d\u201d\uff0c\u672c\u60f3\u6f02\u6cca\u4e00\u751f\u7684\u4ed6\uff0c\u6b63\u5f53\u4ed6\u6253\u7b97\u8fd9\u4e48\u505a\u7684\u65f6\u5019\uff0c\u4e00\u573a\u7a81\u5982\u5176\u6765\u7684\u610f\u5916\u6253\u7834\u4e86\u4ed6\u7684\u8ba1\u5212\uff0c\u7a81\u7136\u88ab\u5377\u5165\u4e86\u4e00\u573a\u975e\u6d32\u56fd\u5bb6\u53db\u4e71\uff0c\u672c\u53ef\u4ee5\u5b89\u5168\u64a4\u79bb\uff0c\u5374\u56e0\u65e0\u6cd5\u5fd8\u8bb0\u66fe\u7ecf\u4e3a\u519b\u4eba\u7684\u4f7f\u547d\uff0c\u5b64\u8eab\u72af\u9669\u51b2\u56de\u6ca6\u9677\u533a\uff0c\u5e26\u9886\u8eab\u9677\u5c60\u6740\u4e2d\u7684\u540c\u80de\u548c\u96be\u6c11\uff0c\u5c55\u5f00\u751f\u6b7b\u9003\u4ea1\u3002\u968f\u7740\u6597\u4e89\u7684\u6301\u7eed\uff0c\u4f53\u5185\u7684\u72fc\u6027\u9010\u6e10\u590d\u82cf\uff0c\u6700\u7ec8\u5b64\u8eab\u95ef\u5165\u6218\u4e71\u533a\u57df\uff0c\u4e3a\u540c\u80de\u800c\u6218\u6597\u3002", 
    "subtype": "movie", 
    "directors": [{
        "alt": "https:\/\/movie.douban.com\/celebrity\/1000525\/", 
        "avatars": {
            "small": "http://img7.doubanio.com\/img\/celebrity\/small\/39105.jpg", 
            "large": "http://img7.doubanio.com\/img\/celebrity\/large\/39105.jpg", 
            "medium": "http://img7.doubanio.com\/img\/celebrity\/medium\/39105.jpg"
        }, 
        "name": "\u5434\u4eac", 
        "id": "1000525"}
    ], 
    "comments_count": 131887, 
    "ratings_count": 239666, 
    "aka": ["\u65b0\u6218\u72fc", "\u65b0\u6218\u6b7b\u6c99\u573a", "Wolf Warriors 2"]
}

index.html

<!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">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css">
    <title>news app</title>
</head>
<body>
    <div class="container" id="app">
        <h3 class="text-center">VueNews</h3>
        <p>{{ results }}</p>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="app.js"></script>
</body>
</html>

app.js

const vm = new Vue({
    el: '#app',
    data: {
        results: {}
    },
    mounted(){
        axios.get('http://api.douban.com/v2/movie/subject/26363254')
             .then(response => {this.results = response.data})
    }
})

出现跨域错误:

XMLHttpRequest cannot load http://api.douban.com/v2/movie/subject/26363254. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

解决方法1.cors解决跨域
解决方法2: qs绕过跨域请求

命令行积累

  • 创建一个文件夹
    mkdir myblog
  • 创建一个文件
    touch index.js
  • 显示文件夹下有哪些文件
    ls
  • 重命名文件
    mv filename newfilename
  • 清屏
    clean或者ctrl + l
  • 取别名
    alias node="node --harmony"
  • 取消别名
    unalias node

筛选node进程

ps aux | grep server | grep node

查找进程

lsof -t -i:9009
kill -9 13761

正则表达式30分钟入门学习笔记

\bhi\b 完全匹配hi
\bhi\b*\blucy\b 匹配hi.........lucy(不换行)
0\d{2}-\d{8} 匹配0后面2个数字-8个数字 [0-9]
\w 匹配字母或数字或下划线或汉字等 [a-z0-9A-Z_]
\ba\w*\b 也就是a然后是任意的数字和字母\w*
\d+ 匹配 1 个或更多连续的数字
\b\w{6}\b 匹配刚好 6 个字符的单词
^\d{5,12}$匹配qq号必须是5-12位的数字
\(?0\d{2}[) -]?\d{8}匹配(010)88886666,或 022-22334455,或 02912345678?表示出现0次或1次
0\d{2}-\d{8}|0\d{3}-\d{7}, 一种是三位区号,8 位本地号 (如 010-12345678),一种是 4 位区号,7 位本地号 (0376-2233445), |表示分支条件
(\d{1,3}\.){3}\d{1,3} 匹配ip地址127.0.0.1的格式
((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)匹配正确的ip地址255.255.255.255

  • A类1.0.0.1—126.255.255.254
  • B类128.0.0.1—191.255.255.254
  • C类192.0.0.1—223.255.255.254
  • D类224.0.0.1—239.255.255.254
    \转义字符
代码 说明
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
代码 / 语法 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复 n 次
{n,} 重复 n 次或更多次
{n,m} 重复 n 到 m 次

反义

\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了 x 以外的任意字符
[^aeiou] 匹配除了 aeiou 这几个字母以外的任意字符

后向引用部分以及后面部分有点看不懂

发现了一个超级棒的GitHub开源项目-快速搭建一个静态的react网站

这是刚刚搭建好的网站
https://annewang.netlify.com/

开源项目https://github.com/gatsbyjs/gatsby

image

Install

  • npm install -g gatsby

Usage

  1. Create new Gatsby site gatsby new my-test-gatsby-site This creates the directory for your Gatsby project and adds the minimal files needed.
  2. cd my-test-gatsby-site
  3. gatsby develop — Gatsby will start a hot-reloading development server accessible at localhost:8000

发现神奇的是:

  1. 上传在github上的代码就是网站的代码,之前的hexo只是上传了生成的静态文件,导致我换了一个电脑之后,环境没有了,就不能写美美哒的博客了。
  2. 页面就是用react写的,而且我自己尝试着安装了一个react-markdown, 通过git将自己的package.json上传之后,发现服务器竟然也自动帮我安装了依赖,只是稍微慢了一会会,需要等待一会才可以看到项目
  3. 可以拥有自己的域名了,自己的服务器,自己的https,这些都是不收费的,哈哈哈哈
  4. react自己官网也使用了这个,说明这个真的做的很棒呢,一想起自己的网站用的是和官网一样的技术,就开心的飞起
  5. 滚去安装其他react依赖了,打造一个自己的静态博客现在不是梦了,而且还可以学习和实践react,何乐而不为呢!!!!

前端面试题-回答

原文

Front-end Job Interview Questions

#前端工作面试问题

Table of Contents目录

  1. General Questions常见问题
  2. HTML QuestionsHTML 相关问题
  3. CSS QuestionsCSS 相关问题
  4. JS QuestionsJS 相关问题
  5. Testing Questions测试相关问题
  6. Performance Questions效能相关问题
  7. Network Questions网络相关问题
  8. Coding Questions代码相关问题
  9. Fun Questions趣味问题

General Questions常见问题:

  • What did you learn yesterday/this week?你在昨天/本周学到了什么?
    这一周,主要将开发环境从windows迁移到ubuntu, 学习javascript的基础。

  • What excites or interests you about coding?编写代码的哪些方面能够使你兴奋或感兴趣?
    将自己的预期目标实现已经给了我很大的鼓励,如果有人夸奖的话,会更加兴奋。

  • What is a recent technical challenge you experienced and how did you solve it?你最近遇到过什么技术挑战?你是如何解决的?
    万事开头难,比如之前是如何安装ubuntu双系统,现在是如何把ubuntu改造成的开发环境,遇到困难,首先想到的就是谷歌和百度搜索,看看有没有其他人也来遇到过同样的问题,正在努力看英文文档解决问题。

  • What UI, Security, Performance, SEO, Maintainability or Technology considerations do you make while building a web application or site?在制作一个网页应用或网站的过程中,你是如何考虑其 UI、安全性、高性能、SEO、可维护性以及技术因素的?
    UI: 现在有很多,比如一开始使用的bootstrap, 到现在的elementUI, 谷歌主推的material等等作为参考。
    主要考虑,1界面美观,2配色好看,前几天看到数据,说蓝色是全世界人普遍都喜欢的颜色,即使对红绿色盲患者也是识别度最高,之前看服装搭配,也说蓝色和粉色是最搭的颜色。3对用户友好,尽量多用选择, 4提供搜索和提示功能。
    安全性:1对输入进行有效性验证,以前听说过一个新闻,有人使用单引号注册,结果导致一个系统奔溃,是因为在数据库的插入语句中,单引号和双引号还是有很大的区别。利用trim()去掉多余的空格。2身份验证,现在的国外的网站大多有机器识别的一个按钮,国内现在还是主推二维码,但是都是在验证是不是机器人,或者是爬虫等程序。3.授权,权限管理,用户权限不同,可以获得的页面也是不同的。4异常错误处理。5加密,对于密码等信息,在存入数据库之前都需要进行bcrypt等等的加密处理,防止泄露用户信息。
    高性能:1DNS负载均衡 2.HTTP重定向3. 分布式缓存redis 4.数据库扩展 5.反向代理均衡
    SEO: seo是最近才了解到事物,优化浏览器搜索,之前了解过爬虫,这个也是类似的,主要优化关键字,描述语言,合理使用h1-h6, 对图片添加alt属性,链接添加target熟悉。
    可维护:代码模块化,合理统一字段名,函数风格。

  • Talk about your preferred development environment.请谈谈你喜欢的开发环境。
    之前一直是使用Windows的系统,其实也觉得在Windows上开发蛮方便的。但是后来慢慢接触到了ubuntu, 大多数博主,比如阮一峰等等,都推荐使用ubuntu, 实验楼的开发环境都是ubuntu, 而且之前买过服务器也是linux系统,再到招聘要求也有很多心仪的公司要求是熟悉linux系统,因此这次下定决心搬迁到ubuntu了。搬过来虽然有很多问题,资料也大多是英文的,但是每天学一点,积累下来,每天都有收获,心情也很美丽。
    然后编辑器是sublime(最熟悉), vscode(最喜欢), atom(Windows上有点卡,但是很好看)
    浏览器一直是chrome. 扩展程序简直太棒了,比如jsonView等等。

  • Which version control systems are you familiar with?你最熟悉哪一套版本控制系统?
    git, 这个是我在大二开始接触的,一个人的代码,现在都托管在github上,换了电脑,配置一下开发环境就可以编码了。团队开发也利用它。减少了很多代码拷贝来拷贝去,还不知道那一份是最新的问题。常用的命令就是git add, git commit, git push origin master, 和git merge.

  • Can you describe your workflow when you create a web page? 你能描述当你制作一个网页的工作流程吗?
    首先是设计UI,设计数据库的表和字段,然后是搭建整体的框架,最后是完善里面的每一个模块,利用CSS美化每一个细节。

  • If you have 5 different stylesheets, how would you best integrate them into the site?假若你有 5 个不同的样式文件 (stylesheets), 整合进网站的最好方式是?
    看到人家的回答是文件拼合,减少HTTP请求,利用一个大的css文件将所有的小的css文件拼在一起,减少浏览器请求的延迟。这也要求每个CSS必须考虑冲突的问题,整理好命名和层级之间的关系。现在的webpack, gulp等前端自动化工具也是将这些静态资源整合在一起的。

  • Can you describe the difference between progressive enhancement and graceful degradation?你能描述渐进增强 (progressive enhancement) 和优雅降级 (graceful degradation) 之间的不同吗?
    这个之前没了解过,参考这篇文章渐进增强和优雅降级吗?[css3兼容性写法]

    .transition { /*渐进增强写法*/
      -webkit-transition: all .5s;
         -moz-transition: all .5s;
           -o-transition: all .5s;
              transition: all .5s;
    }
    .transition { /*优雅降级写法*/
              transition: all .5s;
           -o-transition: all .5s;
         -moz-transition: all .5s;
      -webkit-transition: all .5s;
    }
    

    何谓渐进增强:
    渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
    何谓优雅降级:
    优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览。

  • How would you optimize a website's assets/resources?你如何对网站的文件和资源进行优化?

    1. 尽量使用cdn来获取静态资源,2.缓存, 3 文件合并, 4. 文件压缩,谷歌之前说每一个空格金子,因此需要压缩代码,减少不必要的浪费。
  • How many resources will a browser download from a given domain at a time?浏览器同一时间可以从一个域名下载多少资源?
    浏览器并发请求数,

    • What are the exceptions?有什么例外吗?
  • Name 3 ways to decrease page load (perceived or actual load time).请说出三种减少页面加载时间的方法。(加载时间指感知的时间或者实际加载时间)

  • If you jumped on a project and they used tabs and you used spaces, what would you do?如果你参与到一个项目中,发现他们使用 Tab 来缩进代码,但是你喜欢空格,你会怎么做?

  • Describe how you would create a simple slideshow page.请写一个简单的幻灯效果页面。

  • If you could master one technology this year, what would it be?如果今年你打算熟练掌握一项新技术,那会是什么?

  • Explain the importance of standards and standards bodies.请谈谈你对网页标准和标准制定机构重要性的理解。

  • What is Flash of Unstyled Content? How do you avoid FOUC?什么是 FOUC (无样式内容闪烁)?你如何来避免 FOUC?

  • Explain what ARIA and screenreaders are, and how to make a website accessible.请解释什么是 ARIA 和屏幕阅读器 (screenreaders),以及如何使网站实现无障碍访问 (accessible)。

  • Explain some of the pros and cons for CSS animations versus JavaScript animations.请解释 CSS 动画和 JavaScript 动画的优缺点。

  • What does CORS stand for and what issue does it address?什么是跨域资源共享 (CORS)?它用于解决什么问题?

HTML Questions:HTML 相关问题:

  • What does a doctype do?doctype(文档类型) 的作用是什么?
  • What's the difference between full standards mode, almost standards mode and quirks mode?浏览器标准模式 (standards mode) 、几乎标准模式(almost standards mode)和怪异模式 (quirks mode) 之间的区别是什么?
  • What's the difference between HTML and XHTML?HTML 和 XHTML 有什么区别?
  • Are there any problems with serving pages as application/xhtml+xml?如果页面使用 'application/xhtml+xml' 会有什么问题吗?
  • How do you serve a page with content in multiple languages?如果网页内容需要支持多语言,你会怎么做?
  • What kind of things must you be wary of when design or developing for multilingual sites?在设计和开发多语言网站时,有哪些问题你必须要考虑?
  • What are data- attributes good for?使用 data- 属性的好处是什么?
  • Consider HTML5 as an open web platform. What are the building blocks of HTML5? 如果把 HTML5 看作做一个开放平台,那它的构建模块有哪些?
  • Describe the difference between a cookie, sessionStorage and localStorage.请描述 cookiessessionStoragelocalStorage 的区别。
  • Describe the difference between <script>, <script async> and <script defer>.请解释 <script><script async><script defer> 的区别。
  • Why is it generally a good idea to position CSS <link>s between <head></head> and JS <script>s just before </body>? Do you know any exceptions?为什么通常推荐将 CSS <link> 放置在 <head></head> 之间,而将 JS <script> 放置在 </body> 之前?你知道有哪些例外吗?
  • What is progressive rendering?什么是渐进式渲染 (progressive rendering)?
  • Have you used different HTML templating languages before?你用过哪些不同的 HTML 模板语言?

CSS Questions:CSS 相关问题

  • What is the difference between classes and IDs in CSS?CSS 中类 (classes) 和 ID 的区别。
  • What's the difference between "resetting" and "normalizing" CSS? Which would you choose, and why?请问 "resetting" 和 "normalizing" CSS 之间的区别?你会如何选择,为什么?
  • Describe Floats and how they work.请解释浮动 (Floats) 及其工作原理。
  • Describe z-index and how stacking context is formed.描述z-index和叠加上下文是如何形成的。
  • Describe BFC(Block Formatting Context) and how it works.请描述 BFC(Block Formatting Context) 及其如何工作。
  • What are the various clearing techniques and which is appropriate for what context?列举不同的清除浮动的技巧,并指出它们各自适用的使用场景。
  • Explain CSS sprites, and how you would implement them on a page or site.请解释 CSS sprites,以及你要如何在页面或网站中实现它。
  • What are your favourite image replacement techniques and which do you use when?你最喜欢的图片替换方法是什么,你如何选择使用。
  • How would you approach fixing browser-specific styling issues?你会如何解决特定浏览器的样式问题?
  • How do you serve your pages for feature-constrained browsers? 如何为有功能限制的浏览器提供网页?
    • What techniques/processes do you use?你会使用哪些技术和处理方法?
  • What are the different ways to visually hide content (and make it available only for screen readers)?有哪些的隐藏内容的方法 (如果同时还要保证屏幕阅读器可用呢)?
  • Have you ever used a grid system, and if so, what do you prefer?你用过栅格系统 (grid system) 吗?如果使用过,你最喜欢哪种?
  • Have you used or implemented media queries or mobile specific layouts/CSS?你用过媒体查询,或针对移动端的布局/CSS 吗?
  • Are you familiar with styling SVG?你熟悉 SVG 样式的书写吗?
  • How do you optimize your webpages for print?如何优化网页的打印样式?
  • What are some of the "gotchas" for writing efficient CSS?在书写高效 CSS 时会有哪些问题需要考虑?
  • What are the advantages/disadvantages of using CSS preprocessors?使用 CSS 预处理器的优缺点有哪些?
    • Describe what you like and dislike about the CSS preprocessors you have used.请描述你曾经使用过的 CSS 预处理器的优缺点。
  • How would you implement a web design comp that uses non-standard fonts?如果设计中使用了非标准的字体,你该如何去实现?
  • Explain how a browser determines what elements match a CSS selector.请解释浏览器是如何判断元素是否匹配某个 CSS 选择器?
  • Describe pseudo-elements and discuss what they are used for.请描述伪元素 (pseudo-elements) 及其用途。
  • Explain your understanding of the box model and how you would tell the browser in CSS to render your layout in different box models.请解释你对盒模型的理解,以及如何在 CSS 中告诉浏览器使用不同的盒模型来渲染你的布局。
  • What does * { box-sizing: border-box; } do? What are its advantages?请解释 * { box-sizing: border-box; } 的作用, 并且说明使用它有什么好处?
  • List as many values for the display property that you can remember.请罗列出你所知道的 display 属性的全部值
  • What's the difference between inline and inline-block?请解释 inline 和 inline-block 的区别?
  • What's the difference between a relative, fixed, absolute and statically positioned element?请解释 relative、fixed、absolute 和 static 元素的区别
  • The 'C' in CSS stands for Cascading. How is priority determined in assigning styles (a few examples)? How can you use this system to your advantage?CSS 中字母 'C' 的意思是叠层 (Cascading)。请问在确定样式的过程中优先级是如何决定的 (请举例)?如何有效使用此系统?
  • What existing CSS frameworks have you used locally, or in production? How would you change/improve them? 你在开发或生产环境中使用过哪些 CSS 框架?你觉得应该如何改善他们?
  • Have you played around with the new CSS Flexbox or Grid specs?请问你有尝试过 CSS Flexbox 或者 Grid 标准规格吗?
  • How is responsive design different from adaptive design?为什么响应式设计 (responsive design) 和自适应设计 (adaptive design) 不同?
  • Have you ever worked with retina graphics? If so, when and what techniques did you use?你有兼容 retina 屏幕的经历吗?如果有,在什么地方使用了何种技术?
  • Is there any reason you'd want to use translate() instead of absolute positioning, or vice-versa? And why?请问为何要使用 translate() 而非 absolute positioning,或反之的理由?为什么?

JS Questions:JS 相关问题:

  • Explain event delegation请解释事件代理 (event delegation)。
  • Explain how this works in JavaScript 请解释 JavaScript 中 this 是如何工作的。
  • Explain how prototypal inheritance works请解释原型继承 (prototypal inheritance) 的原理。
  • What do you think of AMD vs CommonJS?你怎么看 AMD vs. CommonJS?
  • Explain why the following doesn't work as an IIFE: function foo(){ }();.请解释为什么接下来这段代码不是 IIFE (立即调用的函数表达式):function foo(){ }();.
    • What needs to be changed to properly make it an IIFE?要做哪些改动使它变成 IIFE?
  • What's the difference between a variable that is: null, undefined or undeclared?描述以下变量的区别:nullundefinedundeclared
    • How would you go about checking for any of these states?该如何检测它们?
  • What is a closure, and how/why would you use one?什么是闭包 (closure),如何使用它,为什么要使用它?
  • What's a typical use case for anonymous functions?请举出一个匿名函数的典型用例?
  • How do you organize your code? (module pattern, classical inheritance?)你是如何组织自己的代码?是使用模块模式,还是使用经典继承的方法?
  • What's the difference between host objects and native objects?请指出 JavaScript 宿主对象 (host objects) 和原生对象 (native objects) 的区别?
  • Difference between: function Person(){}, var person = Person(), and var person = new Person()?请指出以下代码的区别:function Person(){}var person = Person()var person = new Person()
  • What's the difference between .call and .apply?.call.apply 的区别是什么?
  • Explain Function.prototype.bind.请解释 Function.prototype.bind
  • When would you use document.write()?在什么时候你会使用 document.write()
  • What's the difference between feature detection, feature inference, and using the UA string?请指出浏览器特性检测,特性推断和浏览器 UA 字符串嗅探的区别?
  • Explain Ajax in as much detail as possible.请尽可能详尽的解释 Ajax 的工作原理。
  • What are the advantages and disadvantages of using Ajax?使用 Ajax 都有哪些优劣?
  • Explain how JSONP works (and how it's not really Ajax).请解释 JSONP 的工作原理,以及它为什么不是真正的 Ajax。
  • Have you ever used JavaScript templating?你使用过 JavaScript 模板系统吗?
    • If so, what libraries have you used? 如有使用过,请谈谈你都使用过哪些库?
  • Explain "hoisting".请解释变量声明提升 (hoisting)。
  • Describe event bubbling.请描述事件冒泡机制 (event bubbling)。
  • What's the difference between an "attribute" and a "property"?"attribute" 和 "property" 的区别是什么?
  • Why is extending built-in JavaScript objects not a good idea?为什么扩展 JavaScript 内置对象不是好的做法?
  • Difference between document load event and document DOMContentLoaded event?请指出 document load 和 document DOMContentLoaded 两个事件的区别。
  • What is the difference between == and ===?===== 有什么不同?
  • Explain the same-origin policy with regards to JavaScript.请解释 JavaScript 的同源策略 (same-origin policy)
  • Make this work:如何实现下列代码
duplicate([1,2,3,4,5]); // [1,2,3,4,5,1,2,3,4,5]
  • Why is it called a Ternary expression, what does the word "Ternary" indicate?什么是三元表达式 (Ternary expression)?“三元 (Ternary)” 表示什么意思?
  • What is "use strict";? what are the advantages and disadvantages to using it?什么是 "use strict"; ? 使用它的好处和坏处分别是什么?
  • Create a for loop that iterates up to 100 while outputting "fizz" at multiples of 3, "buzz" at multiples of 5 and "fizzbuzz" at multiples of 3 and 5请实现一个遍历至 100 的 for loop 循环,在能被 3 整除时输出 "fizz",在能被 5 整除时输出 "buzz",在能同时被 35 整除时输出 "fizzbuzz"
  • Why is it, in general, a good idea to leave the global scope of a website as-is and never touch it?为何通常会认为保留网站现有的全局作用域 (global scope) 不去改变它,是较好的选择?
  • Why would you use something like the load event? Does this event have disadvantages? Do you know any alternatives, and why would you use those?为何你会使用 load 之类的事件 (event)?此事件有缺点吗?你是否知道其他替代品,以及为何使用它们?
  • Explain what a single page app is and how to make one SEO-friendly.请解释什么是单页应用 (single page app), 以及如何使其对搜索引擎友好 (SEO-friendly)。
  • What is the extent of your experience with Promises and/or their polyfills?
  • What are the pros and cons of using Promises instead of callbacks?使用 Promises 而非回调 (callbacks) 优缺点是什么
  • What are some of the advantages/disadvantages of writing JavaScript code in a language that compiles to JavaScript?使用一种可以编译成 JavaScript 的语言来写 JavaScript 代码有哪些优缺点?
  • What tools and techniques do you use debugging JavaScript code?你使用哪些工具和技术来调试 JavaScript 代码?
  • What language constructions do you use for iterating over object properties and array items?你会使用怎样的语言结构来遍历对象属性 (object properties) 和数组内容?
  • Explain the difference between mutable and immutable objects. 请解释可变 (mutable) 和不变 (immutable) 对象的区别。
    • What is an example of an immutable object in JavaScript?请举出 JavaScript 中一个不变性对象 (immutable object) 的例子?
    • What are the pros and cons of immutability?不变性 (immutability) 有哪些优缺点?
    • How can you achieve immutability in your own code?如何用你自己的代码来实现不变性 (immutability)?
  • Explain the difference between synchronous and asynchronous functions.请解释同步 (synchronous) 和异步 (asynchronous) 函数的区别。
  • What is event loop? 什么是事件循环 (event loop)?
    • What is the difference between call stack and task queue?请问调用栈 (call stack) 和任务队列 (task queue) 的区别是什么?
  • Explain the differences on the usage of foo between function foo() {} and var foo = function() {}解释 function foo() {}var foo = function() {} 用法的区别

Testing Questions:测试相关问题:

  • What are some advantages/disadvantages to testing your code?对代码进行测试的有什么优缺点?
  • What tools would you use to test your code's functionality?你会用什么工具测试你的代码功能?
  • What is the difference between a unit test and a functional/integration test?单元测试与功能/集成测试的区别是什么?
  • What is the purpose of a code style linting tool?代码风格 linting 工具的作用是什么?

Performance Questions:效能相关问题:

  • What tools would you use to find a performance bug in your code?你会用什么工具来查找代码中的性能问题?
  • What are some ways you may improve your website's scrolling performance?你会用什么方式来增强网站的页面滚动效能?
  • Explain the difference between layout, painting and compositing.请解释 layout、painting 和 compositing 的区别。

Network Questions:网络相关问题:

  • Traditionally, why has it been better to serve site assets from multiple domains?为什么传统上利用多个域名来提供网站资源会更有效?
  • Do your best to describe the process from the time you type in a website's URL to it finishing loading on your screen.请尽可能完整得描述从输入 URL 到整个网页加载完毕及显示在屏幕上的整个流程。
  • What are the differences between Long-Polling, Websockets and Server-Sent Events?Long-Polling、Websockets 和 Server-Sent Event 之间有什么区别?
  • Explain the following request and response headers:请描述以下 request 和 response headers:
    • Diff. between Expires, Date, Age and If-Modified-...
    • Do Not Track
    • Cache-Control
    • Transfer-Encoding
    • ETag
    • X-Frame-Options
  • What are HTTP methods? List all HTTP methods that you know, and explain them.什么是 HTTP method?请罗列出你所知道的所有 HTTP method,并给出解释。

Coding Questions:代码相关的问题:

Question: What is the value of foo?

var foo = 10 + '20';

Question: How would you make this work?

add(2, 5); // 7
add(2)(5); // 7

Question: What value is returned from the following statement?

"i'm a lasagna hog".split("").reverse().join("");

Question: What is the value of window.foo?

( window.foo || ( window.foo = "bar" ) );

*Question: What is the outcome of the two alerts below?*下面两个 alert 的结果是什么?

var foo = "Hello";
(function() {
  var bar = " World";
  alert(foo + bar);
})();
alert(foo + bar);

Question: What is the value of foo.length?

var foo = [];
foo.push(1);
foo.push(2);

Question: What is the value of foo.x?

var foo = {n: 1};
var bar = foo;
foo.x = foo = {n: 2};

*Question: What does the following code print?*下面代码的输出是什么?

console.log('one');
setTimeout(function() {
  console.log('two');
}, 0);
console.log('three');

Fun Questions:趣味问题:

  • What's a cool project that you've recently worked on?你最近写过什么的很酷的项目吗?
  • What are some things you like about the developer tools you use?在你使用的开发工具中,最喜欢哪些方面?
  • Who inspires you in the front-end community?谁使你踏足了前端开发领域?
  • Do you have any pet projects? What kind?你有什么业余项目吗?是哪种类型的?
  • What's your favorite feature of Internet Explorer?你最爱的 IE 特性是什么?
  • How do you like your coffee?你对咖啡有没有什么喜好?

ws项目学习笔记

  1. 跨域处理cors
    跨域资源共享 CORS 详解
  2. redissession搭配使用,提高node.js缓存效率
  3. node.js日志处理log4js.json
  4. express中的use, get, post, put/patch, delete的优先级比较
  5. axios处理后台数据
  6. jade前端语言的使用
  7. morgannode.js的日志处理系统, .format定义日志格式
  8. env本地和development开发环境的区别
  9. path
  10. serve-favicon的中间件,可以用于请求网页的logo
  11. 7天学会node.js

2017-12-5

postgreSQL

Install

➜  ~ createuser admin -P
Enter password for new role:
Enter it again:
➜  ~ createdb cake -O admin -E UTF8 -e
CREATE DATABASE cake OWNER admin ENCODING 'UTF8';
➜  ~ psql -U admin -d cake -h 127.0.0.1
cake-> \c cake
You are now connected to database "cake" as user "admin".
cake=> CREATE TABLE test (id int, text VARCHAR(50));
CREATE TABLE
cake=> INSERT INTO test(id, text) VALUES(1, 'test');
INSERT 0 1
cake=> select * from test where id =1;
 id | text
----+------
  1 | test
(1 row)

cake=> update test set text='aaaaaa' where id =1 ;
UPDATE 1
cake=> select * from test where id = 1;
 id |  text
----+--------
  1 | aaaaaa
(1 row)

cake=> delete from test where id = 1;
DELETE 1
cake=> select * from test;
 id | text
----+------
(0 rows)

cake=> pg_dump admin > /usr/local/psql/backup/pg.sql;

数据库可视化工具DataGrip

image

node.js连接postgresql

npm install -g pg

  • example
var { Client } = require("pg");

//创建连接
//var conString = "postgres://y-user:y-ps@localhost:5432/y-db";
var conString = "postgres://admin:1234@localhost:5432/cake"; 
var client = new Client(conString);
await client.connect();

var res = await client.query("select * from test"); //await 报错,使用内部
query.rows.foreach(row => {
  console.log(row);
});

await client.end();
  • callback方式
var { Client } = require("pg");

const client = new Client({
  user: "admin",
  password: "1234",
  database: "cake",
  host: "localhost",
  port: 5432
});
client.connect();
client.query("select * from test", (err, res) => {
  if (err) {
    console.log(err);
  }
  console.log(res);
  res.rows.forEach(row => {
    console.log(row);
  });
  client.end();
});
  • promise方式
var { Client } = require("pg");

var conString = "postgres://admin:1234@localhost:5432/cake";
const client = new Client(conString);
client.connect();
client
  .query("select * from test")
  .then(res => {
    res.rows.forEach(row => {
      console.log(row);
    });
    client.end();
  })
  .catch(e => console.log(e));
  • 参数写法
var { Client } = require("pg");

var conString = "postgres://admin:1234@localhost:5432/cake";
const client = new Client(conString);
client.connect();

const query = {
  name: "fetch-data",
  text: "select * from test where id = $1",
  values: [1]
};
client
  .query(query)
  .then(res => {
    res.rows.forEach(row => {
      console.log(row);
      client.end();
    });
  })
  .catch(e => console.log(e));
  • sql语句
插入
const query = {
  name: "insert-data",
  text: "insert into test (id, test) values ($1,$2)",
  values: [1, "test-1"]
};
删除
const query = {
  name: "delete-data",
  text: "delete from test where id=$1",
  values: [1]
};
  • res
Result {
  command: 'SELECT',
  rowCount: 1,
  oid: null,
  rows: [ anonymous { id: 1, test: 'test' } ],
  fields:
   [ Field {
       name: 'id',
       tableID: 16389,
       columnID: 1,
       dataTypeID: 23,
       dataTypeSize: 4,
       dataTypeModifier: -1,
       format: 'text' },
     Field {
       name: 'test',
       tableID: 16389,
       columnID: 2,
       dataTypeID: 1043,
       dataTypeSize: -1,
       dataTypeModifier: 54,
       format: 'text' } ],
  _parsers: [ [Function: parseInteger], [Function: noParse] ],
  RowCtor: [Function: anonymous],
  rowAsArray: false,
  _getTypeParser: [Function: bound ] }

vim学习之路

一开始只会最简单的

  • hjkl移动
    • h--left
    • l--right
    • j--down
    • k--up
  • i进入 insert 模式
  • esc退出到 normal 模式
  • :wq保存并退出
  • :q!退出不保存

知道了好多东西

  • i,a,A 都可以进入到insert模式
    • i在指针cursor前插入insert
    • a在指针cursor后插入append
    • A在行尾插入
  • o也可以直接向后插入一行,并进入insert mode

终于会最简单的复制粘贴

  • ctrl+v进入vision模式, 可以进行反白状态的多选
  • y 复制
  • p 粘贴paste

知道了如何删除,再也不用一个字符一个字符删了

  • x删除一个word
  • dd 删除一行

知道了如何撤销和重做

  • u撤销undo
  • ctrl+r重做redo

改变单词

  • c(change)直接在
  • R直接进入Replace mode

查找search

  • /开启查找
  • n向后重复查找
  • N向前重复查找

一键跳转到文件首,文件尾(但是目前没什么卵用)

  • G文件尾
  • gg文件首

暂时记住了这么多,w不是很会用

2017-12-7

  • 3 items -> 4 items
  • TopLevelCategory -> Collection
  • test

frontend/containers/popupShops:

PopupShops.getInitialProps = ({ context }: InitialProps): Promise<ShopProps> =>
  makeService(api.PopUpShopService, context)
    .all({})
    .then(({ popupShops: shops }) => ({ shops }));

frontend/containers/popupShops.test.js
主要测试
Promise对象,resolve和reject。resolve表示成功,reject表示被拒绝

describe("PopupShop.getInitialProps", () => {
  test("happy path", async () => {
    const response: typeof api.PopUpShopService.prototype.all = () =>
      Promise.resolve(new api.PopUpShopList({ popupShops: testProps }));

    api.PopUpShopService.prototype.all = jest.fn(response);

    const props = await PopupShops.getInitialProps(testContext());

    const expected: Props = { shops: testProps };

    expect(props).toMatchObject(expected);
  });

  test("failing API call", () => {
    const error = new Error("test error");

    api.PopUpShopService.prototype.all = jest.fn(() => Promise.reject(error));

    expect.hasAssertions();

    return expect(PopupShops.getInitialProps(testContext())).rejects.toBe(
      error
    );
  });
});

frontend/proto.d.ts, 类型声明文件, PopupShopService里面有一个all方法,返回一个Promise对象

class PopUpShopService extends $protobuf.rpc.Service {

        /**
         * Constructs a new PopUpShopService service.
         * @param rpcImpl RPC implementation
         * @param [requestDelimited=false] Whether requests are length-delimited
         * @param [responseDelimited=false] Whether responses are length-delimited
         */
        constructor(rpcImpl: $protobuf.RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean);

        /**
         * Creates new PopUpShopService service using the specified rpc implementation.
         * @param rpcImpl RPC implementation
         * @param [requestDelimited=false] Whether requests are length-delimited
         * @param [responseDelimited=false] Whether responses are length-delimited
         * @returns RPC service. Useful where requests and/or responses are streamed.
         */
        public static create(rpcImpl: $protobuf.RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean): PopUpShopService;

        /**
         * Calls All.
         * @param request Empty message or plain object
         * @param callback Node-style callback called with the error, if any, and PopUpShopList
         */
        public all(request: google.protobuf.IEmpty, callback: api.PopUpShopService.AllCallback): void;

        /**
         * Calls All.
         * @param request Empty message or plain object
         * @returns Promise
         */
        public all(request: google.protobuf.IEmpty): Promise<api.PopUpShopList>;
    }

frontend/proto.js,实现文件, 用变量PopUpShopService.prototype.all调用all方法

api.PopUpShopService = (function() {
  PopUpShopService.prototype.all = function all(request, callback) {
            return this.rpcCall(all, $root.google.protobuf.Empty, $root.api.PopUpShopList, request, callback);
        };
}

api/popupshop.proto 后端文件有一个service类型的PopUpShopService,有一个rpc类型的All方法,返回一个PopupList

package api;

import "github.com/golang/protobuf/ptypes/empty/empty.proto";
import "github.com/theplant/mastani/popupshop/spec.proto";

message PopUpShopList {
    repeated popupshop.PopUpShop popup_shops = 1;
}

service PopUpShopService {
    rpc All(google.protobuf.Empty) returns (PopUpShopList);
}

错误处理文件在frontend/prottp/index.ts文件下
三个错误,一个networkerror表示网络错误,可以通过Promise的reject得到
而其他两个错误是得到数据之后,验证错误提示哪一个field出错和Authorication权限错误
400以上的都是http错误

type IServiceError =
  | INetworkError
  | IHTTPError
  | IValidationError
  | IAuthenticationError;

const validateStatus = (props: { statusCode: number; body: Uint8Array }) => {
  if (props.statusCode === 422) {
    throw new ValidationError(props.body);
  } else if (props.statusCode === 403) {
    throw new AuthenticationError();
  } else if (props.statusCode >= 400) {
    throw new HTTPError(props.statusCode);
  }
  return props;
};

[转载]emmet, 让你的 html 飞起来

emmet 是什么
首先是官网上的介绍。

Emmet is a plugin for many popular text editors which greatly improves HTML & CSS workflow.
Emmet 是一个可用在许多流行文本编辑器上的极大简化 HTML 和 CSS 工作流程的插件。

前身是 Zen coding,他使用仿 css 选择器的语法来生成代码,极大提高了编写 HTML/CSS 的效率,之后改名为 emmet,但是随之而来的改变不仅限于名字,还增加了许多新的特性。

emmet 怎么用

新建一个html文档, 输入html:5, 按下tab键, 神奇的事情发生了

html:5
// tab
<!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>Document</title>
</head>
<body>
    
</body>
</html>

添加类、id、文本和属性
emmet 的一个强大特性,使用类 CSS 选择器的方式,

. 是生成类名,
# 是生成 id,
{} 中生成文本内容,
[] 中可以设置属性, 可以嵌套使用。
p
<p></p>

p.bar
<p class="bar"></p>

p.bar1.bar2
<p class="bar1 bar2"></p>

p#foo
<p id="foo"></p>

input[type=radio]
<input type="radio">

p.bar#foo{123}
<p class="bar" id="foo">123</p>

嵌套和分组
emmet 又一个强大的特性,也是让你写 html 速度起飞的关键因素。嵌套语法:

>:子元素符号,表示嵌套的元素
+:同级标签符号^:可以使该符号前的标签提升一行
其中 ^ 用的不多,容易让人逻辑混乱,这个时候就需要良好的分组来实现。
p>span
<p><span></span></p>

p+span
<p></p>
<span></span>

p>h1^span
<p>
    <h1></h1>
</p>
<span></span>

(p>h1)+span
<p>
    <h1></h1>
</p>
<span></span>

重复添加相同元素

ul>li*5

<ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>

加上分组的应用,可以处理更复杂的 html 结构

(div.warp>p.bar+span#foo)*2

<div class="warp">
    <p class="bar"></p>
    <span id="foo"></span>
</div>
<div class="warp">
    <p class="bar"></p>
    <span id="foo"></span>
</div>

列表按序计数

ul>li.item$*3

<ul>
    <li class="item1"></li>
    <li class="item2"></li>
    <li class="item3"></li>
</ul>

如果想要两位数的序号,添加两个$即可,依此类推
ul>li{item$$}*3

<ul>
    <li>item01</li>
    <li>item02</li>
    <li>item03</li>
</ul>

参考资料
emmet 官网
Emmet:HTML/CSS 代码快速编写神器
sublime text 2 中 Emmet8 个常用的技巧

git积累

关于.gitignore文件

.DS_Store
node_modules/

这样的好处是,可以忽略node_modules等类型的大文件。提高远程仓库的递交速度


递交本地代码到远程仓库

远程仓库的递交方法是

  1. 在github自己的账户下新建一个仓库,new responsity
  2. 克隆到本地
git clone https://github.com/WangHuiying/vCustomers
  1. 本地会有一个vCustomers的文件,将里面的.git文件夹全部拷贝到当前的工作目录下,注意.git文件是一个隐藏文件
  2. 开始递交
git add .
git commit -m "说明"
git push origin master

这样就可以完成远程的递交


github的用处:

  1. 可以把github当成是自己的代码的网盘哦,一般人应该不会把代码保存到百度网盘吧。而且不支持历史记录和修改

  2. 使用Hexo编写文章,把github当成一个免费的服务器, 欢迎参观我的博客

  3. 可以利用github写简历https://resume.github.io/?WangHuiying, 全英文,高大上,有木有

  4. 可以在chrome安装一个gitGist插件, 将看到的代码文章什么的都保存在github上

  5. 最后,如果自己不知道怎么编写.gitignore文件,这边有个在线网站,支持一键生成https://www.gitignore.io/

nodejs 开发一套 REST API 供多种客户端调用时, 如何防止 API 不被未授权的访问

image

基本思路: 当用户登录成功之后, 给用户一个登录的accessToken值
微博开发授权机制

接口 说明
OAuth2/authorize 请求用户授权 Token
OAuth2/access_token 获取授权过的 Access Token
OAuth2/get_token_info 授权信息查询接口
OAuth2/revokeoauth2 授权回收接口
OAuth2/get_oauth2_token OAuth1.0 的 Access Token 更换至 OAuth2.0 的 Access Token
https://api.weibo.com/oauth2/access_token?client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=authorization_code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI&code=CODE
{
    "access_token": "SlAV32hkKG",
    "remind_in": 3600,
    "expires_in": 3600
}

<ECMAScript 6 入门>学习笔记

  1. 检查自己的电脑的node.js支持ES6
node --v8-options | grep harmony
  1. Babel

Babel是一个ES6转码器,可以将ES6代码转换为ES5代码, 从而在现有环境下支持
箭头函数=> 转换为普通函数 function(){}
配置文件.babelrc

{
 "presets": [],
 "plugins": []
}

presets字段设置转码规则

# 最新转码规则
$ npm install --save-dev babel-preset-latest

# react 转码规则
$ npm install --save-dev babel-preset-react

# 不同阶段语法提案的转码规则(共有4个阶段),选装一个
$ npm install --save-dev babel-preset-stage-0
$ npm install --save-dev babel-preset-stage-1
$ npm install --save-dev babel-preset-stage-2
$ npm install --save-dev babel-preset-stage-3
{
    "presets": [
      "latest",
      "react",
      "stage-2"
    ],
    "plugins": []
}

babel-cli工具, 用于命令行转码

$ npm install --global babel-cli

Node.js学习笔记

  1. 安装deepin系统(符合国人用户习惯的linux系统)
1. 制作u盘启动盘
2. 重启,按f12进入bash, 切换到startup启动项,将制作好的u盘调到首位
3. 进入deepin安装界面, 选择安装盘
4. 拔掉u盘, 重启, 完成安装
  1. 在deepin (linux)系统安装node.js
    试了很多种方法, 最后发现nvm安装是最方便的
    查看node.js的发行版本
先安装一个 nvm( https://github.com/creationix/nvm )
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.2/install.sh | bash
nvm 的全称是 Node Version Manager,之所以需要这个工具,是因为 Node.js 的各种特性都没有稳定下来,所以我们经常由于老项目或尝新的原因,需要切换各种版本。

安装完成后,重启bash, 你的 shell 里面应该就有个 nvm 命令了,调用它试试
$ nvm
当看到有输出时,则 nvm 安装成功。

安装 Node.js
使用 nvm 的命令安装 Node.js 最新稳定版,现在是 v6.8.0。

$ nvm install 6.8.0
安装完成后,查看一下
why@why-PC:~/Downloads$ node -v
v6.8.0
why@why-PC:~/Downloads$ npm -v
3.10.8
查看自己安装的所有 Node.js 版本
$ nvm ls
->       v6.8.0
node -> stable (-> v6.8.0) (default)
stable -> 6.8 (-> v6.8.0) (default)
iojs -> iojs- (-> N/A) (default)  #iojs是node.js的一个预发版本, 可以自己百度查看

如果出现下面错误,node未找到命令可以使用下面方法

why@why-PC:~/Downloads$ node
bash: node: 未找到命令
why@why-PC:~/Downloads$ nvm use stable
Now using node v6.8.0 (npm v3.10.8)
  1. npm
    在 PHP 中, 包管理使用的 Composer, python 中,包管理使用 easy_install 或者 pip,ruby 中我们使用 gem。而在 Node.js 中,对应就是 npm,npm 是 Node.js Package Manager 的意思。
    设置npm为淘宝镜像
npm config set registry 'https://registry.npm.taobao.org'

或直接使用cnpm, 接下来每次都使用cnpm安装

npm install -g cnpm
  1. 了解express
url
<scheme>://<user>:<password>@<host>:<port>/<url-path>
mkdir lesson1 & cd lesson1
npm install express --save-dev
touch app.js
// 引入express模块
var express = require('express');
// 调用express实例
var app = express();

//app本身有很多方法, 最常用的get, post, put/patch, delete
// handler函数接收req, res两个参数, 分别试request请求和response会员
app.get('/', function(req, res) {
    res.send('Hello world!'); //res.send向屏幕输出一个字符
})

// 监听3000端口
app.listen(3000, function(){
    console.log('app is listening at port 3000');
})

node app.js
打开浏览器,localhost:3000, 出现Hello Wolrd!字样
  1. 使用express-generator快速生成express项目
全局安装express-generator
npm install express-generator -g
快速生成项目
express --view=pug myapp
create : myapp
   create : myapp/package.json
   create : myapp/app.js
   create : myapp/public
   create : myapp/routes
   create : myapp/routes/index.js
   create : myapp/routes/users.js
   create : myapp/views
   create : myapp/views/index.pug
   create : myapp/views/layout.pug
   create : myapp/views/error.pug
   create : myapp/bin
   create : myapp/bin/www
   create : myapp/public/javascripts
   create : myapp/public/images
   create : myapp/public/stylesheets
   create : myapp/public/stylesheets/style.css
install dependencies:
     $ cd myapp && npm install

   run the app:
     $ DEBUG=myapp:* npm start
> [email protected] start /home/why/Downloads/myapp
> node ./bin/www

  myapp:server Listening on port 3000 +0ms

route路由, get. post, put/patch, delete

Respond with Hello World! on the homepage:
app.get('/', function (req, res) {
  res.send('Hello World!')
})

Respond to POST request on the root route (/), the application’s home page:
app.post('/', function (req, res) {
  res.send('Got a POST request')
})

Respond to a PUT request to the /user route:
app.put('/user', function (req, res) {
  res.send('Got a PUT request at /user')
})

Respond to a DELETE request to the /user route:
app.delete('/user', function (req, res) {
  res.send('Got a DELETE request at /user')
})
  1. package.json 和ultity.md5()加密
npm init来生成一个package.json文件
npm install express utility --save 本地安装,会多出来依赖
"dependencies": {
    "express": "^4.15.3",
    "utility": "^1.12.0"
}

http://localhost:4000/?q=st
md5加密之后
627fcdb6cc9a5e16d657ca6cdef0a6bb

var express = require('express')
var utility = require('utility')

var app = express()

app.get('/', function(req,res){
    var q = req.query.q

    var md5value = utility.md5(q)
    
    res.send(md5value)
})

app.listen(4000, function(req, res){
    console.log('listening at port 3000')
})

7. superagentcherrio爬虫
superagent

request
   .post('/api/pet')
   .send({ name: 'Manny', species: 'cat' })
   .set('X-API-Key', 'foobar')
   .set('Accept', 'application/json')
   .end(function(err, res){
     if (err || !res.ok) {
       alert('Oh no! error');
     } else {
       alert('yay got ' + JSON.stringify(res.body));
     }
   });

爬取cnodejs网站的信息

var express = require('express')
var superagent = require('superagent')
var cheerio = require('cheerio')

app = express()

app.get('/', function(req, res){
    // 使用superagent爬取https://cnodejs.org/的内容
    superagent.get('https://cnodejs.org')
        .end(function(err, content){ //命名为content是为了不与res冲突
          if(err) {
              return next(err)
          }
          // 使用cheerio解析网页的html内容,与jquery类似
          var $ = cheerio.load(content.text)
          var items = []
          $('#topic_list .topic_title').each(function(idx, element) {
              var $element = $(element)
              items.push({
                  title: $element.attr('title'),
                  href: $element.attr('href')
              })
          })
        res.send(items)
      })
})

app.listen(3001, function(req,res) {
    console.log('listening at port 3001')
})

netstat -nap | grep node查看node.js打开的端口

tcp6       0      0 :::6000                 :::*                    LISTEN      10958/node          
tcp6       4      0 :::3000                 :::*                    LISTEN      8035/node           
tcp6       0      0 :::3001                 :::*                    LISTEN      11004/node          
tcp6       3      0 :::4000                 :::*                    LISTEN      9443/node           
tcp6       2      0 :::5000                 :::*                    LISTEN      10849/node          
tcp6       1      0 127.0.0.1:4000          127.0.0.1:39482         CLOSE_WAIT  9443/node           
tcp6       1      0 127.0.0.1:5000          127.0.0.1:40180         CLOSE_WAIT  10849/node          
tcp6       1      0 127.0.0.1:5000          127.0.0.1:40182         CLOSE_WAIT  10849/node          
tcp6     491      0 127.0.0.1:5000          127.0.0.1:39340         CLOSE_WAIT  10849/node          
tcp6       1      0 127.0.0.1:5000          127.0.0.1:40178         CLOSE_WAIT  10849/node          
tcp6       0      0 127.0.0.1:3001          127.0.0.1:47786         ESTABLISHED 11004/node  

使用kill -9 8035 杀死进程, 其中8035是pid

11.Mongodb 与 Mongoose 的使用

工欲善其事必先利其器

小而强大的.exe文件

  • ScreenToGif--屏幕录制软件,到官网上下载就是一个.exe文件,无需安装,操作简单。

  • txt2Mobi通用版--txt文件格式文件必须转换为mobi等格式才可以在kindle阅读,这个下载下来也是一个.exe文件,打开之后将.txt文件拖到软件,就会自动生成一个.html文件和.mobi文件,接下来只需要将.mobi文件拷贝到kindle的.document文件夹就可以直接阅读了。

  • sdr-Cleaner_win文件只有5.4M,也是一个.exe文件,数据线连接kindle和电脑,双击这个.exe文件就会自动清理kindle了。

  • everything电脑上的文件查找软件,非常强大,Windows64操作系统可以选择Everything-1.4.0.713b.x64.Multilingual-Setup.exe这个下载,安装之后文件也不是很大。

  • 微盘上面的两个网站都是微盘的网站,的确微盘是一个找资源的好网站。

谷歌插件

谷歌浏览器的插件都需要通过谷歌应用商店添加,但是无奈的是需要翻墙,但是山人自有妙计,谷歌插件网就是一个国内的谷歌插件网站,这个网站上有很多强大的停不下来的插件,可以完美地解决添加插件的问题。下面是我正在用的插件

  • Smart TOC

  • insight
    给github换成IDE的风格

  • adblock pluschorme去广告插件,官网https://adblockplus.org/zh_CN/,官网的缺点是不能成功下载,所以我的链接是直接到上面提及的谷歌插件网下载。这个插件可以屏蔽大多数广告,还可以自己手动右键屏蔽广告。

  • 花瓣网页采集工具,网页截图还可以编辑图片,快捷键ctrl+ Shift+ R还可以截取网页制作长图,还可以收集网页上好看的图片,花瓣网本身也是设计师的天堂。

  • click && Clean 一键删除浏览记录,以前只能通过设置->历史记录—>清除浏览记录才可以删除浏览记录,这样太消耗时间,现在用这个插件,实时显示浏览网页的个数,一键就可以删除,关闭浏览器自动清除浏览记录,如果遇到关闭重要的网页,还可以直接用谷歌自带快捷键ctrl+ shift + T,恢复刚刚关闭的网页。

  • 印象笔记·悦读,自动识别博客主文,让阅读博客免受干扰,选择本站下载,就会自动添加到chorme插件上。

  • Video Downloader [FVD]网页视频自动检测,并下载,网页链接的图有点。。。但是下载不成问题,重要的是工具使用,很流畅地下载微博上的短视频。


以上是我在用的,小而功能强大的软件,如果你也有好的软件,非常欢迎一起分享,文章会持续更新!

初步尝试React & ReactNative

npm install -g create-react-native-app
create-react-native-app AwesomeProject
错误信息,不支持npm5, 使用npm4或yarn代替
Create React Native App doesn't work with npm 5 yet, unfortunately. We
recommend using npm 4 or yarn until some bugs are resolved.
全局安装
npm install yarn -g
create-react-native-app AwesomeProject
cd AwesomeProject
yarnpkg start

use next.js

https://github.com/zeit/next.js#setup
Install it:

npm install --save next react react-dom

Next.js 4 only supports React 16.
We had to drop React 15 support due to the way how React 16 works and how we use it.
and add a script to your package.json like this:

{
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}

After that, the file-system is the main API. Every .js file becomes a route that gets automatically processed and rendered.

Populate ./pages/index.js inside your project:

export default () => <div>Welcome to next.js!</div>

and then just run npm run dev and go to http://localhost:3000

Node.js缓存技术

Redis 的一些优点。

  1. 异常快 - Redis 非常快,每秒可执行大约110000次的设置 (SET) 操作,每秒大约可执行81000次的读取 / 获取 (GET) 操作。
  2. 支持丰富的数据类型 - Redis 支持开发人员常用的大多数数据类型,例如列表,集合,排序集和散列等等。这使得 Redis 很容易被用来解决各种问题,因为我们知道哪些问题可以更好使用地哪些数据类型来处理解决。
  3. 操作具有原子性 - 所有 Redis 操作都是原子操作,这确保如果两个客户端并发访问,Redis 服务器能接收更新的值。
  4. 多实用工具 - Redis 是一个多实用工具,可用于多种用例,如:缓存,消息队列 (Redis 本地支持发布 / 订阅),应用程序中的任何短期数据,例如,web 应用程序中的会话,网页命中计数等

空间换时间的原理, 会占用一点点内存, 但是给你的 web 服务提升明显的性能.
使用redis缓存数据, 当数据不变时, 直接从redis缓存中读取, 只有当要与数据库进行交互时,才去访问数据库.

var redis = require('redis');
var md5 = require('md5');
var redisClient = redis.createClient();

app.get('/demo', function (req, res) {
    var name = req.query.name;
    var key = md5([req.method, req.url, JSON.stringify(req.query)].join(':'));
    var expired = 60*5;

    redisClient.get(key, function (err, result) {
        if (err) {
            return res.send({message: 'Failed', data: err});
        }

        if (result) {
            // Read data from cache.
            return res.send({message: 'OK', JSON.parse(result)});

        } else {
            // Read data from Mongo and write result into redis.
            User.findOne({name: name}, function (err, user) {
                if (err) {
                    return res.send({message: 'Failed', data: err});
                }

                res.send({message: 'OK', user});
                redisClient.setex(key, expired, JSON.stringify(user));
            });
        }
    });
});

[Redis + Node.js: 请求缓存](http://m.2cto.com/kf/201612/575924.html)

2.Buffers 缓存对象
3. node-cache 轻量级

var cache = require('memory-cache');

// now just use the cache

cache.put('foo', 'bar');
console.log(cache.get('foo'));

// that wasn't too interesting, here's the good part

cache.put('houdini', 'disappear', 100, function(key, value) {
    console.log(key + ' did ' + value);
}); // Time in ms

console.log('Houdini will now ' + cache.get('houdini'));

setTimeout(function() {
    console.log('Houdini is ' + cache.get('houdini'));
}, 200);


// create new cache instance
var newCache = new cache.Cache();

newCache.put('foo', 'newbaz');

setTimeout(function() {
  console.log('foo in old cache is ' + cache.get('foo'));
  console.log('foo in new cache is ' + newCache.get('foo'));
}, 200);

http://yijiebuyi.com/blog/c37a444faab98617a98098f7a29e09db.html

image

http://localhost:3000/repos?org=risingstack
4. node-redis--redis - a node.js redis client
the-little-redis-book

Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED 127.0.0.1:6379
redis - windows
config redis server
Redis 是一个开源,高级的键值存储和一个适用的解决方案,用于构建高性能,可扩展的 Web 应用程序。

Redis 有三个主要特点,使它优越于其它键值数据存储系统 -

Redis 将其数据库完全保存在内存中,仅使用磁盘进行持久化。
与其它键值数据存储相比,Redis 有一组相对丰富的数据类型。
Redis 可以将数据复制到任意数量的从机中

const express = require('express')
const superagent = require('superagent')
var redis_client = require('redis').createClient()
const PORT = 3000

const app = express()

function getNumberOfRepos(req, res, next) {
    const org = req.query.org
    superagent.get(`https://api.github.com/orgs/${org}/repos`, (err, response) => {
    if (err) throw err

    var num = response.body.length
    redis_client.setex(org, 10, num)
    res.send(`Organization "${org}" has ${num} public repositories.`)
    })
}

function cache(req, res, next) {
    const org = req.query.org
    redis_client.get(org, (err, data) => {
        if(err) throw err

        if(data != null){
            res.send(`Orginization "${org}" has ${data} public repositories.`)
        } else {
            next()
        }
    })
}
app.get('/repos', cache, getNumberOfRepos)

app.listen(PORT, () => console.log(`app listen on port ${PORT}`))

image

image

# 启动redis-server
redis-server redis.windows.conf
# 配置redis为windows服务
redis-server --service-install redis.windows.conf
# 开启redis-server服务
redis-server --service-start
# 关闭redis-server服务
redis-server --service-stop
λ redis-cli
127.0.0.1:6379>
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> CONFIG GET loglevel
1) "loglevel"
2) "notice"

image

Redis Desttop Manager

  1. 让你的 Node.js 应用跑得更快的 10 个技巧
var redis = require('redis'),
    client = redis.createClient(null, null, { detect_buffers: true }),
    router = express.Router();

router.route('/latestPosts').get(function(req,res){
  client.get('posts', function (err, posts) {
    if (posts) {
      return res.render('posts', { posts: JSON.parse(posts) });
    }

    Post.getLatest(function(err, posts) {
      if (err) {
        throw err;
      }

      client.set('posts', JSON.stringify(posts));    
      res.render('posts', { posts: posts });
    });
  });
});
我们首先检查 Redis 缓存,看看是否有帖子。如果有,我们从缓存中拿这些帖子列表。否则我们就检索数据库内容,然后把结果缓存。此外,一定时间之后,我们可以清理 Redis 缓存,这样就可以更新内容了
    1. 并行 - async.js
    1. 异步 - readFileSync
    1. 缓存 - Redis 模块, node_redis 的客户端来保存键 / 值对
    1. gzip 压缩 - 内建 express.static() 中间件来处理静态内容,用 compression 中间件压缩和处理静态内容
    1. 如果可以,在用客户端渲染
    1. 不要在 Sessions 存储太多数据 - 只在 Session 中保存他们的 ID 而不是整个用户数据对象,用 MongoDB 或者 Redis 来存储 session 数据
    1. 优化查询 - Mongoose 的 find() 方法会把对象的所有字段都查询出来,而许多字段在主页上并不要求, Post.find().limit(10).exclude('comments').exec(function(err, posts) {} 剔除comments字段
    1. 用标准的 V8 方法
    1. 在 Node 前面用 Nginx, 静态资源配置到 nginx 上
    1. 打包 JavaScript - Grunt/Gulp

Promises学习笔记

resolve - then
reject - catch
this - global object 全局变量
document.readyState

  1. loading
  2. interactive
    3.complete
    .then()

《使用 promise 替代回调函数》

知识点

理解 Promise 概念,为什么需要 promise
学习 q 的 API,利用 q 来替代回调函数 (https://github.com/kriskowal/q )
课程内容

第五课 (https://github.com/alsotang/node-lessons/tree/master/lesson5 ) 讲述了如何使用 async 来控制并发。async 的本质是一个流程控制。其实在异步编程中,还有一个更为经典的模型,叫做 Promise/Deferred 模型。

本节我们就来学习这个模型的代表实现:q

首先,我们思考一个典型的异步编程模型,考虑这样一个题目:读取一个文件,在控制台输出这个文件内容。

var fs = require('fs');
fs.readFile('sample.txt', 'utf8', function (err, data) {
console.log(data);
});
看起来很简单,再进一步: 读取两个文件,在控制台输出这两个文件内容。

var fs = require('fs');
fs.readFile('sample01.txt', 'utf8', function (err, data) {
console.log(data);
fs.readFile('sample02.txt', 'utf8', function (err,data) {
console.log(data);
});
});
要是读取更多的文件呢?

var fs = require('fs');
fs.readFile('sample01.txt', 'utf8', function (err, data) {
fs.readFile('sample02.txt', 'utf8', function (err,data) {
fs.readFile('sample03.txt', 'utf8', function (err, data) {
fs.readFile('sample04.txt', 'utf8', function (err, data) {

		});
	});
});

});
这段代码就是臭名昭著的邪恶金字塔 (Pyramid of Doom)。可以使用 async 来改善这段代码,但是在本课中我们要用 promise/defer 来改善它。

promise 基本概念

先学习 promise 的基本概念。

promise 只有三种状态,未完成,完成 (fulfilled) 和失败 (rejected)。
promise 的状态可以由未完成转换成完成,或者未完成转换成失败。
promise 的状态转换只发生一次
promise 有一个 then 方法,then 方法可以接受 3 个函数作为参数。前两个函数对应 promise 的两种状态 fulfilled, rejected 的回调函数。第三个函数用于处理进度信息。

promiseSomething().then(function(fulfilled){
//当promise状态变成fulfilled时,调用此函数
},function(rejected){
//当promise状态变成rejected时,调用此函数
},function(progress){
//当返回进度信息时,调用此函数
});
学习一个简单的例子:

var Q = require('q');
var defer = Q.defer();
/**

  • 获取初始promise
  • @Private
    /
    function getInitialPromise() {
    return defer.promise;
    }
    /
    *
  • 为promise设置三种状态的回调函数
    */
    getInitialPromise().then(function(success){
    console.log(success);
    },function(error){
    console.log(error);
    },function(progress){
    console.log(progress);
    });
    defer.notify('in progress');//控制台打印in progress
    defer.resolve('resolve'); //控制台打印resolve
    defer.reject('reject'); //没有输出。promise的状态只能改变一次
    promise 的传递

then 方法会返回一个 promise,在下面这个例子中,我们用 outputPromise 指向 then 返回的 promise。

var outputPromise = getInputPromise().then(function (fulfilled) {
}, function (rejected) {
});
现在 outputPromise 就变成了受 function(fulfilled) 或者 function(rejected)控制状态的 promise 了。怎么理解这句话呢?

当 function(fulfilled) 或者 function(rejected) 返回一个值,比如一个字符串,数组,对象等等,那么 outputPromise 的状态就会变成 fulfilled。
在下面这个例子中,我们可以看到,当我们把 inputPromise 的状态通过 defer.resovle() 变成 fulfilled 时,控制台输出 fulfilled.

当我们把 inputPromise 的状态通过 defer.reject() 变成 rejected,控制台输出 rejected

var Q = require('q');
var defer = Q.defer();
/**

  • 通过defer获得promise
  • @Private
    */
    function getInputPromise() {
    return defer.promise;
    }

/**

  • 当inputPromise状态由未完成变成fulfil时,调用function(fulfilled)
  • 当inputPromise状态由未完成变成rejected时,调用function(rejected)
  • 将then返回的promise赋给outputPromise
  • function(fulfilled) 和 function(rejected) 通过返回字符串将outputPromise的状态由
  • 未完成改变为fulfilled
  • @Private
    */
    var outputPromise = getInputPromise().then(function(fulfilled){
    return 'fulfilled';
    },function(rejected){
    return 'rejected';
    });

/**

  • 当outputPromise状态由未完成变成fulfil时,调用function(fulfilled),控制台打印'fulfilled: fulfilled'。
  • 当outputPromise状态由未完成变成rejected, 调用function(rejected), 控制台打印'rejected: rejected'。
    */
    outputPromise.then(function(fulfilled){
    console.log('fulfilled: ' + fulfilled);
    },function(rejected){
    console.log('rejected: ' + rejected);
    });

/**

  • 将inputPromise的状态由未完成变成rejected
    */
    defer.reject(); //输出 fulfilled: rejected

/**

  • 将inputPromise的状态由未完成变成fulfilled
    */
    //defer.resolve(); //输出 fulfilled: fulfilled
    当 function(fulfilled) 或者 function(rejected) 抛出异常时,那么 outputPromise 的状态就会变成 rejected
    var Q = require('q');
    var fs = require('fs');
    var defer = Q.defer();

/**

  • 通过defer获得promise
  • @Private
    */
    function getInputPromise() {
    return defer.promise;
    }

/**

  • 当inputPromise状态由未完成变成fulfil时,调用function(fulfilled)
  • 当inputPromise状态由未完成变成rejected时,调用function(rejected)
  • 将then返回的promise赋给outputPromise
  • function(fulfilled) 和 function(rejected) 通过抛出异常将outputPromise的状态由
  • 未完成改变为reject
  • @Private
    */
    var outputPromise = getInputPromise().then(function(fulfilled){
    throw new Error('fulfilled');
    },function(rejected){
    throw new Error('rejected');
    });

/**

  • 当outputPromise状态由未完成变成fulfil时,调用function(fulfilled)。
  • 当outputPromise状态由未完成变成rejected, 调用function(rejected)。
    */
    outputPromise.then(function(fulfilled){
    console.log('fulfilled: ' + fulfilled);
    },function(rejected){
    console.log('rejected: ' + rejected);
    });

/**

  • 将inputPromise的状态由未完成变成rejected
    */
    defer.reject(); //控制台打印 rejected [Error:rejected]

/**

  • 将inputPromise的状态由未完成变成fulfilled
    */
    //defer.resolve(); //控制台打印 rejected [Error:fulfilled]
    当 function(fulfilled) 或者 function(rejected) 返回一个 promise 时,outputPromise 就会成为这个新的 promise.
    这样做有什么意义呢? 主要在于聚合结果 (Q.all),管理延时,异常恢复等等

比如说我们想要读取一个文件的内容,然后把这些内容打印出来。可能会写出这样的代码:

//错误的写法
var outputPromise = getInputPromise().then(function(fulfilled){
fs.readFile('test.txt','utf8',function(err,data){
return data;
});
});
然而这样写是错误的,因为 function(fulfilled) 并没有返回任何值。需要下面的方式:

var Q = require('q');
var fs = require('fs');
var defer = Q.defer();

/**

  • 通过defer获得promise
  • @Private
    */
    function getInputPromise() {
    return defer.promise;
    }

/**

  • 当inputPromise状态由未完成变成fulfil时,调用function(fulfilled)
  • 当inputPromise状态由未完成变成rejected时,调用function(rejected)
  • 将then返回的promise赋给outputPromise
  • function(fulfilled)将新的promise赋给outputPromise
  • 未完成改变为reject
  • @Private
    */
    var outputPromise = getInputPromise().then(function(fulfilled){
    var myDefer = Q.defer();
    fs.readFile('test.txt','utf8',function(err,data){
    if(!err && data) {
    myDefer.resolve(data);
    }
    });
    return myDefer.promise;
    },function(rejected){
    throw new Error('rejected');
    });

/**

  • 当outputPromise状态由未完成变成fulfil时,调用function(fulfilled),控制台打印test.txt文件内容。

*/
outputPromise.then(function(fulfilled){
console.log(fulfilled);
},function(rejected){
console.log(rejected);
});

/**

  • 将inputPromise的状态由未完成变成rejected
    */
    //defer.reject();

/**

  • 将inputPromise的状态由未完成变成fulfilled
    */
    defer.resolve(); //控制台打印出 test.txt 的内容
    方法传递

方法传递有些类似于 Java 中的 try 和 catch。当一个异常没有响应的捕获时,这个异常会接着往下传递。

方法传递的含义是当一个状态没有响应的回调函数,就会沿着 then 往下找。

没有提供 function(rejected)
var outputPromise = getInputPromise().then(function(fulfilled){})
如果 inputPromise 的状态由未完成变成 rejected, 此时对 rejected 的处理会由 outputPromise 来完成。

var Q = require('q');
var fs = require('fs');
var defer = Q.defer();

/**

  • 通过defer获得promise
  • @Private
    */
    function getInputPromise() {
    return defer.promise;
    }

/**

  • 当inputPromise状态由未完成变成fulfil时,调用function(fulfilled)
  • 当inputPromise状态由未完成变成rejected时,这个rejected会传向outputPromise
    */
    var outputPromise = getInputPromise().then(function(fulfilled){
    return 'fulfilled'
    });
    outputPromise.then(function(fulfilled){
    console.log('fulfilled: ' + fulfilled);
    },function(rejected){
    console.log('rejected: ' + rejected);
    });

/**

  • 将inputPromise的状态由未完成变成rejected
    */
    defer.reject('inputpromise rejected'); //控制台打印rejected: inputpromise rejected

/**

  • 将inputPromise的状态由未完成变成fulfilled
    */
    //defer.resolve();
    没有提供 function(fulfilled)
    var outputPromise = getInputPromise().then(null,function(rejected){})
    如果 inputPromise 的状态由未完成变成 fulfilled, 此时对 fulfil 的处理会由 outputPromise 来完成。

var Q = require('q');
var fs = require('fs');
var defer = Q.defer();

/**

  • 通过defer获得promise
  • @Private
    */
    function getInputPromise() {
    return defer.promise;
    }

/**

  • 当inputPromise状态由未完成变成fulfil时,传递给outputPromise
  • 当inputPromise状态由未完成变成rejected时,调用function(rejected)
  • function(fulfilled)将新的promise赋给outputPromise
  • 未完成改变为reject
  • @Private
    */
    var outputPromise = getInputPromise().then(null,function(rejected){
    return 'rejected';
    });

outputPromise.then(function(fulfilled){
console.log('fulfilled: ' + fulfilled);
},function(rejected){
console.log('rejected: ' + rejected);
});

/**

  • 将inputPromise的状态由未完成变成rejected
    */
    //defer.reject('inputpromise rejected');

/**

  • 将inputPromise的状态由未完成变成fulfilled
    */
    defer.resolve('inputpromise fulfilled'); //控制台打印fulfilled: inputpromise fulfilled
    可以使用 fail(function(error)) 来专门针对错误处理,而不是使用 then(null,function(error))
    var outputPromise = getInputPromise().fail(function(error){})
    看这个例子

var Q = require('q');
var fs = require('fs');
var defer = Q.defer();

/**

  • 通过defer获得promise
  • @Private
    */
    function getInputPromise() {
    return defer.promise;
    }

/**

  • 当inputPromise状态由未完成变成fulfil时,调用then(function(fulfilled))
  • 当inputPromise状态由未完成变成rejected时,调用fail(function(error))
  • function(fulfilled)将新的promise赋给outputPromise
  • 未完成改变为reject
  • @Private
    /
    var outputPromise = getInputPromise().then(function(fulfilled){
    return fulfilled;
    }).fail(function(error){
    console.log('fail: ' + error);
    });
    /
    *
  • 将inputPromise的状态由未完成变成rejected
    */
    defer.reject('inputpromise rejected');//控制台打印fail: inputpromise rejected

/**

  • 将inputPromise的状态由未完成变成fulfilled
    /
    //defer.resolve('inputpromise fulfilled');
    可以使用 progress(function(progress)) 来专门针对进度信息进行处理,而不是使用 then(function(success){},function(error){},function(progress){})
    var Q = require('q');
    var defer = Q.defer();
    /
    *
  • 获取初始promise
  • @Private
    /
    function getInitialPromise() {
    return defer.promise;
    }
    /
    *
  • 为promise设置progress信息处理函数
    */
    var outputPromise = getInitialPromise().then(function(success){

}).progress(function(progress){
console.log(progress);
});

defer.notify(1);
defer.notify(2); //控制台打印1,2
promise 链

promise 链提供了一种让函数顺序执行的方法。

函数顺序执行是很重要的一个功能。比如知道用户名,需要根据用户名从数据库中找到相应的用户,然后将用户信息传给下一个函数进行处理。

var Q = require('q');
var defer = Q.defer();

//一个模拟数据库
var users = [{'name':'andrew','passwd':'password'}];

function getUsername() {
return defer.promise;
}

function getUser(username){
var user;
users.forEach(function(element){
if(element.name === username) {
user = element;
}
});
return user;
}

//promise链
getUsername().then(function(username){
return getUser(username);
}).then(function(user){
console.log(user);
});

defer.resolve('andrew');
我们通过两个 then 达到让函数顺序执行的目的。

then 的数量其实是没有限制的。当然,then 的数量过多,要手动把他们链接起来是很麻烦的。比如

foo(initialVal).then(bar).then(baz).then(qux)
这时我们需要用代码来动态制造 promise 链

var funcs = [foo,bar,baz,qux]
var result = Q(initialVal)
funcs.forEach(function(func){
result = result.then(func)
})
return result
当然,我们可以再简洁一点

var funcs = [foo,bar,baz,qux]
funcs.reduce(function(pre,current),Q(initialVal){
return pre.then(current)
})
看一个具体的例子

function foo(result) {
console.log(result);
return result+result;
}
//手动链接
Q('hello').then(foo).then(foo).then(foo); //控制台输出: hello
// hellohello
// hellohellohello

//动态链接
var funcs = [foo,foo,foo];
var result = Q('hello');
funcs.forEach(function(func){
result = result.then(func);
});
//精简后的动态链接
funcs.reduce(function(prev,current){
return prev.then(current);
},Q('hello'));
对于 promise 链,最重要的是需要理解为什么这个链能够顺序执行。如果能够理解这点,那么以后自己写 promise 链可以说是轻车熟路啊。

promise 组合

回到我们一开始读取文件内容的例子。如果现在让我们把它改写成 promise 链,是不是很简单呢?

var Q = require('q'),
fs = require('fs');
function printFileContent(fileName) {
return function(){
var defer = Q.defer();
fs.readFile(fileName,'utf8',function(err,data){
if(!err && data) {
console.log(data);
defer.resolve();
}
})
return defer.promise;
}
}
//手动链接
printFileContent('sample01.txt')()
.then(printFileContent('sample02.txt'))
.then(printFileContent('sample03.txt'))
.then(printFileContent('sample04.txt')); //控制台顺序打印sample01到sample04的内容
很有成就感是不是。然而如果仔细分析,我们会发现为什么要他们顺序执行呢,如果他们能够并行执行不是更好吗? 我们只需要在他们都执行完成之后,得到他们的执行结果就可以了。

我们可以通过 Q.all([promise1,promise2...]) 将多个 promise 组合成一个 promise 返回。 注意:

当 all 里面所有的 promise 都 fulfil 时,Q.all 返回的 promise 状态变成 fulfil
当任意一个 promise 被 reject 时,Q.all 返回的 promise 状态立即变成 reject
我们来把上面读取文件内容的例子改成并行执行吧

var Q = require('q');
var fs = require('fs');
/**
*读取文件内容
*@Private
*/
function printFileContent(fileName) {
//Todo: 这段代码不够简洁。可以使用Q.denodeify来简化
var defer = Q.defer();
fs.readFile(fileName,'utf8',function(err,data){
if(!err && data) {
console.log(data);
defer.resolve(fileName + ' success ');
}else {
defer.reject(fileName + ' fail ');
}
})
return defer.promise;
}

Q.all([printFileContent('sample01.txt'),printFileContent('sample02.txt'),printFileContent('sample03.txt'),printFileContent('sample04.txt')])
.then(function(success){
console.log(success);
}); //控制台打印各个文件内容 顺序不一定
现在知道 Q.all 会在任意一个 promise 进入 reject 状态后立即进入 reject 状态。如果我们需要等到所有的 promise 都发生状态后 (有的 fulfil, 有的 reject),再转换 Q.all 的状态, 这时我们可以使用 Q.allSettled

var Q = require('q'),
fs = require('fs');
/**
*读取文件内容
*@Private
*/
function printFileContent(fileName) {
//Todo: 这段代码不够简洁。可以使用Q.denodeify来简化
var defer = Q.defer();
fs.readFile(fileName,'utf8',function(err,data){
if(!err && data) {
console.log(data);
defer.resolve(fileName + ' success ');
}else {
defer.reject(fileName + ' fail ');
}
})
return defer.promise;
}

Q.allSettled([printFileContent('nosuchfile.txt'),printFileContent('sample02.txt'),printFileContent('sample03.txt'),printFileContent('sample04.txt')])
.then(function(results){
results.forEach(
function(result) {
console.log(result.state);
}
);
});
结束 promise 链

通常,对于一个 promise 链,有两种结束的方式。第一种方式是返回最后一个 promise

如 return foo().then(bar);

第二种方式就是通过 done 来结束 promise 链

如 foo().then(bar).done()

为什么需要通过 done 来结束一个 promise 链呢? 如果在我们的链中有错误没有被处理,那么在一个正确结束的 promise 链中,这个没被处理的错误会通过异常抛出。

var Q = require('q');
/**
@Private
/
function getPromise(msg,timeout,opt) {
var defer = Q.defer();
setTimeout(function(){
console.log(msg);
if(opt)
defer.reject(msg);
else
defer.resolve(msg);
},timeout);
return defer.promise;
}
/

*没有用done()结束的promise链
*由于getPromse('2',2000,'opt')返回rejected, getPromise('3',1000)就没有执行
然后这个异常并没有任何提醒,是一个潜在的bug
/
getPromise('1',3000)
.then(function(){return getPromise('2',2000,'opt')})
.then(function(){return getPromise('3',1000)});
/

*用done()结束的promise链
*有异常抛出
*/
getPromise('1',3000)
.then(function(){return getPromise('2',2000,'opt')})
.then(function(){return getPromise('3',1000)})
.done();
结束语

当你理解完上面所有的知识点时,你就会正确高效的使用 promise 了。本节只是讲了 promise 的原理和几个基本的 API,不过你掌握了这些之后,再去看 q 的文档,应该很容易就能理解各个 api 的意图。

Todo

valuse = [“CL1”], return fieldName = “ネックレス”
what if values = [“CL1”, “CL2"], should return fieldName = “ネックレス, ネッス“?

  • Consider to get whole values from field Collection instead of get first item of values?
  • figure how to get japanse collection name from code 'CL1'
// getProductField returns the raw field value inside the `product.filterProperties`.
const getProductField = (
  fieldName: ProductField,
  product: products.IProduct
): string | null => {
  if (!product.filterProperties) {
    return null;
  }

  const property = product.filterProperties.find(
    ({ field }) => field === fieldName
  );

  if (!property || !property.values || property.values.length === 0) {
    return null;
  }

  return property.values[0]; // ? should return property.values
};
productResponse{
   code: 'ES-00',
   properties: [
    { 
      "field": "Collection",
      "inValues": ["CL1"]
    }
   ]
}

const rdGroups = [
  {
    info: {
      itemType: "ProductFilterProperties",
      code: ProductField.Collection
    },
    items: [
      {
        itemType: ProductField.Collection,
        code: "CL1",
        slug: "necklace",
        name: "ネックレス"
      }
    ]
  }
];

  • 高效使用mac
  • 1password
  • mac简单入门
  • mac的快捷键
  • 鸟哥的私房菜
  • Linux command
  • Vim
  • alfred + workflow
    • find filename -- find file path
    • open filename -open file
    • 加入书签栏
  • git cherry-pick commit号
  • vscode 快捷键
  • git soft 如何使用
  • 修复code .不能打开当前目录的问题,写的脚本不对
  • 把图片放到docker里面,然后写在代码注释里
  • 录制gif图
:Pseudo-classes     伪类:DOM在不同状态、不同位置下的特殊效果;
::Pseudo-elements   伪元素:DOM按匹配规则伪造出的元素;

常用伪元素

::after         在元素的内容之后
::before        在元素的内容之前
::first-line    元素的第一行
::first-letter  元素的第一个字母
::placeholder   占位符,用于input输入框之类的提醒
::selection     被选取的元素,用于改变网页被选中部分的效果

:active         当元素被点击的时
:blank          空白的元素
:checked        被选中的元素
:default        默认被选中或默认会被提交的元素
:dir()          匹配特定文字书写方向的元素
:disabled       处于被禁止操作状态的元素
:empty          没有任何内容的元素
:enabled        处于可操作状态的元素
:first          用于打印文档的第一页
:first-child    父级元素下的第一个子元素
:first-of-type  父级元素下的第一个同类子元素
:focus          当元素成为焦点
:fullscreen     当元素被HTML5 API调用RequestFullscreen方式全屏时
:hover          当鼠标移动到链接元素上面时
:in-range       当元素属性值处于其指定的范围内时    
:indeterminate  当元素属性值处于不确定状态的
:invalid        当元素属性值不是指定的type属性时
:lang()         匹配有正确lang 属性值的元素,如 lang(zh-Hans)
:last-child     元素的最后一个子元素
:last-of-type   元素的最后一个同类子元素
:left           选择打印文档的左侧页
:link           未被访问的链接元素
:not()          否定选择器(不匹配条件则生效)
:nth-child()    元素的一个或多个特定的子元素
:nth-last-child() 元素的一个或多个特定的子元素,从该元素的最后一个子元素开始算;
:nth-of-type()  选择指定的元素
:nth-last-of-type() 选择指定的元素,从元素的最后一个开始计算
:only-child     元素是它的父元素的唯一子元素
:only-of-type   元素是它的父级元素的唯一一个相同类型的子元素
:optional       未指定required属性的表单元素
:out-of-range   超出规定值范围的元素
:read-only      元素设置了 'readonly' 属性生效
:read-write     元素没有 "readonly" 属性生效
:required       设置了 "required" 属性的元素    
:right          选择打印文档的左侧页
:root           文档的根元素
:scope          作用域的伪类,默认为HTML(案例 :scope #mammma {...})
:target         当前活动的元素(匹配页面URI中对应的目标元素)
:valid          表示有效的元素
:visited        已被访问过的元素
 content        在元素之前或之后添加的内容。

如何使用 nodejs 作为 java(后端)和前端的中间件?

如何使用 nodejs 作为 java(后端)和前端的中间件?
image
image
在这种研发模式下,前后端的职责很清晰。对前端来说,两个 UI 层各司其职:

1、Front-end UI layer 处理浏览器层的展现逻辑。通过 CSS 渲染样式,通过 JavaScript 添加交互功能,HTML 的生成也可以放在这层,具体看应用场景。

2、Back-end UI layer 处理路由、模板、数据获取、cookie 等。通过路由,前端终于可以自主把控 URL Design,这样无论是单页面应用还是多页面应用,前端都可以自由调控。后端也终于可以摆脱对展现的强关注,转而可以专心于业务逻辑层的开发。

通过 Node,Web Server 层也是 JavaScript 代码,这意味着部分代码可前后复用,需要 SEO 的场景可以在服务端同步渲染,由于异步请求太多导致的性能问题也可以通过服务端来缓解。前一种模式的不足,通过这种模式几乎都能完美解决掉。

与 JSP 模式相比,全栈模式看起来是一种回归,也的确是一种向原始开发模式的回归,不过是一种螺旋上升式的回归。

基于 Node 的全栈模式,依旧面临很多挑战:

1、需要前端对服务端编程有更进一步的认识。比如 network/tcp、PE 等知识的掌握。
2、Node 层与 Java 层的高效通信。Node 模式下,都在服务器端,RESTful HTTP 通信未必高效,通过 SOAP 等方式通信更高效。一切需要在验证中前行。
3、对部署、运维层面的熟练了解,需要更多知识点和实操经验。
4、大量历史遗留问题如何过渡。这可能是最大最大的阻力。

Gitbook:
node 中间层搭建 · GitBook
nodejs+express+mongodb 学习笔记
koa
(RESTful的理解)[http://nodeonly.com/2015/06/09/expressjs-rest/]
七个路由,见app/routes/users.js

其中 4 个路由是 crud

GET /users[/] => user.list()
POST /users[/] => user.create()
PATCH /users/:id => user.update()
DELETE /users/:id => user.destroy()
另外 3 个是页面渲染用的

GET /users/new => user.new()
GET /users/:id => user.show()
GET /users/:id/edit => user.edit()
那么我们先来看一下 crud 对应的请求方法

get 用于请求列表
post 用于创建
patch 用于更新,局部更新资源
delete 用于删除

var UserDao = new MongooseDao(User); 数据库操作对象
所以在 controller 里我们看到了如下代码

+ User.getAll(function(err, users){
+ User.getById(id, function(err, user) {
+ User.create({name: req.body.name,password: req.body.password}, function (err, user) {
+ User.updateById(id,{name: req.body.name,password: req.body.password}, function (err, user) {
+ User.deleteById(id, function (err) {

Vue.js处理前端
node.js中间件
java-后端
axios处理网络交互
前端vue.js 后端node.js的交互程序
Java和node.js的历史发展

exports 和 module.exports 的区别了:

  • module.exports 初始值为一个空对象 {}
  • exports 是指向的module.exports 的引用
  • require() 返回的是 module.exports 而不是 exports

Vue2.0学习笔记

  1. 首先使用vue-cli初始化项目
npm install vue-cli -g # 全局安装vue-cli
vue init webpack vueTest # 初始化一个vueTest项目, webpack是打包工具
cd vueTest # 进入vueTest项目根目录
npm install # 安装依赖, 这边取消安装eslint和接下来的一些工具,可以提高开发效率
npm run dev # 运行项目
  1. 引入v-for循环
<ul v-for="item in items">
    <li>{{ item.text }}</li>
</ul>
  1. 点击事件v-on:click
<button v-on:click="addItem">Add Item</button>
  1. 键盘事件 v-on:keypress.enter
# 点击enter
<input id="itemForm" v-on:keypress.enter="addItem"/>
  1. 事件
methods : {
  addItem: function(){
   var input = document.getElementById('itemForm');

   if(input.value !== '') {
      this.items.push({
         text: input.value
      })
      input.value = "";
   }
  },
  deleteItem: function(){
    this.items.splice(index, 1);
  }
}
  1. filter事件
<header> {{ title | capitalize}} <header>
<a href="">{{ dio.text | underscore | url }}</a>
data: {
},
filters: {
  capitalize: function(value) {
   if(!value) return "";
   value = value.toString();
   return value.CharAt(0).toString() + Value.splice(1);
  },
  undercase: function(value){
   if(!value) return "";
   value = value.toString();
   return value.toLowerCase()
  },
  url: function(value) {
     if(!value) return '';
     value = value.toString();
     return "https://en.wikipedia.org/wiki/" + value;
  }
}
  1. compute方法
data: {
   return() {
     totals: 0,
     length: 0
   }
}
methods: {
},
computed: {
  totals: function() {
    var sum = 0;
    var items = this.items;
    
    for(var i in items) {
      sum += items[i].quantity
    }
    return sum;
  },
  length: function(){
     return  this.length
  }
}
  1. watch方法, 监听方法, 当长度太长,就切换按钮的text
data: {
},
watch: {
    input: _.debounce(function(){
     this.buttonText = this.input !== "“ ? "Add" + this.input: "Add Dinsour";
   }, 250);
}

9.v-bind绑定属性, class

<button v-bind:class="[sizeToggle ? 'large' : '',   {'rounded':isRounded }]"
      v-bind:style="styles"
      v-bind:disabled="disabled">Start Tour</button>

computed: {
   styles: function(){
     return {
        color: this.fontColor,
        background: this.backgroundColor,
        'margin-left': this.range + %
     }
   }
}
  1. v-if, v-elsev-show
v-if="array.length > 0"
v-else
v-show="dins.quanatity"
  1. v-on:submit.prevent=" 表单提交
<form v-on:submit.prevent="addDins">
   <button>Add {{amount}} Dinsours</button>
   <input type="number" v-model="amount" />
</form>
<p>you have {[ total }} dinosaurs !</p>
  1. 可复用的组件 v-bind:nameprops
<dino-counter v-bind:name="dino.name"
                         v-bind:initial-quantity="dino.quantity"></dino-counter>

componets: {
    'dino-counter': {
      template: '#dino-counter',
      props: ['name', 'initialQuantity'],
      data: function(){
         return {
            quantity: this.quantity
         }
      }
   }
}

想法

  1. 公交车可以自动根据人流量规划出行时间,避免空车浪费

日记

这个月的记录:

  1. 找到一份超级棒的工作,加入组织theplant,写了分享http://www.jianshu.com/p/221a60abfad0
  2. 拥有人生第一台Mac电脑,27寸超大的iMac。终于在无数次的尝试下完成了appid的注册。下载欧路词典支持屏幕取词。
  3. 昨天介绍自己的翻墙软件https://github.com/XX-net/XX-Net给君哥,被表扬👍,😄
  4. 完成了两个pullrequest
  5. 认识了现在的师父,俊晖哥--超nice的一个人,vimer,超级耐心,广东人,但是英语超棒。头一次见到真实的番茄工作法者
  6. 花钱最贵的一个月,花了1200多,其中给自己买了一件H&M( 比伯推荐 )的红色卫衣179. 吃了两次45块的海鲜大餐。
  7. 找到了一个GitHub插件https://github.com/jawil/GayHub, 响应速度超快,果断放弃原先的insight.io插件

这个月超级充实,哈哈哈,等待国庆放假回来可以收到美金,哈哈哈

2017-12-4

read css
https://juejin.im/post/5a0c184c51882531926e4294#heading-45

iterm & zsh & oh-my-zsh
http://www.dreamxu.com/mac-terminal/

  • 現在配置好的iterm可以支持option+space自动从顶部出现
  • 可以支持历史记录,通过按下》这个键补全历史命令
  • 可以支持 j frontent自动跳转到mastani/frontend目录
  • 背景是透明的,所以不会遮住下面的文字

fix previous-image-show-momentarily
little image will flash from previous to the new

React 的 vDom diff 算法能保证最小程度的 DOM 改变
在渲染的时候,数据发生改变,因此react会立马判断大图发生改变而更新,小图是根据数组的key得到的,因此反应慢一拍
key 值必须是独一无二的,最好不要是数字,绝对不能是遍历中的 index

 <WR perRow={2}>
          {restImages.map(
            ({ id }, index) =>
              id ? (
                <C key={index}>
                  <ThumbImg id={id} />
                </C>
              ) : null
          )}
          {restImages.length % 2 == 1 && <C />}
</WR>

修改
index为 一个独一无二的值,比如id
参考
React 应用性能优化之 shouldComponentUpdate 与 key
了解id是什么

//mastani-dev.s3-ap-southeast-1.amazonaws.com/product_images/322/file/xse-k-67-2.20171108075217046927828.png
//mastani-dev.s3-ap-southeast-1.amazonaws.com/product_images/323/file/xse-k-67-3.20171108070217627002371.png

after

XX-net/XX-Net#8797
手机上的xx-net浏览器,导入APPID之后就可以直接访问外网

配置小狼毫輸入法

Steward--在chrome里使用aflred
http://oksteward.com/%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97.html

初步尝试 React & ReactNative

@wanghuiying commented on Thu Aug 10 2017

@wanghuiying commented on Wed Aug 09 2017

npm install -g create-react-native-app
create-react-native-app AwesomeProject
错误信息,不支持npm5, 使用npm4或yarn代替
Create React Native App doesn't work with npm 5 yet, unfortunately. We
recommend using npm 4 or yarn until some bugs are resolved.
全局安装
npm install yarn -g
create-react-native-app AwesomeProject
cd AwesomeProject
yarnpkg start

@wanghuiying commented on Thu Aug 10 2017

初始化项目,配置舒适的环境
深入浅出/react.js/开发环境

npm install webpack webpack-dev-server --save-dev

安装 css-loader、style-loader、image-loader, 可以在 js 下加载 css 样式文件和图片

npm install css-loader style-loader image-loader --save

安装 react.js 依赖包(react react-dom)和 babel 依赖包(转换 jsx-js 等)

npm install --save react react-dom babel-preset-react babel-preset-es 2015 babel-loader babel-core

新建webpack.config.js文件

var webpack = require('webpack')
var path = require('path')
module.exports = {
    entry: './app/entry.js', //项目打包入口
    output: {
        path: __dirname,
        filename: './build/bundle.js' //项目打包出口
    },
    module: {
        loaders: [{
            test: /\.js[x]?$/,
            exclude: /node_modules/,
            loaders: 'babel-loader?presets[]=es2015&presets[]=react'
        },{
            test: /\.css$/,
            loader: 'style-loader!css-loader'
        },{
            test: /\.(png|jpg)$/,
            loader: 'url-loader?limit=8192'
        }]
    }
};

在package.json文件添加下面脚本

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "start": "webpack-dev-server --devtool eval --progress --colors --hot",
    "deploy":"NODE_ENV=production & webpack -p",
    "deploy-windows":"SET NODE_ENV=production & webpack -p",
    "validate":"npm ls"
},

添加React Router组件

npm install -S react-router

添加 React Redux (状态管理)

npm install react-redux --save

添加 ESLint (代码质量)

npm install eslint --save

添加 antd (蚂蚁金服一款简洁的 UI)

npm install antd --save

首先需要安装 babel-plugin-import 依赖

npm install babel-plugin-import --save-dev

新建.babelrc文件

{
    "plugins": [["import", {"libraryName": "antd", "style": "css"}]] //import js and css modulary
}
app/components/app.js
import React from 'react';
import ReactDOM from 'react-dom';
import {
    Button
} from 'antd';

var App = React.createClass({
    render: function(){
        return (
            <div>
               <h1>Hey,this is a React and Antd IDE</h1>
               <div className="Antd">
                  <Button type="danger" size="large">成功加载Antd组件</Button>
               </div>
            </div>
        )
    }
});

ReactDOM.render(
    <App/>,
    document.getElementById('app')
);
index.html
<!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>index</title>
</head>
<body>
    <div id="app">

    </div>
    <script type="text/javascript" src="build/bundle.js"></script>
</body>
</html>
app/entry.js
'use strict';

//component
import './components/App'

// css
import './style/main.css'
npm start
> webpack-dev-server --devtool eval --progress --colors --hot

'webpack-dev-server' 不是内部或外部命令,也不是可运行的程序
检查package.json文件,发现未安装好webpackwebpack-dev-server,重新安装

npm start
http://localhost:8081/

成功访问

2017-10

昨天刚在搜索如何创建自己的GitHub label, 没想到今天就自己弹出来了,哈哈哈哈😄
image

React&Redux-TodoList

3 Minute React Test Drive: Hello World the easy way

  1. npm install -g react-heatpack
  2. mkdir react-hello & cd react-hello
  3. create and modify index.js
import React from "react";

export default React.createClass({
  render: function() {
    return <div>Hello React!</div>;
  }
});
  1. heatpack index.js

image.png

React&Redux-TodoList

directory
directory

all
all

active
active

completed
completed

index.js

import React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import todoApp from "./reducers";
import App from "./components/App";

let store = createStore(todoApp);

export default React.createClass({
  render: function() {
    return (
      <Provider store={store}>
        <App />
      </Provider>
    );
  }
});

reducer/index.js

import { combineReducers } from "redux";
import todos from "./todos";
import visibilityFilter from "./visibilityFilter";

const todoApp = combineReducers({
  todos,
  visibilityFilter
});

export default todoApp;

reducer/todos.js

const todos = (state = [], action) => {
  switch (action.type) {
    case "ADD_TODO":
      return [
        ...state,
        {
          id: action.id,
          text: action.text,
          completed: false
        }
      ];
    case "TOGGLE_TODO":
      return state.map(
        todo =>
          todo.id === action.id ? { ...todo, completed: !todo.completed } : todo
      );
    default:
      return state;
  }
};

export default todos;

reducer/visibilityFilter.js

const visibilityFilter = (state = "SHOW_ALL", action) => {
  switch (action.type) {
    case "SET_VISIBILITY_FILTER":
      return action.filter;
    default:
      return state;
  }
};

export default visibilityFilter;

containers
containers/AddTodo.js

import React from "react";
import { connect } from "react-redux";
import { addTodo } from "../actions";

let AddTodo = ({ dispatch }) => {
  let input;

  return (
    <div>
      <form
        onSubmit={e => {
          e.preventDefault();
          if (!input.value.trim()) {
            return;
          }
          dispatch(addTodo(input.value));
          input.value = "";
        }}
      >
        <input
          ref={node => {
            input = node;
          }}
        />
        <button type="submit">Add Todo</button>
      </form>
    </div>
  );
};

AddTodo = connect()(AddTodo);

export default AddTodo;

containers/FilterLink.js

import { connect } from "react-redux";
import { setVisibilityFilter } from "../actions";
import Link from "../components/Link";

const mapStateToProps = (state, ownProps) => {
  return {
    active: ownProps.filter === state.visibilityFilter
  };
};

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    onClick: () => {
      dispatch(setVisibilityFilter(ownProps.filter));
    }
  };
};

const FilterLink = connect(mapStateToProps, mapDispatchToProps)(Link);

export default FilterLink;

containers/VisibieTodoList.js

import { connect } from "react-redux";
import { toggleTodo } from "../actions";
import TodoList from "../components/TodoList";

const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case "SHOW_ALL":
      return todos;
    case "SHOW_COMPLETED":
      return todos.filter(t => t.completed);
    case "SHOW_ACTIVE":
      return todos.filter(t => !t.completed);
  }
};

const mapStateToProps = state => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  };
};

const mapDispatchToProps = dispatch => {
  return {
    onTodoClick: id => {
      dispatch(toggleTodo(id));
    }
  };
};

const VisibleTodoList = connect(mapStateToProps, mapDispatchToProps)(TodoList);

export default VisibleTodoList;

actions/index.js

let nextTodoId = 0;
export const addTodo = text => {
  return {
    type: "ADD_TODO",
    id: nextTodoId++,
    text
  };
};

export const setVisibilityFilter = filter => {
  return {
    type: "SET_VISIBILITY_FILTER",
    filter
  };
};

export const toggleTodo = id => {
  return {
    type: "TOGGLE_TODO",
    id
  };
};

components
components/App.js

import React from "react";
import Footer from "./Footer";
import AddTodo from "../containers/AddTodo";
import VisibleTodoList from "../containers/VisibleTodoList";

const App = () => (
  <div>
    <AddTodo />
    <VisibleTodoList />
    <Footer />
  </div>
);

export default App;

components/Footer.js

import React from "react";
import FilterLink from "../containers/FilterLink";

export default React.createClass({
  render: function() {
    return (
      <p>
        Show: <FilterLink filter="SHOW_ALL">All</FilterLink>
        {", "}
        <FilterLink filter="SHOW_ACTIVE">active</FilterLink>
        {", "}
        <FilterLink filter="SHOW_COMPLETED">completed</FilterLink>
      </p>
    );
  }
});

components/Link.js

import React from "react";
import PropTypes from "prop-types";

const Link = ({ active, children, onClick }) => {
  if (active) {
    return <span>{children}</span>;
  }

  return (
    <a
      href="#"
      onClick={e => {
        e.preventDefault();
        onClick();
      }}
    >
      {children}
    </a>
  );
};

Link.propTypes = {
  active: PropTypes.bool.isRequired,
  children: PropTypes.node.isRequired,
  onClick: PropTypes.func.isRequired
};

export default Link;

components/Todo.js

import React from "react";
import PropTypes from "prop-types";

const Todo = ({ onClick, completed, text }) => (
  <li
    onClick={onClick}
    style={{
      textDecoration: completed ? "line-through" : "none"
    }}
  >
    {text}
  </li>
);

Todo.propTypes = {
  onClick: PropTypes.func.isRequired,
  completed: PropTypes.bool.isRequired,
  text: PropTypes.string.isRequired
};

export default Todo;

components/TodoList.js

import React from "react";
import PropTypes from "prop-types";
import Todo from "./todo";

const TodoList = ({ todos, onTodoClick }) => (
  <ul>
    {todos.map(todo => (
      <Todo key={todo.id} {...todo} onClick={() => onTodoClick(todo.id)} />
    ))}
  </ul>
);

TodoList.propTypes = {
  todos: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.number.isRequired,
      completed: PropTypes.bool.isRequired,
      text: PropTypes.string.isRequired
    }).isRequired
  ).isRequired,
  onTodoClick: PropTypes.func.isRequired
};

export default TodoList;

Create a code Snipper by VSCode

link: https://www.youtube.com/watch?v=pbCrDBQFU_A&index=5&list=PLN3n1USn4xlnfJIQBa6bBjjiECnk6zL6s
code -> preference -> User Snipper

{
	// Place your snippets for typescriptreact here. Each snippet is defined under a snippet name and has a prefix, body and 
	// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
	// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the 
	// same ids are connected.
	// Example:
	// "Print to console": {
	// 	"prefix": "log",
	// 	"body": [
	// 		"console.log('$1');",
	// 		"$2"
	// 	],
	// 	"description": "Log output to console"
	// },
	"Typescript React PureComponent": {
		"prefix": "rpc",
		"body": [
			"import * as React from 'react'",
			"",
			"export class $1 extends React.PureComponent {",
			"\trender() {",
			"\t\treturn ($2);",
			"}}",
		],
		"description": "Typescript React PureComponent"
	}
}

create a new file eg.tsx, then input rpc and enter, you will get a code snipper

import * as React from 'react'

export class  extends React.PureComponent {
    render() {
        return ();
}}

如何在 vue 中使用 webuploader 上传文件

@wanghuiying commented on Mon Aug 14 2017

@wanghuiying commented on Mon Aug 14 2017

如何在vue-cli中使用jquery

package.json文件的dependence里面引入jquery

"jquery": "^1.11.1",

修改webpack.base.conf.js
增加

plugins: [
      new webpack.ProvidePlugin({
         $: "jquery",
  			jQuery: "jquery"
      })
   ],

设置界面

upload.vue

<template>
	<div>
		<!-- 断点续传   start-->  
		<!-- 隐藏域 实时保存上传进度 --> 
		<input id="jindutiao" type="hidden"/>  
		<div id="uploader" class="wu-example">  
			<!-- 文件列表:选择文件后在该 div 显示 -->  
			<div id="thelist" class="uploader-list" style="margin-left:160px;"></div> 
		    <div class="btns">  
			    <div id="picker">选择文件</div>
			    <button class="btn" id="startOrStopBtn" @click="FileUpload()" style="padding:8px 18px;margin-top:20px;"> 开始上传 </button>  
			</div> 
		</div>
	</div>
	<!-- 断点续传   end-->
</template>
<script>
        import '../../static/webuploader.css'
	import * as webuploader from '../../static/webuploader.js'
	
	export default {
		data() {
			return {
			}
		},
		mounted(){
			this.$nextTick(function(){
				webuploader.WebUploadRegister();
				webuploader.WebUploadCreate();
				webuploader.WebUploaderFileOperation();
		   })
		},
		methods: {
          FileUpload : function(){
          	webuploader.startOrStopUpload()
          }
		}
	}
</script>
<style>

</style>

webupload.js

import WebUploader from 'webuploader'

/******************* 初始化参数 *********************************/ 
var state = 'pending',// 初始按钮状态  
    uploader, //uploader 对象
    errorUpload = false; 
var fileMd5;  // 文件唯一标识  
  
/****************** 下面的参数是自定义的 *************************/  
var fileName;// 文件名称  
var oldJindu;// 如果该文件之前上传过 已经上传的进度是多少  
var count=0;// 当前正在上传的文件在数组中的下标,一次上传多个文件时使用  
var filesArr=new Array();// 文件数组:每当有文件被添加进队列的时候 就 push 到数组中  
var map={};//key 存储文件 id,value 存储该文件上传过的进度
    
/***************************************************** 监听分块上传过程中的三个时间点 start ***********************************************************/  
export const WebUploadRegister = function(){
	WebUploader.Uploader.register({
	    "before-send-file":"beforeSendFile",// 整个文件上传前  
	    "before-send":"beforeSend",  // 每个分片上传前  
	    "after-send-file":"afterSendFile",  // 分片上传完毕  
	},  
	{    
	    // 时间点 1:所有分块进行上传之前调用此函数    
	    beforeSendFile:function(file){  
	        var deferred = WebUploader.Deferred();    
	        //1、计算文件的唯一标记 fileMd5,用于断点续传  如果. md5File(file) 方法里只写一个 file 参数则计算 MD5 值会很慢 所以加了后面的参数:10*1024*1024  
	        (new WebUploader.Uploader()).md5File(file,0,10*1024*1024).progress(function(percentage){  
	
	        })    
	        .then(function(val){    
	            $('#'+file.id ).find("p.state").text("成功获取文件信息...");    
	            fileMd5=val;    
	            // 获取文件信息后进入下一步    
	            deferred.resolve();    
	        });    
	        fileName=file.name; // 为自定义参数文件名赋值  
	        return deferred.promise();    
	    },    
	    // 时间点 2:如果有分块上传,则每个分块上传之前调用此函数    
	    beforeSend:function(block){  
	        var deferred = WebUploader.Deferred(); 
	        $.ajax({    
	            type:"POST",    
	            url:"../upload?param=checkChunk",  //ajax 验证每一个分片  
	            data:{    
	                fileName : fileName,  
	                jindutiao:$("#jindutiao").val(),  
	                fileMd5:fileMd5,  // 文件唯一标记    
	                chunk:block.chunk,  // 当前分块下标    
	                chunkSize:block.end-block.start// 当前分块大小    
	            },    
	            cache: false,  
	            async: false,  // 与 js 同步  
	            timeout: 1000, //todo 超时的话,只能认为该分片未上传过  
	            dataType:"json",    
	            success:function(response){  
	                if(response.ifExist){  
	                    // 分块存在,跳过    
	                    deferred.reject();    
	                }else{    
	                    // 分块不存在或不完整,重新发送该分块内容
	                    deferred.resolve();    
	                }    
	            }    
	        });    
	                           
	        this.owner.options.formData.fileMd5 = fileMd5;    
	        deferred.resolve();    
	        return deferred.promise();    
	    },    
	    // 时间点 3:所有分块上传成功后调用此函数    
	    afterSendFile:function(){  
	        // 如果分块上传成功,则通知后台合并分块 
	        $.ajax({    
	            type:"POST",    
	            url:"../upload?param=mergeChunks",  //ajax 将所有片段合并成整体  
	            data:{    
	                fileName : fileName,  
	                fileMd5:fileMd5,  
	            },    
	            success:function(data){  
	                count++; // 每上传完成一个文件 count+1  
	                if(count<=filesArr.length-1){  
	                    uploader.upload(filesArr[count].id);// 上传文件列表中的下一个文件  
	                }  
	                // 合并成功之后的操作  
	            }    
	        });    
	    }    
	});  
}
/***************************************************** 监听分块上传过程中的三个时间点 end **************************************************************/  

export const WebUploadCreate = function(){
	/************************************************************ 初始化 WebUploader start ******************************************************************/  
    uploader = WebUploader.create({  
        auto:true,// 选择文件后是否自动上传  
        chunked: true,// 开启分片上传  
        chunkSize:10*1024*1024,// 如果要分片,分多大一片?默认大小为 5M  
        chunkRetry: 3,// 如果某个分片由于网络问题出错,允许自动重传多少次  
        threads: 3,// 上传并发数。允许同时最大上传进程数 [默认值:3]  
        duplicate : false,// 是否重复上传(同时选择多个一样的文件),true 可以重复上传  
        prepareNextFile: true,// 上传当前分片时预处理下一分片  
        swf: 'http://cdn.staticfile.org/webuploader/0.1.0/Uploader.swf',// swf 文件路径    
        server: '../upload/',// 文件接收服务端  
        fileSizeLimit:6*1024*1024*1024,//6G 验证文件总大小是否超出限制, 超出则不允许加入队列  
        fileSingleSizeLimit:3*1024*1024*1024,  //3G 验证单个文件大小是否超出限制, 超出则不允许加入队列  
        pick: {  
            id: '#picker', // 这个 id 是你要点击上传文件按钮的外层 div 的 id  
            multiple : true // 是否可以批量上传,true 可以同时选择多个文件  
        },    
        resize: false,  // 不压缩 image, 默认如果是 jpeg,文件上传前会先压缩再上传!  
        accept: {    
            // 允许上传的文件后缀,不带点,多个用逗号分割  
            extensions: "txt,jpg,jpeg,bmp,png,zip,rar,war,pdf,cebx,doc,docx,ppt,pptx,xls,xlsx",    
            mimeTypes: '.txt,.jpg,.jpeg,.bmp,.png,.zip,.rar,.war,.pdf,.cebx,.doc,.docx,.ppt,.pptx,.xls,.xlsx',    
        }    
    });    
    /************************************************************ 初始化 WebUploader end ********************************************************************/  
}

export const WebUploaderFileOperation = function(){
	// 当有文件被添加进队列的时候(点击上传文件按钮,弹出文件选择框,选择完文件点击确定后触发的事件)    
    uploader.on('fileQueued', function(file) { 
    	$('#thelist').append( '<div id="' + file.id + '"class="item">' +  
                        '<h4 class="info">' + file.name + '</h4>' +  
                        '<p class="state"> 等待上传...</p>' +  
                        '<a href="javascript:void(0);"class="btn btn-primary file_btn btnRemoveFile"> 删除 </a>' +  
                    '</div>' );
        // 限制单个文件的大小 超出了提示  
        if(file.size>3*1024*1024*1024){  
            alert("单个文件大小不能超过 3G");  
            return false;  
        }  
          
        /************* 如果一次只能选择一个文件,再次选择替换前一个,就增加如下代码 *******************************/  
        // 清空文件队列  
//      $('#thelist').html("");  
        // 清空文件数组  
        filesArr=[];  
        /************* 如果一次只能选择一个文件,再次选择替换前一个,就增加以上代码 *******************************/  
          
        // 将选择的文件添加进文件数组  
        filesArr.push(file);  
        $.ajax({    
            type:"POST",    
            url:"../upload/",  // 先检查该文件是否上传过,如果上传过,上传进度是多少  
            data:{    
                fileName : file.name  // 文件名  
            },    
            cache: false,  
            async: false,  // 同步  
            dataType:"json",    
            success:function(data){    
                // 上传过  
                if(data>0){  
                    // 上传过的进度的百分比  
                    oldJindu=data/100;  
                    // 如果上传过 上传了多少  
                    var jindutiaoStyle="width:"+data+"%";  
                    $('#thelist').append( '<div id="' + file.id + '"class="item">' +  
                        '<h4 class="info">' + file.name + '</h4>' +  
                        '<p class="state"> 已上传'+data+'%</p>' +  
                        '<a href="javascript:void(0);"class="btn btn-primary file_btn btnRemoveFile"> 删除 </a>' +  
                            '<div class="progress progress-striped active">' +  
                        '<div class="progress-bar"role="progressbar"style="'+jindutiaoStyle+'">' +  
                        '</div>' +  
                    '</div>'+  
                    '</div>' );  
                    // 将上传过的进度存入 map 集合  
                    map[file.id]=oldJindu;  
                }else{// 没有上传过  
                    $list.append( '<div id="' + file.id + '"class="item">' +  
                        '<h4 class="info">' + file.name + '</h4>' +  
                        '<p class="state"> 等待上传...</p>' +  
                        '<a href="javascript:void(0);"class="btn btn-primary file_btn btnRemoveFile"> 删除 </a>' +  
                    '</div>' );  
                }    
            }  
        });  
        uploader.stop(true);  
        // 删除队列中的文件  
        $(".btnRemoveFile").bind("click", function() {  
            var fileItem = $(this).parent();  
            uploader.removeFile($(fileItem).attr("id"), true);  
            $(fileItem).fadeOut(function() {  
                $(fileItem).remove();  
            });  
          
            // 数组中的文件也要删除  
            for(var i=0;i<filesArr.length;i++){  
                if(filesArr[i].id==$(fileItem).attr("id")){  
                    filesArr.splice(i,1);//i 是要删除的元素在数组中的下标,1 代表从下标位置开始连续删除一个元素  
                }  
            }  
        });  
    });    
           
    // 文件上传过程中创建进度条实时显示  
    uploader.on('uploadProgress', function(file, percentage) {  
        var $li = $( '#'+file.id ),  
            $percent = $li.find('.progress .progress-bar');  
        // 避免重复创建  
        if (!$percent.length){  
            $percent = $('<div class="progress progress-striped active">' +  
              '<div class="progress-bar"role="progressbar"style="width: 0%">' +  
              '</div>' +  
            '</div>').appendTo($li).find('.progress-bar');  
        }  
          
        // 将实时进度存入隐藏域  
        $("#jindutiao").val(Math.round(percentage * 100));  
          
        // 根据 fielId 获得当前要上传的文件的进度  
        var oldJinduValue = map[file.id];  
          
        if(percentage<oldJinduValue && oldJinduValue!=1){  
            $li.find('p.state').text('上传中'+Math.round(oldJinduValue * 100) + '%');  
            $percent.css('width', oldJinduValue * 100 + '%');  
        }else{  
            $li.find('p.state').text('上传中'+Math.round(percentage * 100) + '%');  
            $percent.css('width', percentage * 100 + '%');  
        }  
    });    
      
    // 上传成功后执行的方法  
    uploader.on('uploadSuccess', function(file) {
        // 上传成功去掉进度条  
        $('#'+file.id).find('.progress').fadeOut();  
        // 隐藏删除按钮  
        $(".btnRemoveFile").hide();  
        // 隐藏上传按钮  
        $("#startOrStopBtn").hide();  
        $('#'+file.id).find('p.state').text('文件已上传成功,系统后台正在处理,请稍后...');    
    });    
      
    // 上传出错后执行的方法  
    uploader.on('uploadError', function(file) {  
        errorUpload=true;  
        $('#startOrStopBtn').text('开始上传');  
        uploader.stop(true);  
        $('#'+file.id).find('p.state').text('上传出错,请检查网络连接');  
    });    
        
    // 文件上传成功失败都会走这个方法  
    uploader.on('uploadComplete', function(file) {  
        $( '#'+file.id ).find('.progress').fadeOut();
    });    
      
    uploader.on('all', function(type){ 
        if (type === 'startUpload'){  
            state = 'uploading';  
        }else if(type === 'stopUpload'){  
            state = 'paused';  
        }else if(type === 'uploadFinished'){  
            state = 'done';  
        }  
  
        if (state === 'uploading'){  
            $('#startOrStopBtn').text('暂停上传');  
        } else {  
            $('#startOrStopBtn').text('开始上传');  
        }  
    });
}

export const startOrStopUpload = function(){
	if (state === 'uploading'){  
        uploader.stop(true);  
    } else {  
        // 当前上传文件的文件名  
        var currentFileName;  
        // 当前上传文件的文件 id  
        var currentFileId;  
        //count=0 说明没开始传 默认从文件列表的第一个开始传  
        if(count==0){  
            currentFileName=filesArr[0].name;  
            currentFileId=filesArr[0].id;  
        }else{  
            if(count<=filesArr.length-1){  
                currentFileName=filesArr[count].name;  
                currentFileId=filesArr[count].id;  
            }  
        }  
          
        // 先查询该文件是否上传过 如果上传过已经上传的进度是多少  
        $.ajax({    
            type:"POST",    
            url:"../upload/",    
            data:{    
                fileName : currentFileName// 文件名  
            },    
            cache: false,  
            async: false,  // 同步  
            dataType:"json",    
            success:function(data){    
                // 如果上传过 将进度存入 map  
                if(data>0){  
                    map[currentFileId]=data/100;  
                }  
                // 执行上传  
                uploader.upload(currentFileId);  
            }    
        });  
    }  
}

webuploader.css

.webuploader-container {
	position: relative;
}
.webuploader-element-invisible {
	position: absolute !important;
	clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
    clip: rect(1px,1px,1px,1px);
}
.webuploader-pick {
	position: relative;
	display: inline-block;
	cursor: pointer;
	background: #00b7ee;
	padding: 10px 15px;
	color: #fff;
	text-align: center;
	border-radius: 3px;
	overflow: hidden;
}
.webuploader-pick-hover {
	background: #00a2d4;
}

.webuploader-pick-disable {
	opacity: 0.6;
	pointer-events:none;
}

效果

tim 20170814110524

学计算机单词

latency 潜伏 pipelining 流水线 Eliminate 消除 schemes 方案 格式 promotes 促进 protocol 协议 memos 备忘录 numerous 众多 variants 变种 dedicated 专用 charter 宪章 specification 规格 procedures 程序 suffix 后缀 spec 规范 spearheaded 带头 implementation 实现 significant重大的 significant证明 deployed 部署restraints限制innovate创新 maintain保持 paradigms 范式 URLs 网址 scheme 方案 proxy 代理 Subsequently 后来 features 特征 reduce 减少 mantra 口头禅 mandatory 强制的 minor 次要的 compatible 兼容 upgrade 升级 round-trip 往返 penalty 罚款 negotiation 谈判 significantly 显著的 widespread 广泛的 assumption 假设 interfere 干扰 hand-wringing 握手 agitated 激动 fierce 激烈 ciphers 密码 blacklist 黑名单 suite 套件 restrictions 限制 Application Layer Protocol Negotiation 应用层协议协商 promoted 提拔 marshaling 分送处理 instinctively 本能地arguments参数 superior 优越 handcraft 手工 intermixed 混合 compression 压缩 diminishes 减少 inspector 检察员 dissector 解剖器 Stream Identifier 流标识符 frame payload 帧有效载荷 fundamental 基本的 Multiplexed复合 directional 定向 sequence序列stream流 bi-directional sequence of frames双向帧序列 concurrently 同时 endpoint 端点 interleaving 交错 unilaterally 单方面 significant重大地 Priorities 优先级 restraints 限制 In short 简而言之 paradigm 范例 repetitive 重复 tricky 狡猾 vulnerable 弱势 encrypted 加密 crafted 将雕细作 exploit 利用 leak 泄漏receiver 接收器context上下文re-indexing 重新索引Huffman-encoded哈夫曼编码 drawbacks 缺点,outcoming弱点 Content-Length 内容长度 handshake 握手 bandwidth 带宽 tear down 拆除 Server push 服务器端推送explicitly明确地 spirit精神 peer 窥视 mandates 任务 hop-by-hop 逐条 debated 辩论 swinging 摇摆 ultimately 最终 inclusion 包容 Alternative替代 adoption 采用 suspect 疑似 potentially 可能 balancers 平衡器 maintenance 保养 asynchronously 异步 Opportunistic 机会主义somewhat 有些 debatable值得商榷 unauthenticated 未经验证 firmly 牢牢地 Blocked 阻止 forbids 禁止facilitate 促进 discarding 丢弃 parallel 平行 trim 修剪 toolbox 工具箱tricks技巧 justification理由 Spriting and inlining 精灵和内联, Sharding 拆分detrimental有害 futile 无用 doomed 注定outdated过时terms 条款 tech preview 技术预览 insecure 不安全 critiques 批评 forth 向前 implying 意味着illustrating说明

CSS积累

  1. 不同浏览器内核
/* Chrome, Opera, Safari */
::webkit-input-placeholder {
   color: #ff6600; /*orange*/
}
/* Firefox 19+*/
::-moz-placeholder {
  color: #ff6600;
  opacity: 1; /*提高透明度*/
}

/* Firefox 18 and below*/
:-moz-placeholder {
  color: #ff6600;
   opacity: 1;
}
/* MS IE 10+ */
:-ms-input-placeholder {
   color: #ff6600;
   opacity: 1;
}
  1. 屏幕自适应
@media screen and (max-width: ${BREAKPOINT - 1}px) {
    padding: ${MOBILE_PADDING}px;
  }

Markdown语法积累

1. 制作一份待办事宜 Todo 列表

  • 支持以 PDF 格式导出文稿
  • 改进 Cmd 渲染算法,使用局部渲染技术提高渲染效率
  • 新增 Todo 列表功能
  • 修复 LaTex 公式渲染问题
  • 新增 LaTex 公式编号功能

2. 高亮一段代码[^code]

@requires_authorization
class SomeClass:
    pass

if __name__ == '__main__':
    # A comment
    print 'hello world'

3. 绘制表格

项目 价格 数量
计算机 $1600 5
手机 $12 12
管线 $1 234

Little tips

鼠标使用卡顿,调节BlueTooth第一, wifi第二,就可以解决了

image

image

ES6学习笔记

  1. 使用letconst代替原有的var定义变量
let sum = 0;
for(const i=0;i<array.length;i++){
  sum += array[i];
}
  1. 使用for ... of代替原有的for循环
for(for list of lists){
  console.log(list);
}
  1. 使用箭头函数=> 代替原来的function, 并去掉关键字return.
# 无参, 直接用()代替
() => x
# 有参, 直接使用参数返回
x => x*x;
(x, y) => (x=1, y=2)
  1. 函数内参数可以设置默认值
# 单个参数
function(x=1, y=2)
# 数组赋值
function([x, y] = [1,2])
# 对象赋值
function({x, y} = {1,2})
# 嵌套赋值
function({x,[y,z]} = {1, [2, 3]})
  1. 引入类Class, 每个类必须定义构造方法constructor, 类的方法不需要原型关键字prototype属性赋值,而且方法之间不要,分割
Classs A {
  constructor(){
  }
 
  getX(){
  }
}
  1. 引入类的继承extends概念, 子类可以继承父类的所有方法, 使用super()函数继承
Class B extends A {
  constructor(){
   super();
  }
  getX(){
  }
}
  1. 引入this对象, 默认是全局的变量, 比较复杂, 使用that = this方法变为局部变量
that = this
  1. template string, HTML的写法, 使用<h1></h1>来编写HTML, 使用${num}来显示变量
# 一行
`<h1>${title}</h1>`
# 多行
`
<h1>
   <p>${content}</p>
</h1>
`
  1. 直接赋值
let a = "a";
let b = "b"
let array = [a, b];  
# 原来的写法是 var array = [a:a, b:b];

Darams

The freedom to make my own mistakes 能自由地犯错 was all I ever wanted只是我一生追求 Mence Rayder, you've been called the King-beyound-the-Wall 曼斯 雷德 你被成为境外之王 Westeros only have one king维斯特洛只有一个真正的王 Bend the knee, I promise you mercy下跪 我答应宽宏处理 kneel and live 下跪即活着 This was my home for many years这里曾是我家园多年 I wish you good fortune in the wars to come在即将到来的战争中, 我祝你好运 We all must choose我们都必须进行选择Man or woman, young or old不管男或女 不管老或幼 lord or peasant, our choices are the same 不管王或民,我们选择皆同we choose light or we choose darkness选择光明或是黑暗we choose good or we choose evil选择正义或是邪恶 we choose the true god or the false选择真神或是假神

彦萍和我谈心,说我要是心情不好,或者是我不想理人的话,会表现的很明显,然后说话也会很平淡,然后没说几句她就会走掉了,然后如果我心情很好,那么和我聊天会很开心,我真的是表情这么这么明显的人吗,仿佛一切都发生在脸上

Mac使用积累

mac 使用总结

  • control + space -- 切换中英文输入法
  • command + space -- 调出 spotlight 快速查找文件,应用,网页
  • command + q -- 彻底结束应用程序
  • control + c -- 结束终端
  • control + 鼠标点击 -- 鼠标右键
  • 左键长按应用,弹出框,选择选项,固定在dock栏
  • 清理屏幕 clear
  • install mysql in mac: brew install mysql.
  • login in mysql without enter a password:mysql -uroot;
  • create database in mysql: create database if not exist asics3;
  • cd go/src/github.com/theplant/aigle/aigleapp
  • 快速回到根目录/Usr/apple --cd ~
  • tab键快速补齐
  • 常用工作目录
    cd go/src/github.com/theplant/
  • vscode 安装命令行插件code, 进入目录之后,直接输入code . 在vscode打开当前目录
  • pwd显示当前文件目录,编辑zsh环境变量 zshrc文件
`vi ~/.zshrc`

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.