├── .gitignore ├── CNAME ├── README.md ├── _config.yml ├── _includes ├── custom │ └── comment.html ├── footer.html ├── head.html ├── header.html ├── icon-github.html ├── icon-github.svg ├── icon-twitter.html └── icon-twitter.svg ├── _layouts ├── default.html ├── page.html └── post.html ├── _posts ├── 2015-12-28-javascript-protytype.md ├── 2015-12-29-javascript-this.md ├── 2015-12-30-javascript-clouse.md ├── 2016-01-01-javascript-object-create.md └── 2016-03-01-javascript-cross-domain.md ├── _sass ├── _base.scss ├── _layout.scss └── _syntax-highlighting.scss ├── about.md ├── api └── list.json ├── css └── main.scss ├── feed.xml ├── index.html ├── spider ├── index.js └── package.json └── wechatApp ├── app.js ├── app.json ├── app.wxss ├── pages ├── index │ ├── index.js │ ├── index.wxml │ └── index.wxss ├── logs │ ├── logs.js │ ├── logs.json │ ├── logs.wxml │ └── logs.wxss └── main │ ├── main.js │ ├── main.wxml │ └── main.wxss └── utils └── util.js /.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .sass-cache 3 | .jekyll-metadata 4 | node_modules/ 5 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | blog.rccoder.net 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rccoder's blog 2 | 3 | * **链接:** [blog.rccoder.net](http://blog.rccoder.net) 4 | 5 | *其实你直接访问 [Issues](https://github.com/rccoder/blog/issues) 更加方便* 6 | 7 | * **主题:**: Technology and Life 8 | * **幼稚的老博客:** [life.rccoder.net](http://life.rccoder.net) 9 | 10 | ## 订阅点赞 11 | 12 | * 关注订阅请 **watch** 13 | * 点赞点赞请 **star** 14 | 15 | ## 版权声明 16 | 17 | * 请尊重辛勤劳动 18 | * 禁止不署名完全转载,可单独通过下面的捐赠付版权费 19 | * 建议署名并进行摘要性质转载 20 | 21 | ## 捐赠 22 | 23 | 写文不易,赠我一杯咖啡增强一下感情可好? 24 | 25 | ![alipay](https://cloud.githubusercontent.com/assets/7554325/13387514/4e6c3b42-def2-11e5-849c-90c5f1109fe7.png) 26 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Welcome to Jekyll! 2 | # 3 | # This config file is meant for settings that affect your whole blog, values 4 | # which you are expected to set up once and rarely need to edit after that. 5 | # For technical reasons, this file is *NOT* reloaded automatically when you use 6 | # 'jekyll serve'. If you change this file, please restart the server process. 7 | 8 | # Site settings 9 | title: Rccoder 10 | email: rccoder.net@gmail.com 11 | description: > # this means to ignore newlines until "baseurl:" 12 | 在对的时间做正确的事。欢迎你订阅本[博客](https://github.com/rccoder/blog):Watch + Star 13 | baseurl: "" # the subpath of your site, e.g. /blog 14 | url: "http://blog.rccoder.net" # the base hostname & protocol for your site 15 | weibo_username: rccoder 16 | github_username: rccoder 17 | 18 | # Build settings 19 | markdown: kramdown 20 | kramdown: 21 | input: GFM 22 | 23 | user: rccoder 24 | repo: blog -------------------------------------------------------------------------------- /_includes/custom/comment.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 |
12 | -------------------------------------------------------------------------------- /_includes/footer.html: -------------------------------------------------------------------------------- 1 | 39 | -------------------------------------------------------------------------------- /_includes/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %} 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /_includes/header.html: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /_includes/icon-github.html: -------------------------------------------------------------------------------- 1 | {% include icon-github.svg %}{{ include.username }} 2 | -------------------------------------------------------------------------------- /_includes/icon-github.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /_includes/icon-twitter.html: -------------------------------------------------------------------------------- 1 | {% include icon-twitter.svg %}{{ include.username }} 2 | -------------------------------------------------------------------------------- /_includes/icon-twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% include head.html %} 5 | 6 | 7 | 8 | {% include header.html %} 9 | 10 |
11 |
12 | {{ content }} 13 |

评论:

14 | {% include custom/comment.html %} 15 |
16 |

17 | 上述评论由petal获取得到, 如果你想评论本文章,请去这里评论,内容将自动同步. 18 |

19 |

对了,不要忘记star一下

20 |
21 |
22 |
23 | {% include footer.html %} 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 |
5 | 6 |
7 |

{{ page.title }}

8 |
9 | 10 |
11 | {{ content }} 12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /_layouts/post.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 |
5 | 6 |
7 |

{{ page.title }}

8 | 9 |
10 | 11 |
12 | {{ content }} 13 |
14 | 15 |
16 | -------------------------------------------------------------------------------- /_posts/2015-12-28-javascript-protytype.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "JavaScript 之原型周边" 4 | date: 2015-12-28 18:26:42 +0800 5 | categories: JavaScript 6 | github_issues: 5 7 | --- 8 | 9 | ## 简介 10 | 11 | 如果之间学习过`cpp` 、`java` 之类的语言,都会知道他们是可以基于类 `class` 进行继承的, 在`JavaScript` 中,并没有类继承这个概念,要实现`JavaScript` 中的继承,需要原型来帮助。 12 | 13 | 比如在下面的这段代码中: 14 | 15 | ``` javascript 16 | 17 | function Foo () { 18 | 19 | this.value = 1; 20 | 21 | }; 22 | 23 | Foo.prototype = { 24 | 25 | method: function () {}; 26 | 27 | }; 28 | 29 | //设置Bar的原型为Foo()的实例 30 | 31 | Bar.prototype = new Foo(); 32 | 33 | Bar.prototype.foo = 'Hello World'; 34 | 35 | //修正Bar的constructor 36 | 37 | Bar.prototype.constructor = Bar; 38 | 39 | //创建一个Bar的实例 40 | 41 | var test = new Bar(); 42 | 43 | ``` 44 | 45 | 在这段代码中,就一直维护着一个原型链,抽象化的理解起来可能是这样的: 46 | 47 | ``` 48 | test [Bar的实例] 49 | Bar.prototype [Foo的实例] 50 | {foo: 'Hello World!'} 51 | Foo.prototype 52 | {method: function(){}} 53 | Object.prototype 54 | {...} 55 | ``` 56 | 57 | 很好去理解,test 是从`Bar.prototype` 和 `Foo.prototype` 中继承下来的,所以他能够访问`Foo` 实例属性中的`value` 。 58 | 59 | 需要注意的是,在 `new Bar` 操作中,并不会重新创建一个`Foo` 的实例,而是会重复的使用在他的原型上的那个实例。 60 | 61 | 除此之外,原型是共享的,如果我们有`Foo.prototype = Bar.prototype` 的写法,改变这两个对象任何一个的原型都会影响另外一个,这在大多的情况下是不可取的。 62 | 63 | 当对象查找一个属性的时候,他会沿着原型链一直往上追踪,直到直到为之。当然 `Object.prototypr` 就是这个链的最后一层了,如果还是没找到,就会返回`undefined` 。 64 | 65 | ## hasOwnProperty 66 | 67 | 在性能方面,原则上应该尽量避免原型链太长。正如用`for ... in ...` 去遍历的时候,他会去遍历整个原型链,这往往在比较高的性能要求或者普通的遍历中是不可取的。 68 | 69 | 为了去判断一个对象包含的属性是他本身就有的还是在原型链上的,需要使用继承在`Object prototype` 上的`hasOwnProperty` 方法。 70 | 71 | 比如在下面的例子中 72 | 73 | ``` javascript 74 | Oboject.prototype.bar = 1; 75 | 76 | var foo = { 77 | value: 2; 78 | }; 79 | 80 | foo.var //通过原型链继承自Object,输出1 81 | 'bar' in foo; //通过整个原型链进行查找,输出true 82 | 83 | foo.hasOwnProperty('bar'); //false 84 | foo.hasOwnProperty('value') //true 85 | ``` 86 | 87 | 在`for ... in ...` 的遍历中,一般建议使用`hasOwnProperty` 的方法。 88 | 89 | 需要注意的是: `javascript`并没有对`hasOwnProperty` 做相关的保护,如果恰巧对象有这个叫做`hasOwnProperty` 的属性,那么产生的结果应该不是我们所期待的。比如像下面这样: 90 | 91 | ``` javascript 92 | var foo = { 93 | hasOwnProperty: function () { return flase}; 94 | bar: '1'; 95 | }; 96 | 97 | foo.hasOwnProperty('bar') //正如你猜的那样,返回的值永远是false 98 | ``` 99 | 100 | 这时候可能需要做的就是调用外部的`hasOwnproperty`, 对,就是用`call` 或者`apply`。像下面这样: 101 | 102 | ``` javascript 103 | //返回true 104 | Object.hasOwnProperty.call(foo, 'bar'); 105 | Object.hasOwnProperty.apply(foo, ['bar']); 106 | ``` -------------------------------------------------------------------------------- /_posts/2015-12-29-javascript-this.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "JavaScript 之 this 指向问题" 4 | date: 2015-12-29 18:26:42 +0800 5 | categories: JavaScript 6 | github_issues: 2 7 | --- 8 | 9 | ## 1. 一等公民对象——函数 10 | 11 | 在提this指向问题之前,肯定是有必要说明一等公民对象`function` ,既然`function`是对象,那么就能像普通的值一样传递。嗯,在匿名函数中,这样的做法是非常常见的。 12 | 13 | 函数会在代码的运行前进行解析,这就保证了函数存在于当前上下文的任意一个地方,即在函数定义的前面去调用也是正确的。 14 | 15 | ``` javascript 16 | foo(); 17 | 18 | function foo () {}; 19 | ``` 20 | 21 | 函数是一个对象,所以我们常常会看见把一个匿名的函数给一个值。 22 | 23 | ``` javascript 24 | var foo = function () { 25 | 26 | }; 27 | ``` 28 | 29 | 赋值语句只有在执行的时候才会运行,也就是说所看到的`var foo = 1` 是分为两部分的: 30 | 31 | ``` javascript 32 | var foo; 33 | ... 34 | foo = 1; 35 | ... 36 | ``` 37 | 38 | 所以可能会出现下面的问题 39 | 40 | ``` javascript 41 | foo; //undefined 42 | foo(); //TypeError 43 | var foo = function () { 44 | console.log(1); 45 | } 46 | ``` 47 | 48 | 因为他和下面的写法是一样的 49 | 50 | ``` javascript 51 | var foo; 52 | 53 | foo; 54 | 55 | foo(); 56 | 57 | foo = function () { 58 | console.log(1); 59 | } 60 | ``` 61 | 62 | 正常的,我们这样写是没有问题的 63 | 64 | ``` javascript 65 | foo; // undefined 66 | 67 | var foo = function () { 68 | console.log(1); 69 | } 70 | 71 | foo(); // 1 72 | ``` 73 | 74 | ## 2. this指向问题 75 | 76 | `this` 是和执行上下问环境息息相关的。他是上下文环境的一个属性,而不是某个变量对象的属性。 77 | 78 | 这个特点很重要,因为和变量不同,this是没有一个类似搜寻变量的过程。当你在代码中使用了this,这个 79 | 80 | this的值就直接从执行的上下文中获取了,而不会从作用域链中搜寻。this的值只取决中进入上下文时的情 81 | 82 | 况。 83 | 84 | 这样,`javascript`中的`this`和一般语言中的`this`是有点区别的,在不同的情况下,指向也有所不同: 85 | 86 | 1. 全局范围内 87 | 88 | 指向的是全局对象。在普通浏览器中指向的是`window`, 在Node中指向的是全局对象`global`(全局环境中) 或者`module.exports`(模块环境中)。 89 | 90 | 2. 函数调用中 91 | 92 | 在普通的函数调用中,this依旧指向全局对象。(这个设计似乎并没有什么作用,应该是一个错误的设计。并且在很多的情况下不注意都会引来很多的麻烦) 93 | 94 | ``` javascript 95 | Foo.method = function () { 96 | function test () { 97 | //这里的this指向的不是Foo.而是全局对象 98 | } 99 | } 100 | ``` 101 | 102 | 一般我们会创建一个局部的变量去指代上一层的对象 103 | 104 | ``` javascript 105 | Foo.method = function () { 106 | that = this; //按照下面一条规则,这儿的this指向的是Foo 107 | function (test) { 108 | // that 109 | } 110 | } 111 | ``` 112 | 113 | 3. 方法调用中 114 | 115 | 指向调用它的对象 116 | 117 | 4. 调用构造函数 118 | 119 | 指向新创建的对象 120 | 121 | 5. 显式设置`this` 122 | 123 | 指向显式指向的对象。即指向`call`或者`apply`的第一个参数。 124 | 125 | **注意:** 126 | 127 | 像下面这样对方法进行赋值的时候,函数内`this`的指向也不是赋值时所调用方法的对象。 128 | 129 | ``` javascript 130 | var test = Obj.method(); 131 | 132 | test(); // 第二条规则,this指向的不是Obj 133 | ``` 134 | -------------------------------------------------------------------------------- /_posts/2015-12-30-javascript-clouse.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "JavaScript之闭包相关" 4 | date: 2015-12-30 18:26:42 +0800 5 | categories: JavaScript 6 | github_issues: 3 7 | --- 8 | 9 | > Like most modern programming languages, JavaScript uses lexical scoping. This means that functions are executed using the variable scope that was in effect when they were defined, not the variable scope that is in effect when they are invoked. In order to implement lexical scoping, the internal state of a JavaScript function object must in- clude not only the code of the function but also a reference to the current scope chain. (Before reading the rest of this section, you may want to review the material on variable scope and the scope chain in §3.10 and §3.10.3.) This combination of a function object and a scope (a set of variable bindings) in which the function’s variables are resolved is called a closure in the computer science literature. (This is an old term that refers to the fact that the function’s variables have bindings in the scope chain and that therefore the function is “closed over” its variables.) 10 | > 11 | > Technically, all JavaScript functions are closures: they are objects, and they have a scope chain associated with them. Most functions are invoked using the same scope chain that was in effect when the function was defined, and it doesn’t really matter that there is a closure involved. Closures become interesting when they are invoked under a different scope chain than the one that was in effect when they were defined. This happens most commonly when a nested function object is returned from the function within which it was defined. There are a number of powerful programming techniques that involve this kind of nested function closures, and their use has become relatively common in JavaScript programming. Closures may seem confusing when you first en- counter them, but it is important that you understand them well enough to use them comfortably. 12 | > 13 | > *JavaScript, The Definite Guide* 14 | 15 | 翻译成中文的话也许是这样: 16 | 17 | 和大多数的现代化编程语言一样,`JavaScript`是采用词法作用域的,这就意味着函数的执行依赖于函数定义的时候所产生(而不是函数调用的时候产生的)的变量作用域。为了去实现这种词法作用域,`JavaScript`函数对象的内部状态不仅包含函数逻辑的代码,除此之外还包含当前作用域链的引用。函数对象可以通过这个作用域链相互关联起来,如此,函数体内部的变量都可以保存在函数的作用域内,这在计算机的文献中被称之为闭包。 18 | 19 | 从技术的角度去将,所有的`JavaScript`函数都是闭包:他们都是对象,他们都有一个关联到他们的作用域链。绝大多数函数在调用的时候使用的作用域链和他们在定义的时候的作用域链是相同的,但是这并不影响闭包。当调用函数的时候闭包所指向的作用域链和定义函数时的作用域链不是同一个作用域链的时候,闭包become interesting。这种interesting的事情往往发生在这样的情况下: 当一个函数嵌套了另外的一个函数,外部的函数将内部嵌套的这个函数作为对象返回。一大批强大的编程技术都利用了这类嵌套的函数闭包,当然,`javascript`也是这样。可能你第一次碰见闭包觉得比较难以理解,但是去明白闭包然后去非常自如的使用它是非常重要的。 20 | 21 | 通俗点说,在程序语言范畴内的闭包是指函数把其的变量作用域也包含在这个函数的作用域内,形成一个所谓的“闭包”,这样的话外部的函数就无法去访问内部变量。所以按照第二段所说的,严格意义上所有的函数都是闭包。 22 | 23 | 需要注意的是:我们常常所说的闭包指的是让外部函数访问到内部的变量,也就是说,按照一般的做法,是使内部函数返回一个函数,然后操作其中的变量。这样做的话一是可以读取函数内部的变量,二是可以让这些变量的值始终保存在内存中。 24 | 25 | `JavaScript`利用闭包的这个特性,就意味着当前的作用域总是能够访问外部作用域中的变量。 26 | 27 | ``` javascript 28 | function counter (start) { 29 | var count = start; 30 | return { 31 | add: function () { 32 | count ++; 33 | }, 34 | get: function () { 35 | return count; 36 | }, 37 | }; 38 | } 39 | 40 | var foo = counter (4); 41 | 42 | foo.add(); 43 | foo.get() //5 44 | ``` 45 | 46 | 上面的代码中,`counter`函数返回的是两个闭包(两个内部嵌套的函数),这两个函数维持着对他们外部的作用域`counter`的引用,因此这两个函数没有理由不可以访问`count` ; 47 | 48 | 在`JavaScript`中没有办法在外部访问`count`(`JavaScript`不可以强行对作用域进行引用或者赋值),唯一可以使用的途径就是以这种闭包的形式去访问。 49 | 50 | 对于闭包的使用,最长见的可能是下面的这个例子: 51 | 52 | ``` javascript 53 | for (var i = 0; i < 10; i++) { 54 | setTimeout (function (i) { 55 | console.log (i); //10 10 10 .... 56 | }, 1000); 57 | } 58 | ``` 59 | 60 | --在上面的例子中,当`console.log`被调用的时候,匿名函数保持对外部变量的引用,这个时候`for` 循环早就已经运行结束,输出的`i`值也就一直是`10`。但这在一般的意义上并不是我们想要的结果。-- 61 | 62 | setTimeout 中的 i 都共享的是这个函数中的作用域, 也就是说,他们是共享的。这样的话下一次循环就使得 i 值进行变化,这样共享的这个 i 就会发生变化。这就使得输出的结果一直是 10 63 | 64 | 为了获得我们想要的结果,我们一般是这样做: 65 | 66 | ``` javascript 67 | for (var i = 0; i < 10; i++) { 68 | (function (e) { 69 | setTimeout (function () { 70 | console.log (e); 71 | }, 1000); 72 | })(i); 73 | } 74 | ``` 75 | 76 | 外部套着的这个函数不会像`setTimeout`一样延迟,而是直接立即执行,并且把`i`作为他的参数,这个时候`e`就是对`i`的一个拷贝。当时间达到后,传给`setTimeout`的时候,传递的是`e`的引用。这个值是不会被循环所改变的。 77 | 78 | 除了上面的写法之外,这样的写法显然也是没有任何问题的: 79 | 80 | ``` javascript 81 | for (var i = 0; i < 10; i++) { 82 | setTimeout((function(e) { 83 | return function() { 84 | console.log (e); 85 | } 86 | })(i), 1000); 87 | } 88 | ``` 89 | 90 | 或许,还可以借助这个故事理解一下: 91 | 92 | > I'm a big fan of analogy and metaphor when explaining difficult concepts, so let me try my hand with a story. 93 | > 94 | > **Once upon a time:** 95 | > 96 | > There was a princess... 97 | > 98 | > ``` 99 | > function princess() { 100 | > ``` 101 | > 102 | > She lived in a wonderful world full of adventures. She met her Prince Charming, rode around her world on a unicorn, battled dragons, encountered talking animals, and many other fantastical things. 103 | > 104 | > ``` 105 | > var adventures = []; 106 | > 107 | > function princeCharming() { /* ... */ } 108 | > 109 | > var unicorn = { /* ... */ }, 110 | > dragons = [ /* ... */ ], 111 | > squirrel = "Hello!"; 112 | > ``` 113 | > 114 | > But she would always have to return back to her dull world of chores and grown-ups. 115 | > 116 | > ``` 117 | > return { 118 | > ``` 119 | > 120 | > And she would often tell them of her latest amazing adventure as a princess. 121 | > 122 | > ``` 123 | > story: function() { 124 | > return adventures[adventures.length - 1]; 125 | > } 126 | > }; 127 | > } 128 | > ``` 129 | > 130 | > But all they would see is a little girl... 131 | > 132 | > ``` 133 | > var littleGirl = princess(); 134 | > ``` 135 | > 136 | > ...telling stories about magic and fantasy. 137 | > 138 | > ``` 139 | > littleGirl.story(); 140 | > ``` 141 | > 142 | > And even though the grown-ups knew of real princesses, they would never believe in the unicorns or dragons because they could never see them. The grown-ups said that they only existed inside the little girl's imagination. 143 | > 144 | > But we know the real truth; that the little girl with the princess inside... 145 | > 146 | > ...is really a princess with a little girl inside. 147 | > 148 | > *http://stackoverflow.com/a/6472397/4681656* 149 | -------------------------------------------------------------------------------- /_posts/2016-01-01-javascript-object-create.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "JavaScript之对象创建" 4 | date: 2016-01-01 18:26:42 +0800 5 | categories: JavaScript 6 | github_issues: 4 7 | --- 8 | 9 | ## 1.构造函数模式 10 | 11 | `JavaScript`中的构造函数是通过`new`调用的,也就是说,通过`new`关键字调用的函数都被认为是构造函数。 12 | 13 | 在构造函数的内部,`this`的指向是新创建的对象`Object`。 14 | 15 | 如果构造函数没有显式的`return`表达式,则会隐式的返回新创建的对象——`this`对象。 16 | 17 | ``` javascript 18 | function Foo () { 19 | this.name = 'rccoder'; 20 | } 21 | 22 | Foo.prototype.test = function () { 23 | console.log (this.name); 24 | } 25 | 26 | var bar = new Foo(); 27 | 28 | bar.name; // rccoder 29 | bar.test(); // rccoder 30 | ``` 31 | 32 | 在构造函数中,显式的`return`会影响返回的值,但是仅限于返回的是 **一个对象**。**当返回值不是一个对象的时候,实际上会返回一个新创建的对象;当返回值就是一个对象的时候,返回的不是新创建的对象,而是本身就要返回的那个对象** 33 | 34 | ``` javascript 35 | function Foo () { 36 | return 2; 37 | } 38 | 39 | new Foo(); // Foo {} 返回的不是2,而是新创建了一个对象 40 | 41 | function Bar () { 42 | this.name = 'rccoder'; 43 | return { 44 | foo: 1 45 | } 46 | } 47 | 48 | new Bar(); // Object {foo: 1} 返回要返回的那个对象 49 | (new Bar()).name // undefined 50 | (new Bar()).foo // 1 51 | ``` 52 | 53 | 构造函数模式主要有以下几个特点: 54 | 55 | 1. 没有显式的返回对象 56 | 2. 直接将属性和方法赋值给`this`对象 57 | 3. 没有`return`语句 58 | 59 | > 通过`new`关键字调用的函数都被认为是构造函数。 60 | 61 | `new`之后产生的是一个新的对象,可以在`new`的时候传递参数,并且把这个参数的值赋值给`this` 指针,这样,传递进去的内容,就变成了新产生的对象的属性或者方法。 62 | 63 | 为了让代码看起来更加的“优雅”,构造函数的首字母都是大写。 64 | 65 | 除此之外,用构造函数产生的实例中,他的原型都会默认的包含一个`constructor`属性,会指向构造函数。这样就能够知道这个对象是从哪儿创建的,也就是说能够区分这个对象的类型了(下面的工厂模式就无法区分对象的类型)。 66 | 67 | ``` javascript 68 | function Foo () { 69 | this.value = 1; 70 | } 71 | 72 | test = new Foo (); 73 | 74 | test.constructor == Foo (); 75 | ``` 76 | 77 | 78 | 79 | 当然,构造函数也是可以直接执行的,而不是一定要`new`,直接执行的化“构造函数”中的`this`指向的就不再是新产生的对象了(实际上这种情况下就和普通的函数一样,并不会产生新的对象),往往在浏览器中是`window`. 80 | 81 | 构造函数在每次`new`的时候产生的实例都是重新创建的,因此不同实例上的同名函数是不相等的。 82 | 83 | ``` javascript 84 | function Foo () { 85 | this.test = function () { 86 | 87 | }; 88 | } 89 | 90 | var a = new Foo(); 91 | var b = new Foo(); 92 | 93 | a.test === b.test // false 94 | ``` 95 | 96 | 所以说,构造函数每次`new`都是产生一个新的实例,并且这个实例的属性和方法是独享的。这样往往造成了一些浪费(属性是独有的可以理解,但是就方法而言,大多数往往是一样的,这和我们想要的可能有点差别)。 97 | 98 | ## 2.工厂模式 99 | 100 | 为了不去使用`new`关键字,上面提到的构造函数必须显式的返回。当前这个时候就可以理解为不是构造函数了。 101 | 102 | ``` javascript 103 | function Foo () { 104 | var value = 1; 105 | 106 | return { 107 | method: function () { 108 | return value; 109 | } 110 | }; 111 | 112 | }; 113 | 114 | Foo.prototype = { 115 | foo: function () { 116 | 117 | } 118 | }; 119 | 120 | new Foo(); 121 | Foo(); 122 | ``` 123 | 124 | 上面加不加`new`的返回结果是完全一样的,都是一个新创建的,拥有`method`属性的对象。嗯。如果对闭包有所理解的话,他返回的就是一个闭包! 125 | 126 | 需要注意的是,上面返回的是一个包含`method`属性的自定义对象,所以他并不返回`Foo.prototype`. 127 | 128 | ``` javascript 129 | (new Foo()).foo // undefined 130 | (Foo()).foo // undefined 131 | ``` 132 | 133 | 按照正常人的思路,一般选择用`new`来调用函数总是显得很奇怪,这也估计就是大多人说不要使用`new`关键字来调用函数的原因了,因为如果忘记`new`就会产生难以察觉的错误。 134 | 135 | 嗯,是时候引出**工厂模式**了: 136 | 137 | ``` javascript 138 | function Foo () { 139 | var obj = {}; 140 | obj.value = 'rccoder'; 141 | 142 | var privateValue = 2; 143 | 144 | obj.method = function (value) { 145 | this.value = value; 146 | }; 147 | 148 | obj.getPrivate = function () { 149 | return privateValue; 150 | }; 151 | 152 | return obj; 153 | } 154 | ``` 155 | 156 | 就像上面的代码一样,有个工厂,就这样生产出了一个个的工人。工厂模式解决了多个比较相似的对象重复创建的问题。但是这个创建只单纯的一个创建,但并不知道这个对象是从哪里创建的,也就是说无法去区分这个对象的类型。 157 | 158 | 当然还有一些其他的缺点,比如由于新创建的对象只是简单的创建,所以不能共享原型上的方法,如果要实现所谓的继承,就要从另外的一个对象去拷贝所有的属性...嗯,他放弃了原型,为了去防止`new`带来的问题。 159 | 160 | ## 3.原型模式 161 | 162 | 在构造函数模式中提到每次`new`之后创建的新的对象是互相独立的,是独享的。 163 | 164 | > 构造函数每次`new`都是产生一个新的实例,并且这个实例的属性和方法是独享的。这样往往造成了一些浪费(属性是独有的可以理解,但是就方法而言,大多数往往是一样的,这和我们想要的可能有点差别) 165 | 166 | 就最后一句而言,我们或许可以这样写: 167 | 168 | ``` javascript 169 | function Foo (value) { 170 | this.value = value; 171 | this.method = method; 172 | } 173 | 174 | function method () { 175 | console.log (this.value); 176 | } 177 | ``` 178 | 179 | 这样把方法去放在外面,在构造函数里面去调用这个函数,好像就`hack`的解决了上面的问题。但是这个函数好像就是全局函数了,并且和`Foo()`看上去并不怎么愉快的是一家人,谈封装也就有些牵强。 180 | 181 | 这种去共享方法的问题用`prototype`看似就可以解决,毕竟他产生的属性和方法是所有产生的实例所共享的。 182 | 183 | ``` javascript 184 | function Foo () { 185 | ... 186 | }; 187 | 188 | Foo.prototype.value = 'rccoder'; 189 | Foo.prototype.method = function () { 190 | console.log (this.value); 191 | }; 192 | 193 | var test = new Foo (); 194 | test.method(); // rccoder 195 | ``` 196 | 197 | 这样看起来好像是可行的,当需要找某个对象的属性的时候,往往直接看有没有这个属性,没有的话再按照原型链向上寻找,而不是去寻找构造函数。 198 | 199 | 原型是动态的,所以不要随便的去修改原型。这个修改后会立即影响实例的结果。 200 | 201 | > 如果我们有`Foo.prototype = Bar.prototype` 的写法,改变这两个对象任何一个的原型都会影响另外一个,这在大多的情况下是不可取的。 202 | 203 | 一般情况下不建议对原型做修改,因为很可能由于代码量太多导致维护太困难。 204 | 205 | 另外,还记得用原型模式的初衷吗?是要公用方法,而不是公用属性。纯粹的用原型会同样的公用属性,这在很多情况下看起来是很郁闷的。所以可能需要我们把原型和构造函数结合起来使用。 206 | 207 | ## 4.优雅混合使用构造函数与原型 208 | 209 | 这或许是比较理想话的使用方法了,用构造函数来区分独享的属性,用原型来共享大家都用的方法。 210 | 211 | ``` javascript 212 | function Foo (value1, value2) { 213 | this.value1 = value1; 214 | this.value2 = value2; 215 | } 216 | 217 | Foo.prototype.method = function () { 218 | console.log (this.value1) 219 | }; 220 | 221 | test1 = new Foo (2, 3); 222 | test1.method(); // 2 223 | 224 | test2 = new Foo (4, 5); 225 | test2.method() // 4 226 | ``` 227 | 228 | 哦,对了,你可能会看见这样写上面的代码 229 | 230 | ``` javascript 231 | function Foo (value1, value2) { 232 | this.value1 = value1; 233 | this.value2 = value2; 234 | } 235 | 236 | Foo.prototype = { 237 | constructor: Foo, 238 | method: function () { 239 | console.log (this.value1); 240 | } 241 | } 242 | 243 | test = new Foo (2, 3); 244 | test.method(); 245 | ``` 246 | 247 | 别怕,这只是覆盖了`Foo`的原型而已,是真的覆盖到连`constructor`是谁都不认识了,所以需要手动的是想一下,指向谁呢?正常人的话指向的应该是构造函数吧。 248 | 249 | 250 | 251 | > 参考资料: 252 | > 253 | > 1. JavaScript密码花园 254 | > 2. [JavaScript 原型理解与创建对象应用-于江水的博客](http://yujiangshui.com/javascript-prototype-and-create-object/) 255 | 256 | 257 | 258 | 原文链接:http://life.rccoder.net/javascript/1216.html -------------------------------------------------------------------------------- /_posts/2016-03-01-javascript-cross-domain.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "浅谈浏览器端JavaScript跨域解决方法" 4 | date: 2016-03-01 15:26:42 +0800 5 | categories: JavaScript 6 | github_issues: 5 7 | --- 8 | 由于安全的原因,浏览器做了很多方面的工作,由此也就引入了一系列的跨域问题,需要注意的是: 9 | 10 | **跨域并非浏览器限制了发起跨站请求,而是跨站请求可以正常发起,但是返回结果被浏览器拦截了。最好的例子是 `crsf` 跨站攻击原理,请求是发送到了后端服务器无论是否跨域!注意:有些浏览器不允许从HTTPS的域跨域访问HTTP,比如Chrome和Firefox,这些浏览器在请求还未发出的时候就会拦截请求,这是一个特例** 11 | 12 | ## 1. JSONP 13 | 14 | `JSONP`的全称是 "JSON With Padding", 词面意思上理解就是 "填充式的JSON"。它不是一个新鲜的东西,隶属于 `JSON` 的一种使用方法,或者说是一种使用模式,可以解决一些常见的浏览器端网页跨域问题。 15 | 16 | 正如他的名称一样,它是指被包含在调用函数中的JSON,比如这样: 17 | 18 | ``` javascript 19 | callback({"Name": "小明", "Id" : 1823, "Rank": 7}) 20 | ``` 21 | 22 | 由于 `jQuery` 的一些原因,使得 `JSONP` 常常与 `Ajax` 混淆。实际上,他们没有任何关系。 23 | 24 | 由于浏览器的同源策略,使得在网页端出现了这个“跨域”的问题,然而我们发现,所有的 `src` 属性并没有受到相关的限制,比如 `img` / `script` 等。 25 | 26 | `JSONP` 的原理就要从 `script` 说起。`script` 可以执行其他域的`js` 函数,比如这样: 27 | 28 | ``` javascript 29 | a.html 30 | ... 31 | 36 | 37 | 38 | ... 39 | 40 | 41 | b.js 42 | callback({url: 'http://www.rccoder.net'}) 43 | ``` 44 | 45 | 显然,上面的代码是可以执行的,并且可以在console里面输出http://www.rccoder.net 46 | 47 | 利用这一点,假如b.js里面的内容不是固定的,而是根据一些东西自动生成的, 嗯,这就是JSONP的主要原理了。回调函数+数据就是 `JSON With Padding` 了,回调函数用来响应应该在页面中调用的函数,数据则用来传入要执行的回调函数。 48 | 49 | 至于这个数据是怎么产生的,说粗鲁点无非就是字符串拼接了。 50 | 51 | **简单总结一下:** Ajax 是利用 XMLHTTPRequest 来请求数据的,而它是不能请求不同域上的数据的。但是,在页面上引用不同域的 js 文件却是没有任何问题的,这样,利用异步的加载,请求一个 js 文件,而这个文件的内容是动态生成的(后台语言字符串拼接出来的),里面包含的是 JSON With Padding(回调函数+数据),之前写的那个函数就因为新加载进来的这段动态生成的 js 而执行,也就是获取到了他要获取的数据。 52 | 53 | 重复一下,在一个页面中,a.html这样写,得到 UserId 为 1823 的信息: 54 | 55 | ``` javascript 56 | a.html 57 | 58 | ... 59 | src="http://server2.example.com/RetrieveUser?UserId=1823&callback=parseResponse"> 60 | ... 61 | ``` 62 | 63 | 请求这个地址会得到一个可以执行的 JavaScript。比如会得到: 64 | 65 | ``` javascript 66 | parseResponse({"Name": "小明", "Id" : 1823, "Rank": 7}) 67 | ``` 68 | 69 | 这样,a.html里面的 `parseResponse()` 这个函数就能执行并且得到数据了。 70 | 71 | **等等,jQuery到底做了什么:** 72 | 73 | jQuery 让 JSONP 的使用API和Ajax的一模一样: 74 | 75 | ``` javascript 76 | $.ajax({ 77 | method: 'jsonp', 78 | url: 'http://server2.example.com/RetrieveUser?UserId=1823', 79 | success: function(data) { 80 | console.log(data) 81 | } 82 | }) 83 | ``` 84 | 85 | 之所以可以这样是因为 jQuery 在背后倾注了心血,它会在执行的时候生成函数替换`callback=dosomthing` ,然后获取到数据之后销毁掉这个函数,起到一个临时的代理器作用,这样就拿到了数据。 86 | 87 | **JSONP 的后话**: 88 | 89 | JSONP的这种实现方式不受同源策略的影响,兼容性也很好;但是它之支持 GET 方式的清楚,只支持 HTTP 请求这种特殊的情况,对于两个不同域之间两个页面的互相调用也是无能为力。 90 | 91 | ## 2. CORS 92 | 93 | `XMLHttpRequest` 的同源策略看起来是如此的变态,即使是同一个公司的产品,也不可能完全在同一个域上面。还好,网络设计者在设计的时候考略到了这一点,可以在服务器端进行一些定义,允许部分网络访问。 94 | 95 | CORS 的全称是 Cross-Origin Resource Sharing,即跨域资源共享。他的原理就是使用自定义的 HTTP 头部,让服务器与浏览器进行沟通,主要是通过设置响应头的 `Access-Control-Allow-Origin` 来达到目的的。这样,XMLHttpRequest 就能跨域了。 96 | 97 | 值得注意的是,正常情况下的 XMLHttpRequest 是只发送一次请求的,但是跨域问题下很可能是会发送两次的请求(预发送)。 98 | 99 | 更加详细的内容可以参见: 100 | 101 | > https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS 102 | 103 | **CORS 的后话:** 104 | 105 | 相比之下,CORS 就支持所有类型的 HTTP 请求了,但是在兼容上面,往往一些老的浏览器并不支持 CORS。 106 | 107 | Desktop: 108 | 109 | | 浏览器 | 版本 | 110 | | ----------------- | ------------------------- | 111 | | Chrome | 4 | 112 | | Firefox (Gecko) | 3.5 | 113 | | Internet Explorer | 8 (via XDomainReques) 10 | 114 | | Opera | 12 | 115 | | Safari | 4 | 116 | 117 | Mobile: 118 | 119 | | 设备 | 版本 | 120 | | ---------------------- | ---- | 121 | | Android | 2.1 | 122 | | Chrome for Android | yes | 123 | | Firefox Mobile (Gecko) | yes | 124 | | IE Mobile | ? | 125 | | Opera Mobile | 12 | 126 | | Safari Mobile | 3.2 | 127 | 128 | ## 3. window.name 129 | 130 | window.name 在一个窗口(标签)的生命周期之内是共享的,利用这点就可以传输一些数据。 131 | 132 | 除此之外,结合 iframe 还能实现更加强大的功能: 133 | 134 | 需要3个文件: a/proxy/b 135 | 136 | ``` javascript 137 | a.html 138 | 139 | 159 | ``` 160 | 161 | ``` javascript 162 | b.html 163 | 164 | 168 | ``` 169 | 170 | proxy 是一个代理文件,空的就可以,需要和 a 在同一域下 171 | 172 | ## 4. document.domain 173 | 174 | 在不同的**子域** + iframe交互的时候,获取到另外一个 iframe 的 window对象是没有问题的,但是获取到的这个window的方法和属性大多数都是不能使用的。 175 | 176 | 这种现象可以借助`document.domain` 来解决。 177 | 178 | ``` 179 | example.com 180 | 181 | 182 | 186 | ``` 187 | 188 | ``` javascript 189 | 1.example.com 190 | 191 | 194 | ``` 195 | 196 | 这样,就可以解决问题了。值得注意的是:**`document.domain` 的设置是有限制的,只能设置为页面本身或者更高一级的域名。** 197 | 198 | **document.domain的后话:** 199 | 200 | 利用这种方法是极其方便的,但是如果一个网站被攻击之后另外一个网站很可能会引起安全漏洞。 201 | 202 | ## 5.location.hash 203 | 204 | 这种方法可以把数据的变化显示在 url 的 hash 里面。但是由于 chrome 和 IE 不允许修改parent.location.hash 的值,所以需要再加一层。 205 | 206 | a.html 和 b.html 进行数据交换。 207 | 208 | ``` html 209 | a.html 210 | 211 | function startRequest(){ 212 | var ifr = document.createElement('iframe'); 213 | ifr.style.display = 'none'; 214 | ifr.src = 'http://2.com/b.html#paramdo'; 215 | document.body.appendChild(ifr); 216 | } 217 | 218 | function checkHash() { 219 | try { 220 | var data = location.hash ? location.hash.substring(1) : ''; 221 | if (console.log) { 222 | console.log('Now the data is '+data); 223 | } 224 | } catch(e) {}; 225 | } 226 | setInterval(checkHash, 2000); 227 | ``` 228 | 229 | ``` html 230 | b.html 231 | 232 | //模拟一个简单的参数处理操作 233 | switch(location.hash){ 234 | case '#paramdo': 235 | callBack(); 236 | break; 237 | case '#paramset': 238 | //do something…… 239 | break; 240 | } 241 | 242 | function callBack(){ 243 | try { 244 | parent.location.hash = 'somedata'; 245 | } catch (e) { 246 | // ie、chrome的安全机制无法修改parent.location.hash, 247 | // 所以要利用一个中间域下的代理iframe 248 | var ifrproxy = document.createElement('iframe'); 249 | ifrproxy.style.display = 'none'; 250 | ifrproxy.src = 'http://3.com/c.html#somedata'; // 注意该文件在"a.com"域下 251 | document.body.appendChild(ifrproxy); 252 | } 253 | } 254 | ``` 255 | 256 | ``` html 257 | c.html 258 | 259 | //因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值 260 | parent.parent.location.hash = self.location.hash.substring(1); 261 | ``` 262 | 263 | 这样,利用中间的 c 层就可以用 hash 达到 a 与 b 的交互了。 264 | 265 | ## 6.window.postMessage() 266 | 267 | 这个方法是 HTML5 的一个新特性,可以用来向其他所有的window对象发送消息。需要注意的是我们必须要保证所有的脚本执行完才发送MessageEvent,如果在函数执行的过程中调用了他,就会让后面的函数超时无法执行。 268 | 269 | > https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage 270 | 271 | 272 | 273 | ## 参考资料 274 | 275 | http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html 276 | 277 | http://www.cnblogs.com/rainman/archive/2011/02/21/1960044.html 278 | 279 | --- 280 | 281 | ## 捐赠 282 | 283 | 写文不易,赠我一杯咖啡增强一下感情可好? 284 | 285 | ![alipay](https://cloud.githubusercontent.com/assets/7554325/13387514/4e6c3b42-def2-11e5-849c-90c5f1109fe7.png) 286 | -------------------------------------------------------------------------------- /_sass/_base.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Reset some basic elements 3 | */ 4 | body, h1, h2, h3, h4, h5, h6, 5 | p, blockquote, pre, hr, 6 | dl, dd, ol, ul, figure { 7 | margin: 0; 8 | padding: 0; 9 | } 10 | 11 | 12 | 13 | /** 14 | * Basic styling 15 | */ 16 | body { 17 | font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family; 18 | color: $text-color; 19 | background-color: $background-color; 20 | -webkit-text-size-adjust: 100%; 21 | -webkit-font-feature-settings: "kern" 1; 22 | -moz-font-feature-settings: "kern" 1; 23 | -o-font-feature-settings: "kern" 1; 24 | font-feature-settings: "kern" 1; 25 | font-kerning: normal; 26 | } 27 | 28 | 29 | 30 | /** 31 | * Set `margin-bottom` to maintain vertical rhythm 32 | */ 33 | h1, h2, h3, h4, h5, h6, 34 | p, blockquote, pre, 35 | ul, ol, dl, figure, 36 | %vertical-rhythm { 37 | margin-bottom: $spacing-unit / 2; 38 | } 39 | 40 | 41 | 42 | /** 43 | * Images 44 | */ 45 | img { 46 | max-width: 100%; 47 | vertical-align: middle; 48 | } 49 | 50 | 51 | 52 | /** 53 | * Figures 54 | */ 55 | figure > img { 56 | display: block; 57 | } 58 | 59 | figcaption { 60 | font-size: $small-font-size; 61 | } 62 | 63 | 64 | 65 | /** 66 | * Lists 67 | */ 68 | ul, ol { 69 | margin-left: $spacing-unit; 70 | } 71 | 72 | li { 73 | > ul, 74 | > ol { 75 | margin-bottom: 0; 76 | } 77 | } 78 | 79 | 80 | 81 | /** 82 | * Headings 83 | */ 84 | h1, h2, h3, h4, h5, h6 { 85 | font-weight: $base-font-weight; 86 | } 87 | 88 | 89 | 90 | /** 91 | * Links 92 | */ 93 | a { 94 | color: $brand-color; 95 | text-decoration: none; 96 | 97 | &:visited { 98 | color: darken($brand-color, 15%); 99 | } 100 | 101 | &:hover { 102 | color: $text-color; 103 | text-decoration: underline; 104 | } 105 | } 106 | 107 | 108 | 109 | /** 110 | * Blockquotes 111 | */ 112 | blockquote { 113 | color: $grey-color; 114 | border-left: 4px solid $grey-color-light; 115 | padding-left: $spacing-unit / 2; 116 | font-size: 18px; 117 | letter-spacing: -1px; 118 | font-style: italic; 119 | 120 | > :last-child { 121 | margin-bottom: 0; 122 | } 123 | } 124 | 125 | 126 | 127 | /** 128 | * Code formatting 129 | */ 130 | pre, 131 | code { 132 | font-size: 15px; 133 | border: 1px solid $grey-color-light; 134 | border-radius: 3px; 135 | //background-color: #eef; 136 | } 137 | 138 | code { 139 | padding: 1px 5px; 140 | } 141 | 142 | pre { 143 | padding: 8px 12px; 144 | overflow-x: auto; 145 | 146 | > code { 147 | border: 0; 148 | padding-right: 0; 149 | padding-left: 0; 150 | } 151 | } 152 | 153 | 154 | 155 | /** 156 | * Wrapper 157 | */ 158 | .wrapper { 159 | max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2)); 160 | max-width: calc(#{$content-width} - (#{$spacing-unit} * 2)); 161 | margin-right: auto; 162 | margin-left: auto; 163 | padding-right: $spacing-unit; 164 | padding-left: $spacing-unit; 165 | @extend %clearfix; 166 | 167 | @include media-query($on-laptop) { 168 | max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit})); 169 | max-width: calc(#{$content-width} - (#{$spacing-unit})); 170 | padding-right: $spacing-unit / 2; 171 | padding-left: $spacing-unit / 2; 172 | } 173 | } 174 | 175 | 176 | 177 | /** 178 | * Clearfix 179 | */ 180 | %clearfix { 181 | 182 | &:after { 183 | content: ""; 184 | display: table; 185 | clear: both; 186 | } 187 | } 188 | 189 | 190 | 191 | /** 192 | * Icons 193 | */ 194 | .icon { 195 | 196 | > svg { 197 | display: inline-block; 198 | width: 16px; 199 | height: 16px; 200 | vertical-align: middle; 201 | 202 | path { 203 | fill: $grey-color; 204 | } 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /_sass/_layout.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Site header 3 | */ 4 | .site-header { 5 | border-top: 5px solid $grey-color-dark; 6 | border-bottom: 1px solid $grey-color-light; 7 | min-height: 56px; 8 | 9 | // Positioning context for the mobile navigation icon 10 | position: relative; 11 | } 12 | 13 | .site-title { 14 | font-size: 26px; 15 | font-weight: 300; 16 | line-height: 56px; 17 | letter-spacing: -1px; 18 | margin-bottom: 0; 19 | float: left; 20 | 21 | &, 22 | &:visited { 23 | color: $grey-color-dark; 24 | } 25 | } 26 | 27 | .site-nav { 28 | float: right; 29 | line-height: 56px; 30 | 31 | .menu-icon { 32 | display: none; 33 | } 34 | 35 | .page-link { 36 | color: $text-color; 37 | line-height: $base-line-height; 38 | 39 | // Gaps between nav items, but not on the last one 40 | &:not(:last-child) { 41 | margin-right: 20px; 42 | } 43 | } 44 | 45 | @include media-query($on-palm) { 46 | position: absolute; 47 | top: 9px; 48 | right: $spacing-unit / 2; 49 | background-color: $background-color; 50 | border: 1px solid $grey-color-light; 51 | border-radius: 5px; 52 | text-align: right; 53 | 54 | .menu-icon { 55 | display: block; 56 | float: right; 57 | width: 36px; 58 | height: 26px; 59 | line-height: 0; 60 | padding-top: 10px; 61 | text-align: center; 62 | 63 | > svg { 64 | width: 18px; 65 | height: 15px; 66 | 67 | path { 68 | fill: $grey-color-dark; 69 | } 70 | } 71 | } 72 | 73 | .trigger { 74 | clear: both; 75 | display: none; 76 | } 77 | 78 | &:hover .trigger { 79 | display: block; 80 | padding-bottom: 5px; 81 | } 82 | 83 | .page-link { 84 | display: block; 85 | padding: 5px 10px; 86 | 87 | &:not(:last-child) { 88 | margin-right: 0; 89 | } 90 | margin-left: 20px; 91 | } 92 | } 93 | } 94 | 95 | 96 | 97 | /** 98 | * Site footer 99 | */ 100 | .site-footer { 101 | border-top: 1px solid $grey-color-light; 102 | padding: $spacing-unit 0; 103 | } 104 | 105 | .footer-heading { 106 | font-size: 18px; 107 | margin-bottom: $spacing-unit / 2; 108 | } 109 | 110 | .contact-list, 111 | .social-media-list { 112 | list-style: none; 113 | margin-left: 0; 114 | } 115 | 116 | .footer-col-wrapper { 117 | font-size: 15px; 118 | color: $grey-color; 119 | margin-left: -$spacing-unit / 2; 120 | @extend %clearfix; 121 | } 122 | 123 | .footer-col { 124 | float: left; 125 | margin-bottom: $spacing-unit / 2; 126 | padding-left: $spacing-unit / 2; 127 | } 128 | 129 | .footer-col-1 { 130 | width: -webkit-calc(35% - (#{$spacing-unit} / 2)); 131 | width: calc(35% - (#{$spacing-unit} / 2)); 132 | } 133 | 134 | .footer-col-2 { 135 | width: -webkit-calc(20% - (#{$spacing-unit} / 2)); 136 | width: calc(20% - (#{$spacing-unit} / 2)); 137 | } 138 | 139 | .footer-col-3 { 140 | width: -webkit-calc(45% - (#{$spacing-unit} / 2)); 141 | width: calc(45% - (#{$spacing-unit} / 2)); 142 | } 143 | 144 | @include media-query($on-laptop) { 145 | .footer-col-1, 146 | .footer-col-2 { 147 | width: -webkit-calc(50% - (#{$spacing-unit} / 2)); 148 | width: calc(50% - (#{$spacing-unit} / 2)); 149 | } 150 | 151 | .footer-col-3 { 152 | width: -webkit-calc(100% - (#{$spacing-unit} / 2)); 153 | width: calc(100% - (#{$spacing-unit} / 2)); 154 | } 155 | } 156 | 157 | @include media-query($on-palm) { 158 | .footer-col { 159 | float: none; 160 | width: -webkit-calc(100% - (#{$spacing-unit} / 2)); 161 | width: calc(100% - (#{$spacing-unit} / 2)); 162 | } 163 | } 164 | 165 | 166 | 167 | /** 168 | * Page content 169 | */ 170 | .page-content { 171 | padding: $spacing-unit 0; 172 | } 173 | 174 | .page-heading { 175 | font-size: 20px; 176 | } 177 | 178 | .post-list { 179 | margin-left: 0; 180 | list-style: none; 181 | 182 | > li { 183 | margin-bottom: $spacing-unit; 184 | } 185 | } 186 | 187 | .post-meta { 188 | font-size: $small-font-size; 189 | color: $grey-color; 190 | } 191 | 192 | .post-link { 193 | display: block; 194 | font-size: 24px; 195 | } 196 | 197 | 198 | 199 | /** 200 | * Posts 201 | */ 202 | .post-header { 203 | margin-bottom: $spacing-unit; 204 | } 205 | 206 | .post-title { 207 | font-size: 42px; 208 | letter-spacing: -1px; 209 | line-height: 1; 210 | 211 | @include media-query($on-laptop) { 212 | font-size: 36px; 213 | } 214 | } 215 | 216 | .post-content { 217 | margin-bottom: $spacing-unit; 218 | 219 | h2 { 220 | font-size: 32px; 221 | 222 | @include media-query($on-laptop) { 223 | font-size: 28px; 224 | } 225 | } 226 | 227 | h3 { 228 | font-size: 26px; 229 | 230 | @include media-query($on-laptop) { 231 | font-size: 22px; 232 | } 233 | } 234 | 235 | h4 { 236 | font-size: 20px; 237 | 238 | @include media-query($on-laptop) { 239 | font-size: 18px; 240 | } 241 | } 242 | } 243 | 244 | .petal .reply, .petal .footer{ 245 | display: none; 246 | } 247 | .petal-dec { 248 | margin: 40px 249 | } -------------------------------------------------------------------------------- /_sass/_syntax-highlighting.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Syntax highlighting styles 3 | */ 4 | .highlight { 5 | background: #fff; 6 | @extend %vertical-rhythm; 7 | 8 | .highlighter-rouge & { 9 | //background: #eef; 10 | } 11 | 12 | .c { color: #998; font-style: italic } // Comment 13 | .err { color: #a61717; background-color: #e3d2d2 } // Error 14 | .k { font-weight: bold } // Keyword 15 | .o { font-weight: bold } // Operator 16 | .cm { color: #998; font-style: italic } // Comment.Multiline 17 | .cp { color: #999; font-weight: bold } // Comment.Preproc 18 | .c1 { color: #998; font-style: italic } // Comment.Single 19 | .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special 20 | .gd { color: #000; background-color: #fdd } // Generic.Deleted 21 | .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific 22 | .ge { font-style: italic } // Generic.Emph 23 | .gr { color: #a00 } // Generic.Error 24 | .gh { color: #999 } // Generic.Heading 25 | .gi { color: #000; background-color: #dfd } // Generic.Inserted 26 | .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific 27 | .go { color: #888 } // Generic.Output 28 | .gp { color: #555 } // Generic.Prompt 29 | .gs { font-weight: bold } // Generic.Strong 30 | .gu { color: #aaa } // Generic.Subheading 31 | .gt { color: #a00 } // Generic.Traceback 32 | .kc { font-weight: bold } // Keyword.Constant 33 | .kd { font-weight: bold } // Keyword.Declaration 34 | .kp { font-weight: bold } // Keyword.Pseudo 35 | .kr { font-weight: bold } // Keyword.Reserved 36 | .kt { color: #458; font-weight: bold } // Keyword.Type 37 | .m { color: #099 } // Literal.Number 38 | .s { color: #d14 } // Literal.String 39 | .na { color: #008080 } // Name.Attribute 40 | .nb { color: #0086B3 } // Name.Builtin 41 | .nc { color: #458; font-weight: bold } // Name.Class 42 | .no { color: #008080 } // Name.Constant 43 | .ni { color: #800080 } // Name.Entity 44 | .ne { color: #900; font-weight: bold } // Name.Exception 45 | .nf { color: #900; font-weight: bold } // Name.Function 46 | .nn { color: #555 } // Name.Namespace 47 | .nt { color: #000080 } // Name.Tag 48 | .nv { color: #008080 } // Name.Variable 49 | .ow { font-weight: bold } // Operator.Word 50 | .w { color: #bbb } // Text.Whitespace 51 | .mf { color: #099 } // Literal.Number.Float 52 | .mh { color: #099 } // Literal.Number.Hex 53 | .mi { color: #099 } // Literal.Number.Integer 54 | .mo { color: #099 } // Literal.Number.Oct 55 | .sb { color: #d14 } // Literal.String.Backtick 56 | .sc { color: #d14 } // Literal.String.Char 57 | .sd { color: #d14 } // Literal.String.Doc 58 | .s2 { color: #d14 } // Literal.String.Double 59 | .se { color: #d14 } // Literal.String.Escape 60 | .sh { color: #d14 } // Literal.String.Heredoc 61 | .si { color: #d14 } // Literal.String.Interpol 62 | .sx { color: #d14 } // Literal.String.Other 63 | .sr { color: #009926 } // Literal.String.Regex 64 | .s1 { color: #d14 } // Literal.String.Single 65 | .ss { color: #990073 } // Literal.String.Symbol 66 | .bp { color: #999 } // Name.Builtin.Pseudo 67 | .vc { color: #008080 } // Name.Variable.Class 68 | .vg { color: #008080 } // Name.Variable.Global 69 | .vi { color: #008080 } // Name.Variable.Instance 70 | .il { color: #099 } // Literal.Number.Integer.Long 71 | } 72 | -------------------------------------------------------------------------------- /about.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: About 4 | permalink: /about/ 5 | --- 6 | 7 | Hi, 很高兴认识你,这是我的技术博客。 8 | 9 | 如果你想在更多的地方认识我,可以选择下面的各种方式: 10 | 11 | **GitHub:** [rccoder](https://github.com/rccoder) 12 | 13 | **知乎:** [rccoder](https://www.zhihu.com/people/rccoder) 14 | 15 | **Weibo:** [rccoder](http://weibo.com/rccoder) 16 | 17 | **segmentfault:** [rccoder](https://segmentfault.com/u/rccoder) 18 | 19 | **stackoverflow:** [rccoder](http://stackoverflow.com/users/4681656/rccoder) 20 | 21 | **Linkedin:** [rccoder](https://cn.linkedin.com/in/尚斌-杨-7803a7b8) 22 | 23 | 对了,如果你想"金钱"联络一下感情,可以扫描下面的二维码试试: 24 | 25 | ![alipay](https://cloud.githubusercontent.com/assets/7554325/13387514/4e6c3b42-def2-11e5-849c-90c5f1109fe7.png) -------------------------------------------------------------------------------- /api/list.json: -------------------------------------------------------------------------------- 1 | { 2 | "api": "title_url_label", 3 | "desc": "所有文章标题-地址-标签", 4 | "content": [ 5 | { 6 | "id": "16", 7 | "title": "React 数据阵营之 State 与 Props", 8 | "url": "https://github.com/rccoder/blog/issues/16", 9 | "label": [ 10 | "React" 11 | ] 12 | }, 13 | { 14 | "id": "15", 15 | "title": "如何在 JavaScript 中声明变量", 16 | "url": "https://github.com/rccoder/blog/issues/15", 17 | "label": [ 18 | "JavaScript" 19 | ] 20 | }, 21 | { 22 | "id": "14", 23 | "title": "少年,洗个牌吧", 24 | "url": "https://github.com/rccoder/blog/issues/14", 25 | "label": "算法" 26 | }, 27 | { 28 | "id": "13", 29 | "title": "Centos 5.8 LAMP 环境 PHP 版本升级记录", 30 | "url": "https://github.com/rccoder/blog/issues/13", 31 | "label": [ 32 | "运维" 33 | ] 34 | }, 35 | { 36 | "id": "12", 37 | "title": "说说浏览器端缓存的那点事儿-扑朔迷离的 etag 与 last-modified", 38 | "url": "https://github.com/rccoder/blog/issues/12", 39 | "label": [ 40 | "HTTP" 41 | ] 42 | }, 43 | { 44 | "id": "11", 45 | "title": "你不知道的 transition 与 animation", 46 | "url": "https://github.com/rccoder/blog/issues/11", 47 | "label": [ 48 | "CSS" 49 | ] 50 | }, 51 | { 52 | "id": "10", 53 | "title": "如何在 CSS 预处理器 Less 中使用 Mixins", 54 | "url": "https://github.com/rccoder/blog/issues/10", 55 | "label": [ 56 | "翻译" 57 | ] 58 | }, 59 | { 60 | "id": "9", 61 | "title": "在 pre-commit 的钩子中运行 npm script", 62 | "url": "https://github.com/rccoder/blog/issues/9", 63 | "label": [ 64 | "翻译" 65 | ] 66 | }, 67 | { 68 | "id": "8", 69 | "title": "类 Bootstrap 栅栏布局的实现", 70 | "url": "https://github.com/rccoder/blog/issues/8", 71 | "label": [ 72 | "CSS", 73 | "布局" 74 | ] 75 | }, 76 | { 77 | "id": "7", 78 | "title": "从baidu-ife Task1-11 初尝移动端开发 —— 萌芽篇", 79 | "url": "https://github.com/rccoder/blog/issues/7", 80 | "label": [ 81 | "WebApp" 82 | ] 83 | }, 84 | { 85 | "id": "6", 86 | "title": "那些年,奇妙的圣杯与双飞翼,还有负边距", 87 | "url": "https://github.com/rccoder/blog/issues/6", 88 | "label": [ 89 | "CSS", 90 | "布局" 91 | ] 92 | }, 93 | { 94 | "id": "5", 95 | "title": "浅谈浏览器端JavaScript跨域解决方法", 96 | "url": "https://github.com/rccoder/blog/issues/5", 97 | "label": [ 98 | "JavaScript" 99 | ] 100 | }, 101 | { 102 | "id": "4", 103 | "title": "JavaScript之对象创建", 104 | "url": "https://github.com/rccoder/blog/issues/4", 105 | "label": [ 106 | "JavaScript" 107 | ] 108 | }, 109 | { 110 | "id": "3", 111 | "title": "JavaScript之闭包相", 112 | "url": "https://github.com/rccoder/blog/issues/3", 113 | "label": [ 114 | "JavaScript" 115 | ] 116 | }, 117 | { 118 | "id": "2", 119 | "title": "JavaScript 之 this 指向问题", 120 | "url": "https://github.com/rccoder/blog/issues/2", 121 | "label": [ 122 | "JavaScript" 123 | ] 124 | }, 125 | { 126 | "id": "1", 127 | "title": "JavaScript 之原型周边", 128 | "url": "https://github.com/rccoder/blog/issues/1", 129 | "label": [ 130 | "JavaScript" 131 | ] 132 | } 133 | ] 134 | } 135 | -------------------------------------------------------------------------------- /css/main.scss: -------------------------------------------------------------------------------- 1 | --- 2 | # Only the main Sass file needs front matter (the dashes are enough) 3 | --- 4 | @charset "utf-8"; 5 | 6 | 7 | 8 | // Our variables 9 | $base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 10 | $base-font-size: 16px; 11 | $base-font-weight: 400; 12 | $small-font-size: $base-font-size * 0.875; 13 | $base-line-height: 1.5; 14 | 15 | $spacing-unit: 30px; 16 | 17 | $text-color: #111; 18 | $background-color: #fdfdfd; 19 | $brand-color: #2a7ae2; 20 | 21 | $grey-color: #828282; 22 | $grey-color-light: lighten($grey-color, 40%); 23 | $grey-color-dark: darken($grey-color, 25%); 24 | 25 | // Width of the content area 26 | $content-width: 800px; 27 | 28 | $on-palm: 600px; 29 | $on-laptop: 800px; 30 | 31 | 32 | 33 | // Use media queries like this: 34 | // @include media-query($on-palm) { 35 | // .wrapper { 36 | // padding-right: $spacing-unit / 2; 37 | // padding-left: $spacing-unit / 2; 38 | // } 39 | // } 40 | @mixin media-query($device) { 41 | @media screen and (max-width: $device) { 42 | @content; 43 | } 44 | } 45 | 46 | 47 | 48 | // Import partials from `sass_dir` (defaults to `_sass`) 49 | @import 50 | "base", 51 | "layout", 52 | "syntax-highlighting" 53 | ; 54 | -------------------------------------------------------------------------------- /feed.xml: -------------------------------------------------------------------------------- 1 | --- 2 | layout: null 3 | --- 4 | 5 | 6 | 7 | {{ site.title | xml_escape }} 8 | {{ site.description | xml_escape }} 9 | {{ site.url }}{{ site.baseurl }}/ 10 | 11 | {{ site.time | date_to_rfc822 }} 12 | {{ site.time | date_to_rfc822 }} 13 | Jekyll v{{ jekyll.version }} 14 | {% for post in site.posts limit:10 %} 15 | 16 | {{ post.title | xml_escape }} 17 | {{ post.content | xml_escape }} 18 | {{ post.date | date_to_rfc822 }} 19 | {{ post.url | prepend: site.baseurl | prepend: site.url }} 20 | {{ post.url | prepend: site.baseurl | prepend: site.url }} 21 | {% for tag in post.tags %} 22 | {{ tag | xml_escape }} 23 | {% endfor %} 24 | {% for cat in post.categories %} 25 | {{ cat | xml_escape }} 26 | {% endfor %} 27 | 28 | {% endfor %} 29 | 30 | 31 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 |
6 | 7 |

Posts

8 | 9 | 20 | 21 |

subscribe via RSS

22 | 23 |
24 | -------------------------------------------------------------------------------- /spider/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const request = require('superagent') 4 | const cheerio = require('cheerio') 5 | 6 | const base_url = 'http://github.com/' 7 | 8 | const data = [] 9 | request 10 | .get('https://github.com/rccoder/blog/issues') 11 | .end((err, res) => { 12 | if(err) { 13 | console.log(err) 14 | } else { 15 | let $ = cheerio.load(res.text) 16 | $('.Box-row-link').each((id, value) => { 17 | let url = `${base_url}${value.attribs.href}` 18 | let title = `${value.children[0].data.trim()}` 19 | let label = [] 20 | label.push() 21 | }) 22 | } 23 | }) 24 | -------------------------------------------------------------------------------- /spider/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spider", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cheerio": "^0.22.0", 13 | "superagent": "^2.3.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /wechatApp/app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | App({ 3 | onLaunch: function () { 4 | //调用API从本地缓存中获取数据 5 | var logs = wx.getStorageSync('logs') || [] 6 | logs.unshift(Date.now()) 7 | wx.setStorageSync('logs', logs) 8 | }, 9 | getUserInfo:function(cb){ 10 | var that = this; 11 | if(this.globalData.userInfo){ 12 | typeof cb == "function" && cb(this.globalData.userInfo) 13 | }else{ 14 | //调用登录接口 15 | wx.login({ 16 | success: function () { 17 | wx.getUserInfo({ 18 | success: function (res) { 19 | that.globalData.userInfo = res.userInfo; 20 | typeof cb == "function" && cb(that.globalData.userInfo) 21 | } 22 | }) 23 | } 24 | }); 25 | } 26 | }, 27 | getGitHubIssues:function(cb) { 28 | var that = this; 29 | if(this.globalData.issuesContent) { 30 | typeof cb == "function" && cb(this.globalData.issuesContent) 31 | } else { 32 | wx.request({ 33 | url: 'https://raw.githubusercontent.com/rccoder/blog/gh-pages/api/list.json', 34 | success: function(res) { 35 | that.globalData.issues = res.data.content 36 | typeof cb == "function" && cb(that.globalData.issues) 37 | } 38 | }) 39 | } 40 | }, 41 | globalData:{ 42 | userInfo:null 43 | } 44 | }) 45 | -------------------------------------------------------------------------------- /wechatApp/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages":[ 3 | "pages/index/index", 4 | "pages/logs/logs" 5 | ], 6 | "window":{ 7 | "backgroundTextStyle":"light", 8 | "navigationBarBackgroundColor": "#fff", 9 | "navigationBarTitleText": "WeChat", 10 | "navigationBarTextStyle":"black" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /wechatApp/app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | .container { 3 | box-sizing: border-box; 4 | margin: 0 auto; 5 | background: #f8f8f8; 6 | } 7 | -------------------------------------------------------------------------------- /wechatApp/pages/index/index.js: -------------------------------------------------------------------------------- 1 | //index.js 2 | //获取应用实例 3 | var app = getApp() 4 | Page({ 5 | data: { 6 | userInfo: { 7 | nickName: 'rccoder', 8 | avatarUrl: '//avatars2.githubusercontent.com/u/7554325?v=3&s=466' 9 | }, 10 | issuesContent: [] 11 | }, 12 | //事件处理函数 13 | bindViewTap: function() { 14 | wx.navigateTo({ 15 | url: '../logs/logs' 16 | }) 17 | }, 18 | onLoad: function () { 19 | console.log('onLoad') 20 | var that = this 21 | app.getGitHubIssues(function(issuesContent) { 22 | console.log(issuesContent) 23 | that.setData({ 24 | issuesContent: issuesContent 25 | }) 26 | that.update() 27 | }) 28 | } 29 | }) 30 | -------------------------------------------------------------------------------- /wechatApp/pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{userInfo.nickName}} 6 | 7 | 8 | 9 | 文章列表 10 | 11 | 12 | 13 | {{item.title}} 14 | 由各种物质组成的巨型球状天体,叫做星球。星球有一定的形状,有自己的运行轨道 15 | 16 | 17 | 18 | 19 | ©️ 2016 rccoder 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /wechatApp/pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | .userinfo { 2 | padding-top: 40rpx; 3 | width: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | } 7 | 8 | .userinfo-avatar { 9 | width: 128rpx; 10 | height: 128rpx; 11 | margin: 20rpx auto; 12 | border-radius: 50%; 13 | } 14 | .userinfo-nickname { 15 | text-align: center; 16 | font-size: 12rpx; 17 | } 18 | 19 | .content { 20 | margin-top: 80rpx; 21 | color: #999999; 22 | position: relative; 23 | background: white; 24 | } 25 | .content:before{ 26 | content: " "; 27 | position: absolute; 28 | left: 0; 29 | top: 0; 30 | right: 0; 31 | height: 1px; 32 | border-top: 1px solid #E5E5E5; 33 | color: #E5E5E5; 34 | transform-origin: 0 0; 35 | transform: scaleY(0.5); 36 | } 37 | .content:after{ 38 | content: " "; 39 | position: absolute; 40 | left: 0; 41 | bottom: 0; 42 | right: 0; 43 | height: 1px; 44 | border-bottom: 1px solid #E5E5E5; 45 | color: #E5E5E5; 46 | transform-origin: 0 0; 47 | transform: scaleY(0.5); 48 | } 49 | .panel-hd { 50 | padding: 30rpx 28rpx 20rpx; 51 | font-size: 26rpx; 52 | } 53 | .panel-bd .box { 54 | position: relative; 55 | padding: 30rpx; 56 | } 57 | .panel-bd .box:before { 58 | content: " "; 59 | position: absolute; 60 | top: 0; 61 | right: 0; 62 | height: 1rpx; 63 | border-top: 1rpx solid #E5E5E5; 64 | color: #E5E5E5; 65 | transform-origin: 0 0; 66 | transform: scaleY(0.5); 67 | left: 15rpx; 68 | } 69 | .panel-bd .box .title { 70 | display: block; 71 | margin-bottom: 16rpx; 72 | font-size: 34rpx; 73 | font-weight: 400; 74 | width: auto; 75 | overflow: hidden; 76 | color: #000000; 77 | } 78 | .panel-bd .box .desc { 79 | display: block; 80 | font-size: 26rpx; 81 | color: #999999; 82 | } 83 | .panel-ft { 84 | position: relative; 85 | font-size: 24rpx; 86 | display: flex; 87 | justify-content: flex-end; 88 | padding: 20rpx; 89 | } 90 | .panel-ft:before { 91 | content: " "; 92 | position: absolute; 93 | top: 0; 94 | right: 0; 95 | height: 1rpx; 96 | border-top: 1rpx solid #E5E5E5; 97 | color: #E5E5E5; 98 | transform-origin: 0 0; 99 | transform: scaleY(0.5); 100 | left: 15rpx; 101 | } 102 | .footer { 103 | height: 200rpx; 104 | font-size: 24rpx; 105 | display: flex; 106 | align-items: center; 107 | justify-content: center; 108 | } -------------------------------------------------------------------------------- /wechatApp/pages/logs/logs.js: -------------------------------------------------------------------------------- 1 | var util = require('../../utils/util.js') 2 | Page({ 3 | data: { 4 | logs: [] 5 | }, 6 | onLoad: function () { 7 | this.setData({ 8 | logs: (wx.getStorageSync('logs') || []).map(function (log) { 9 | return util.formatTime(new Date(log)) 10 | }) 11 | }) 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /wechatApp/pages/logs/logs.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "查看启动日志" 3 | } -------------------------------------------------------------------------------- /wechatApp/pages/logs/logs.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{index + 1}}. {{log}} 5 | 6 | 7 | -------------------------------------------------------------------------------- /wechatApp/pages/logs/logs.wxss: -------------------------------------------------------------------------------- 1 | .log-list { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 40rpx; 5 | } 6 | .log-item { 7 | margin: 10rpx; 8 | } 9 | -------------------------------------------------------------------------------- /wechatApp/pages/main/main.js: -------------------------------------------------------------------------------- 1 | var app = getApp() 2 | Page({ 3 | data: { 4 | motto: 'Hello WeApp', 5 | userInfo: {} 6 | }, 7 | onButtonTap: function() { 8 | wx.navigateTo({ 9 | url: '../logs/logs' 10 | }) 11 | }, 12 | onLoad: function () { 13 | console.log('onLoad') 14 | var that = this 15 | //登录 16 | wx.login({ 17 | success: function () { 18 | wx.getUserInfo({ 19 | success: function (res) { 20 | that.setData({userInfo: res.userInfo}) 21 | that.update() 22 | } 23 | }) 24 | }, 25 | fail: function (res) { 26 | console.log(res) 27 | } 28 | }); 29 | } 30 | }) 31 | -------------------------------------------------------------------------------- /wechatApp/pages/main/main.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{userInfo.nickName}} 6 | 7 | 8 | {{motto}} 9 | 10 | 11 | -------------------------------------------------------------------------------- /wechatApp/pages/main/main.wxss: -------------------------------------------------------------------------------- 1 | /**index.wxss**/ 2 | .container { 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: space-between; 8 | padding: 200rpx 0; 9 | box-sizing: border-box; 10 | } 11 | .userinfo { 12 | display: flex; 13 | flex-direction: column; 14 | align-items: center; 15 | } 16 | .userinfo-avatar { 17 | width: 128rpx; 18 | height: 128rpx; 19 | margin: 20rpx; 20 | border-radius: 50%; 21 | } 22 | .userinfo-nickname { 23 | color: #aaa; 24 | } 25 | -------------------------------------------------------------------------------- /wechatApp/utils/util.js: -------------------------------------------------------------------------------- 1 | function formatTime(date) { 2 | var year = date.getFullYear() 3 | var month = date.getMonth() + 1 4 | var day = date.getDate() 5 | 6 | var hour = date.getHours() 7 | var minute = date.getMinutes() 8 | var second = date.getSeconds(); 9 | 10 | 11 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') 12 | } 13 | 14 | function formatNumber(n) { 15 | n = n.toString() 16 | return n[1] ? n : '0' + n 17 | } 18 | 19 | module.exports = { 20 | formatTime: formatTime 21 | } 22 | --------------------------------------------------------------------------------