SegmentFault web development最新的文章
2016-10-19T23:01:14+08:00
https://segmentfault.com/feeds/blogs
https://creativecommons.org/licenses/by-nc-nd/4.0/
Redux使用探究
https://segmentfault.com/a/1190000007220286
2016-10-19T23:01:14+08:00
2016-10-19T23:01:14+08:00
二胖手
https://segmentfault.com/u/cycok
0
<h2>动机</h2>
<p>如今用<code>React</code>或者<code>vue</code>开发单页应用越来越普遍。当项目越来越大,管理不断变化的state越来越困难。可能散落在各处。需要一个统一的容器来管理各种<code>state</code>。<br><code>Redux</code> 是 <code>JavaScript</code> 状态容器。 它和<code>react</code>和<code>vue</code>无直接关系。只是刚好两者可以结合起来发挥不错的。</p>
<h2>三大原则</h2>
<p>Redux 可以用这三个基本原则来描述:</p>
<h3>单一数据源</h3>
<p>整个应用的 <code>state</code> 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 <code>store</code> 中</p>
<h3>State 是只读的</h3>
<p>惟一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。</p>
<h3>使用纯函数来执行修改</h3>
<p>为了描述 <code>action</code> 如何改变 <code>state</code> tree ,你需要编写 <code>reducers</code>。</p>
<p><code>Reducer</code> 只是一些纯函数,它接收先前的 <code>state</code> 和 <code>action</code>,并返回新的 <code>state</code>。刚开始你可以只有一个 <code>reducer</code>,随着应用变大,你可以把它拆成多个小的 <code>reducers</code>,分别独立地操作 <code>state</code> tree 的不同部分,因为 <code>reducer</code> 只是函数,你可以控制它们被调用的顺序,传入附加数据,甚至编写可复用的 <code>reducer</code> 来处理一些通用任务,如分页器。</p>
<h2>API 文档</h2>
<p><code>Redux</code> 的 API 非常少。</p>
<p>记住,<code>Redux</code> 只关心如何管理 <code>state</code>。在实际的项目中,你还需要使用 UI 绑定库如 <code>react-redux</code>。实际上就是帮你处理了<code>state</code>变化时的监听</p>
<h3>createStore</h3>
<p>产生<code>store</code></p>
<h3>combineReducers</h3>
<p>把多个小reducers组合成一个reducer</p>
<h3>applyMiddleware(...middlewares)</h3>
<p>action中间件</p>
<h3>bindActionCreators</h3>
<p>产生可以不用dispatch的action (感觉用处并不大)</p>
<h3>compose</h3>
<p>把多个中间件组合在一起</p>
web-style文档
https://segmentfault.com/a/1190000006034332
2016-07-21T18:16:19+08:00
2016-07-21T18:16:19+08:00
二胖手
https://segmentfault.com/u/cycok
0
<h2>下载</h2>
<h3>npm</h3>
<p>Web-Style 推荐使用 <a href="https://link.segmentfault.com/?enc=g3WGeU6vCt52HZ%2B94Vd4Hw%3D%3D.qRbrl6XiAES8tw04R1t5psgv%2BEPp66VvduPn0ucMCxE%3D" rel="nofollow">npm</a> 下载或者访问 <a href="https://link.segmentfault.com/?enc=AYoO%2BqpmESWINQ23PUmQHQ%3D%3D.xwrX2ghOkvhr543uFvymPY0SWBTnnLd%2BBHx2C4p30OV3S7FC7WT6bNRPyNZ2Bfw6" rel="nofollow">Web-Style</a></p>
<pre><code>$ npm install web-style --save</code></pre>
<h2>内容说明</h2>
<h3>编译文件</h3>
<p>Web-Style 是通过 <a href="https://link.segmentfault.com/?enc=aetv0RMyeFmJBOUre6qCiA%3D%3D.XRbwM3kGev%2Fp%2FsonV70HbTRHN55NP%2BIjdlJWsXWISlA%3D" rel="nofollow">webpack</a> 进行打包编译。采用了 <a href="https://link.segmentfault.com/?enc=UjZnIcmpeJ%2FdCBynpZ7BUA%3D%3D.%2B5Ciuozt3%2Fofnt9B7J7lddlrhHnmpoeKjSQLb2P4OPw%3D" rel="nofollow">ESLint</a> 规范。编译文件都在dist目录下, 目录结构:</p>
<pre><code>dist/
├── css/
│ └─ web-style.css
├── js/
│ └─ web-style.js
└── fonts/
├─ iconfont.eot
├─ iconfont.svg
├─ iconfont.ttf
└─ iconfont.woff </code></pre>
<p>上面展示的就是Web-Style编译文件, 编译文件可以直接使用到任何web项目中. 提供了编译好的css文件, 包括基础样式和组件的样式。提供了编译好的vue组件 同时还提供了一套 <code>iconfont</code> 的图标字体</p>
<h3>源文件</h3>
<p>Web-Style 源文件目录结构:</p>
<pre><code>src/
├── assets/
│ ├─ sass/
│ └─ fonts/
└── components/</code></pre>
<p><code>assets</code> 下存放公共的样式和字体文件, 采用 <code>sass</code> 预编译 以及采用 <code>autoprefixer</code> 添加兼容性的前缀</p>
<h2>使用方法</h2>
<h3>ES6</h3>
<pre><code class="js">import Vue from 'vue'
import { Message } from 'Web-style'
new Vue({
el: 'body',
components:{
'v-message': Message
}
})</code></pre>
<h3>浏览器使用</h3>
<blockquote><p><strong>Web-Style</strong> 依赖 <strong>vue</strong> , 必须在 <strong>web-style</strong>前引入.</p></blockquote>
<pre><code class="html"><script src="path/to/vue.js"></script>
<script src="path/to/web-style.js"></script>
<script>
var app = new Vue({
el: "body",
components: {
alert: VueStrap.alert
}
})
</script></code></pre>
<h2>编译CSS 和 JavaScript 文件</h2>
<p>Web-Style 使用 webpack 作为编译系统, 并且对外提供了一些方便的方法用于编译整个框架。</p>
<h3>安装依赖</h3>
<p>推荐使用 <a href="https://link.segmentfault.com/?enc=7hHQw6EhS%2BDvAu%2Fp9wylbg%3D%3D.mRbNRLA%2B4Il7s0KLvLnF33T0iHTlZAZZIIsoyHAq%2Bvs%3D" rel="nofollow">cnpm</a> 安装依赖</p>
<pre><code>$ cnpm install</code></pre>
<h3>打包公共的样式</h3>
<pre><code>$ npm run static</code></pre>
<p>该指令执行后会把 <code>assets/</code> 下的文件打包到 <code>static/</code> 这样做的目的是在开发的时候无需重复打包公共部分, 提升编译效率。一旦修改<code>assets/</code> 一定要第执行该指令</p>
<h3>开发模式</h3>
<pre><code>$ npm run dev</code></pre>
<p>本地开启一个服务器, 自动打开浏览器访问index.html文件, 进行开发vue组件</p>
<h3>打包文件</h3>
<pre><code>$ npm run build</code></pre>
<p>会打包所有组件和公共的样式生成到dist目录下。</p>
vue一步步实现alert功能。
https://segmentfault.com/a/1190000005708968
2016-06-13T18:17:35+08:00
2016-06-13T18:17:35+08:00
二胖手
https://segmentfault.com/u/cycok
16
<h2>原生alert的缺点</h2>
<ol>
<li><p>会阻塞一切操作,影响用户体验</p></li>
<li><p>很多浏览器会默认静止alert,例如微信。</p></li>
<li><p>原生alert框样式丑陋。</p></li>
</ol>
<p><img src="/img/bVx7ib" alt="图片描述" title="图片描述"></p>
<p>demo地址: <a href="https://link.segmentfault.com/?enc=f5OETQLdyqz4CYAmhHpBPA%3D%3D.BRHpJY1rU9NV7Ujtz1AchFSR9cLKHZFwpNLPwZnB0xGCc6HsCG5X%2B49pyFFgk%2BLA" rel="nofollow">用力点我</a><br>项目地址: <a href="https://link.segmentfault.com/?enc=hwU2qXdjI7SNgbsmlegYWA%3D%3D.3BtFPxiLRuF8WoMWWW3F4RM%2BScFQw0QYydOrpWaKxVVanL8Uh2Js4HTjW0rDxq9upQMlQ5kZfolMPvBbZwBxJA%3D%3D" rel="nofollow">web-style</a> 希望大家多多关注。项目里有css样式和vue组件。目标是快速构建后台系统。有一定自适应的设计。</p>
<h2>css</h2>
<p>思路:最外层是一个黑色透明撑满全屏幕的div并且是fixed的<code>div.modal-mask</code>。 </p>
<p>在mask内部是一个垂直居中的div框大小可以固定。垂直居中方法有几种可选。我选用的是flex。<br>关键性的css代码如下</p>
<pre><code>.modal-mask{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(55,55,55,.6);
z-index: 100;
display: flex;
align-items: center;
justify-content: center;
}
.modal-confirm{
width: 400px;
box-sizing: border-box;
padding: 30px 40px;
background-color: #fff;
border-radius: 6px;
}
@media only screen and (max-width: 640px) {
.modal-confirm{
width: 100%;
margin: 0 20px;
padding: 10px 20px;
}
}</code></pre>
<p>其中<code>modal-confirm</code>是alert框,有固定的宽度400px 还有padding。 然后我们做了一个小小的自适应。 在小屏上(屏幕宽度小于640px)取消了固定宽度。减少了padding的值,看起来更小巧。</p>
<h2>开发vue组件</h2>
<h4>vue template</h4>
<p>首先我希望这个组件功能能像原生的alert事件一样随时随地的方便调用。 不希望每次都<code>new Vue({})</code>一个实例。 所以我做了一些不一样的设计。</p>
<pre><code><div class="modal-mask" v-show="show">
<div class="modal-confirm">
<h2 class="confirm-header">
<i class="iconfont icon-questioncircle"></i> {{ title }}
</h2>
<div class="confirm-content">
{{ content }}
</div>
<div class="confirm-btns">
<button class="btn" @click="op(1)">取 消</button>
<button class="btn btn-primary" @click="op(2)">确 定</button>
</div>
</div>
</div></code></pre>
<p><code>v-show</code>是控制alert组件的显示和隐藏的指令。 <code>{{ }}</code>是vue默认的模版标记。<br><code>@click</code> 是绑定click事件的指令</p>
<h4>vue data</h4>
<pre><code>new Vue({
el: '#V-confirm',
data: {
show: false,
onCancel: false,
onOk: false,
title: '',
content: ''
}
})</code></pre>
<ul>
<li><p><code>show</code> 是控制显示隐藏的标记。</p></li>
<li><p><code>onCancel onOk</code> 是点击取消或者确定时候触发的回调。</p></li>
<li><p><code>title content</code> 是alert显示的文本。</p></li>
</ul>
<h4>vue methods</h4>
<pre><code> methods: {
op(type){
this.show = false
if(type == '1'){
if(this.onCancel) this.onCancel()
}else{
if(this.onOk) this.onOk()
}
this.onCancel = false
this.onOk = false
document.body.style.overflow = ''
},
alert(setting){
this.title = setting.title || '标题'
this.content = setting.content || '内容'
this.onOk = setting.onOk || false
this.onCancel = setting.onCancel || false
this.show = true
document.body.style.overflow = 'hidden'
}
}
}</code></pre>
<p><code>alert(setting)</code> 方法是控制显示alert组件的方法。接受一个object的参数配置。<br><code>op(type)</code> 方法是点击取消和确定按钮的时候触发的时候。</p>
<h4>hack代码</h4>
<pre><code>
var element = document.createElement('div');
element.id = 'V-confirm'
element.innerHTML = template
document.body.appendChild(element)
</code></pre>
<p>这一段代码作用是一开始就把vue实例插入到 <code>body</code> 底部,方便直接 <code>alert</code> 调用。</p>
<h4>加入一些动画效果</h4>
<p>依赖的是vue指令 <code>transition</code> 具体的用法教程 大家去 <a href="https://link.segmentfault.com/?enc=Wu%2FgdTM8p%2Bi5JTTvUavajQ%3D%3D.xSJBEyDEEj5K82ckih7dV6bht9CNF3mCiNxQjIjBgvrqFuhOa1EcbhvUGc0mOy0W" rel="nofollow">过渡-传送门</a></p>
<pre><code>.modal-enter, .modal-leave {
opacity: 0;
}
.modal-transition{
transition: all .3s ease;
}
.modal-enter .modal-confirm,
.modal-leave .modal-confirm {
transform: scale(1.1);
}
.modal-transition{
transition: all .3s ease;
}</code></pre>
<h4>用法</h4>
<pre><code>var setting = {}
setting.title = '你确定删除吗?'
setting.content = '删除不可以恢复...'
setting.onOk = function(){}
setting.onCancel = function(){}
$confirm.alert(setting)
</code></pre>
OSX下安装PHP7教程
https://segmentfault.com/a/1190000004503584
2016-02-28T09:35:48+08:00
2016-02-28T09:35:48+08:00
二胖手
https://segmentfault.com/u/cycok
1
<h2>内容概要</h2>
<ol>
<li><p>安装homebrew</p></li>
<li><p>通过homebrew安装php7</p></li>
<li><p>配置apache文件</p></li>
<li><p>重启apache</p></li>
</ol>
<h3>安装homebrew</h3>
<p><code>homebrew</code>是OSX下的最好的包管理软件(没有之一),而且非常简单易用,包都非常新。这是官方帮助<a href="https://link.segmentfault.com/?enc=FvQLDoBDPqm8wPRTk5aG8Q%3D%3D.oLUE1bl6yiqpYP8H9w3rdA%3D%3D" rel="nofollow">homewbrew</a>,如果你安装了请跳过。同时为确保后面的库安装的顺利。请更新下<code>homebrew</code></p>
<pre><code>$ brew update && brew upgrade </code></pre>
<p>等待几分钟即可</p>
<h3>安装PHP7</h3>
<p>然后在你的命令行中运行如下几行代码</p>
<pre><code>$ brew tap homebrew/dupes
$ brew tap homebrew/versions
$ brew tap homebrew/homebrew-php
//安装php7
$ brew install php70
//如果你通过homebrew安装了之前的php版本
//你可以解绑他们,如果用的就是mac自带的PHP 就跳过
$ brew unlink php56</code></pre>
<h3>配置apache文件</h3>
<pre><code>//用vim打开
$ sudo vim /etc/apache2/httpd.conf</code></pre>
<p>如果之前你的<code>httpd.conf</code>已经被改的乱七八糟了,建议你找到同个目录下的<code>httpd.conf~previous</code> 复制一直覆盖掉<code>httpd.conf</code></p>
<pre><code>//把php5的模块 注释掉
#LoadModule php5_module libexec/apache2/libphp5.so
//加入php7的模块
LoadModule php7_module/usr/local/opt/php70/libexec/apache2/libphp7.so</code></pre>
<h3>重启apache</h3>
<pre><code>$ sudo apachectl start
//or
$ sudo apachectl restart
//如果php发现不行,执行看看报错
$ apachectl
</code></pre>
vuejs实现一个简单的日期组件
https://segmentfault.com/a/1190000004416013
2016-02-04T21:20:14+08:00
2016-02-04T21:20:14+08:00
二胖手
https://segmentfault.com/u/cycok
2
<h2>介绍</h2>
<p>学习使用了一段时间的vue。和之前的jQuery相比。编程体验好了很多。尝试动手写一些简单的组件。<a href="https://link.segmentfault.com/?enc=OUPPN017ZVwiICUvYSC12w%3D%3D.Gx0jq7CcQpz2ymVZWVUz%2F%2B7UdTwLk30o6byenJ%2Fq0iNuYfWoDJzkjtIMnlSoM0d7" rel="nofollow">项目地址</a><br><img src="/img/bVsGX6" alt="图片描述" title="图片描述"></p>
<h2>组件解析</h2>
<p>calendarLine组件</p>
<pre><code> var calendarLine = Vue.extend({
props:['items', 'cur', 'sel', 'month'],
data(){
return {}
},
template: `<tr>
<td v-for="item in items" v-bind:class="{'dp-last': month!= item.month, 'dp-today': cur == item.data, 'dp-select': sel == item.data}">
<span @click="click(item)">{{ item.day }}</span>
</td>
</tr>`,
methods: {
click(item){
this.$dispatch('click', item.data)
}
}
})</code></pre>
<p>这个小组件是输出日历的一行,点击的时候通知父组件。<br>calendar组件(主要的)</p>
<pre><code> <div class="input-wrap">
<input type="text" class="input middle-input" @focus="foc" v-model="sel">
</div>
<div class="dp" v-show="show">
<div class="dp-header"><a class="dp-h-1" @click="cy(-1)">«</a><a class="dp-h-2" @click="cm(-1)">‹</a>
<span class="dp-ym">{{y}}年 {{m}}月</span>
<a class="dp-h-3" @click="cm(1)">›</a><a class="dp-h-4" @click="cy(1)">»</a></div>
<table class="dp-table">
<thead>
<tr>
<th><span>一</span></th>
<th><span>二</span></th>
<th><span>三</span></th>
<th><span>四</span></th>
<th><span>五</span></th>
<th><span>六</span></th>
<th><span>日</span></th>
</tr>
</thead>
<tbody>
<tr is="calendar-line" v-for="cell in data" :items="cell" :month="m" :cur="cur" :sel="sel"></tr>
</tbody>
</table>
<div class="dp-footer"><a @click="clickNow">{{sel}}</a> <span class="btn btn-ok" @click="show=false">确定</span></div>
</div>
</code></pre>
<p>关键看模版,这个组件接收一个date时间戳,自己生成当前时间,选择时间等。</p>
OSX、Linux 使用nvm 安装node环境
https://segmentfault.com/a/1190000004142879
2015-12-14T11:57:15+08:00
2015-12-14T11:57:15+08:00
二胖手
https://segmentfault.com/u/cycok
0
<h2>下载nvm包</h2>
<p>去<a href="https://link.segmentfault.com/?enc=SJFuLWfhB107gQpyrV7BCg%3D%3D.EDIF94S%2Bk0cL9%2BIE8nEPNo5JoSnoYDC1dKMa%2B13qg0BNVw8XgFSFNXSgpbydxfHD" rel="nofollow">nvm github</a>上按照install script,用curl或者wget。都试一下。注意如果一种方式失败了,请先删除残留文件再试另一种方法。</p>
<pre><code>curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash
wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash</code></pre>
<h2>放到默认路径</h2>
<p>上述步骤后,nvm还不能用,必须用nvm.sh。执行以下两行命令行即可</p>
<pre><code>export NVM_DIR=~/.nvm
source ~/.nvm/nvm.sh
</code></pre>
<h2>激活node</h2>
<pre><code>nvm install 5.0 //下载
nvm alias default 5.6 //指定新开的shell默认的node 版本</code></pre>
<p>git config --global credential.helper store//账号密码cache</p>
js各种小知识点备忘录(持续更新)
https://segmentfault.com/a/1190000004038512
2015-11-24T15:30:10+08:00
2015-11-24T15:30:10+08:00
二胖手
https://segmentfault.com/u/cycok
1
<h2>apply | call</h2>
<pre><code>function foo(data1,data2){
console.log(data1)
console.log(data2)
}
foo.call(this, '1', '2')
等效于 foo.apply(this, [1,2])</code></pre>
<p>apply跟的是数组,call就是按照参数的顺序</p>
<h2>split | join</h2>
<pre><code>var str = '1-2-3-'
var p = str.split(-) //["1","2","3",""] split分裂
var ar = [5,4,3,2,1]
var p2 = ar.join('x') //5x4x3x2x1 数组合并成字符串中间加 "x"
</code></pre>
<h2>splice | slice</h2>
<pre><code>//slice(片) 不会改变原来数组, splice(剪接)
slice(startIndex, endIndex)
slice(stratIndex)//缺少endIndex 就会执行到末尾
slice(-1)最后一个元素
splice(startIndex,length) //截取原来的数组</code></pre>
<p>数组下标 startIndex =< <strong>index</strong> <endIndex<br>当startIndex为负数的时候就会从最后的元素开始计算</p>
<h2>substr | substring</h2>
<pre><code>substr(start [, length ])
substring(start, end)
var str = '005'
str.substr(-2) //05返回最后两个字符
</code></pre>
<p>没有第二个参数就默认到最后<br>第一个参数为负数的时候从末尾算起</p>
<h2>Math - floor| round | ceil</h2>
<p>ceil 向上取整数<br>round 标准的四舍五入<br>floor 向下取整数</p>
<pre><code>var x = 12.3
var y = 12.6
Math.floor(x) === Math.floor(y) === Math.round(x) // 12
Math.ceil(x) === Math.ceil(y) === Math.round(y) // 13
</code></pre>
<h2>Array some | every| indexOf</h2>
<pre><code>var ar = [1,2,3,4,5]
ar.some(val => val == 1) // true 满足一个
ar.every(val => val == 1) //false 全都满足</code></pre>
<h2>Array Map</h2>
<p>返回一个新的数组</p>
<pre><code>let ar = [1,2,3]
ar.map(function(it, index, items){})</code></pre>
<h2>js数组删除指定元素</h2>
<pre><code>var ar = [1,2,3,4,5,6]
function deleteAr(ar){
for(var i = 0; i< ar.length; i++){
if(条件){
return ar.splice(i,1)
}
}
}</code></pre>
<h2>js Date 时间函数</h2>
<pre><code>var time = new Date(2016,0,1,12,11,22,111)
//年、月(-1)、日、时、分、秒、毫秒
//小技巧 var maxDay = new Date(2016,1,0) 可以获取2016年1月的最后一天
var year = time.getFullYear() //年
var month = time.getMonth() + 1 //月
var day = time.getDate() //日
var week = time.getDay() // 0~6 周日是 0</code></pre>
<h2>布尔值</h2>
<pre><code>undefined null 0 -0 NaN ""
//以上都会自动转换成false</code></pre>
<h2>对象数组拷贝</h2>
<pre><code>JSON.parse(JSON.stringify(originArray))
//数组深拷贝</code></pre>
<h2>正则表达式</h2>
<pre><code>( [ { \ ^ $ | ) ? * + . ] }</code></pre>
<h2>Array.reduce</h2>
<pre><code>array.reduce(callback[, initialValue])
var sum = [1, 2, 3, 4].reduce(function (previous, current, index, array) {
return previous + current;
});
console.log(sum); // 10</code></pre>
<p>callback函数接受4个参数:之前值、当前值、索引值以及数组本身。initialValue参数可选,表示初始值。若指定,则当作最初使用的previous值;如果缺省,则使用数组的第一个元素作为previous初始值,同时current往后排一位,相比有initialValue值少一次迭代。</p>
vue入门-实现一个分页组件(1.0.3版本)
https://segmentfault.com/a/1190000003931500
2015-10-30T17:28:53+08:00
2015-10-30T17:28:53+08:00
二胖手
https://segmentfault.com/u/cycok
13
<h2>vue</h2>
<p>关注前端社区的同学,一定知道vue。一个小巧、优雅 mvvm 框架。 目前是1.0.3正式版,然后中文文档还没更新上来。 使用了一段时间的感触就是,我再也不想直接操作DOM了。数据绑定式的编程体验真是好。实现的一个分页组件。</p>
<p><img src="/img/bVqEQu" alt="图片描述" title="图片描述"></p>
<h2>css</h2>
<pre><code>
ul,li{
margin: 0px;
padding: 0px;
}
li{
list-style: none
}
.page-bar li:first-child>a {
margin-left: 0px
}
.page-bar a{
border: 1px solid #ddd;
text-decoration: none;
position: relative;
float: left;
padding: 6px 12px;
margin-left: -1px;
line-height: 1.42857143;
color: #337ab7;
cursor: pointer
}
.page-bar a:hover{
background-color: #eee;
}
.page-bar .active a{
color: #fff;
cursor: default;
background-color: #337ab7;
border-color: #337ab7;
}
.page-bar i{
font-style:normal;
color: #d44950;
margin: 0px 4px;
font-size: 12px;
}</code></pre>
<h2>模版</h2>
<pre><code> <div class="page-bar">
<ul>
<li v-if="showFirst"><a v-on:click="cur--">上一页</a></li>
<li v-for="index in indexs" v-bind:class="{ 'active': cur == index}">
<a v-on:click="btnClick(index)">{{ index }}</a>
</li>
<li v-if="showLast"><a v-on:click="cur++">下一页</a></li>
<li><a>共<i>{{all}}</i>页</a></li>
</ul>
</div></code></pre>
<p><img src="/img/bVqEQ4" alt="图片描述" title="图片描述"><br>在未引入js前,页面的显示,分析下,all字段简单直接输出即可,{{index}}是分页码这个需要一些动态的渲染。</p>
<h2>js</h2>
<pre><code>var pageBar = new Vue({
el: '.page-bar',
data: {
all: 20, //总页数
cur: 1,//当前页码
});</code></pre>
<p>调用 <code>new Vue({参数}) </code>就是创建了一个基本的组件,赋值给变量 pageBar.<br>el就是element的缩写,定位模版的位置.data就是数据了.<br>知道了总页数但是要显示页码还是要一番计算,所以显示页码就是计算属性了.<br>所以我们要用computed</p>
<pre><code>computed: {
indexs: function(){
var left = 1
var right = this.all
var ar = []
if(this.all>= 11){
if(this.cur > 5 && this.cur < this.all-4){
left = this.cur - 5
right = this.cur + 4
}else{
if(this.cur<=5){
left = 1
right = 10
}else{
right = this.all
left = this.all -9
}
}
}
while (left <= right){
ar.push(left)
left ++
}
return ar
},
showLast: function(){
if(this.cur == this.all){
return false
}
return true
},
showFirst: function(){
if(this.cur == 1){
return false
}
return true
}</code></pre>
<p>ok这个页码显示规则是参考Baidu搜寻的 返回值就是[2,3,4,5,6]之类。<br>有了角标还需判断前一页、下一页的显示.增加showLast和showFirst字段(bool)<br>观看html模版发现<code>v-if</code>指令.很明显当内容是true就输出,否就没。<br>重点看下</p>
<pre><code> <li v-for="index in indexs" v-bind:class="{ 'active': cur == index}">
<a v-on:click="btnClick(index)">{{ index }}</a>
</li></code></pre>
<p><code>v-for</code>是循环渲染输出计算属性indexs.每一次循环的子元素赋值给index <code>v-bind:class</code>绑定class,当渲染到目前的角标的时候加个class <code>v-on:click</code>是绑定了事件,我把index当参数传进入了,后面做判断,默认传event事件.<br>然后我们给Vue的选项里面再增加methods字段</p>
<pre><code> methods: {
btnClick: function(data){//页码点击事件
if(data != this.cur){
this.cur = data
}
}
}</code></pre>
<h2>组件交互</h2>
<p>组件写完了,问题来了,用户点击发生页面改变,你怎么通知其他组件作出相应的变化. 可以在页角发生改变的函数下,插一条语句通知其他组件。不过这种方法是很差的做法。可以使用</p>
<pre><code>watch: {
cur: function(oldValue , newValue){
console.log(arguments)
}
}</code></pre>
<p>观察了cur数据当它改变的时候,可以获取前后值。然后通知其他组件。</p>
<p>完整的代码可以看 github:<a href="https://link.segmentfault.com/?enc=rSZ3dKAN%2FtiyaPkYxGBFdw%3D%3D.KHXKYpnr86n8YtaUO3g71C5uujObBLPoq8LehotARNCf1SW%2FZbqbUIOAOgCqzBc5" rel="nofollow">vue-pagination</a></p>
Node.js 官方URL模块简介
https://segmentfault.com/a/1190000003874963
2015-10-19T09:38:44+08:00
2015-10-19T09:38:44+08:00
二胖手
https://segmentfault.com/u/cycok
0
<h2>URL</h2>
<p>这个模块含有一些系列方法函数处理和解析URL<br>使用<code>require('url')</code>使用</p>
<h4>parsing(string)</h4>
<p>这个方法返回包含具体路由信息的对象<br>没有就返回null</p>
<pre><code>url.parse('http://user:pass@host.com:8080/p/a/t/h?query=string')
{
protocol: 'http:',
slashes: true,
auth: 'user:pass',
host: 'host.com:8080',
port: '8080',
hostname: 'host.com',
hash: null,
search: '?query=string',
query: 'query=string',
pathname: '/p/a/t/h',
path: '/p/a/t/h?query=string',
href: 'http://user:pass@host.com:8080/p/a/t/h?query=string#hash'
}</code></pre>
<ol>
<li><p>href,完整的路径</p></li>
<li><p>pathname,路径名字不包含参数</p></li>
<li><p>host比hostname多一个端口号</p></li>
</ol>
<h4>format(urlObj)</h4>
<p>同理这个函数就是根据obj的信息构造一个路径</p>
<pre><code>var obj =
{ protocol: 'https',
host: 'www.cycok.com:4000',
pathname: 'index'
}
url.format(obj)
//returns 'https://www.cycok.com:4000/index'</code></pre>
<h4>url.resolve(from, to)</h4>
<p>提供一个基础的路径,还有要去的路径,解析出浏览器最终会去的路径</p>
<pre><code>url.resolve('/one/two/three', 'four') // '/one/two/four'
url.resolve('http://example.com/', '/one') // 'http://example.com/one'
url.resolve('http://example.com/one', '/two') // 'http://example.com/two'</code></pre>
Node.js 官方Path模块简介
https://segmentfault.com/a/1190000003874170
2015-10-18T22:57:14+08:00
2015-10-18T22:57:14+08:00
二胖手
https://segmentfault.com/u/cycok
0
<h2>Path</h2>
<p>这个模块包含了用于处理文件路径相关的操作的函数。</p>
<pre><code>var path = requie ('path')</code></pre>
<h4>path.normalize(p)</h4>
<ol>
<li><p>返回正常的文件夹路径。主要处理 '..' 和 '.'的部分。</p></li>
<li><p>发现多斜杆转换为单斜杆。</p></li>
<li><p>windows下变成反斜杠</p></li>
</ol>
<pre><code>path.normalize('a/b/../c//d')
//returns 'a/b/d'</code></pre>
<h4>path.join(path1[, ...])</h4>
<p>把参数路径全部拼凑起来成为最终路径会计算'..' 和 '.'</p>
<pre><code>path.join('/foo', 'bar', 'baz/asdf', 'quux', '..')
// returns '/foo/bar/baz/asdf'</code></pre>
<h4>path.resolve([from ...], to)</h4>
<p>返回一个绝对路径</p>
<pre><code>path.resolve('static')
// returns '/Users/cycok/github/simple-server/static'
path.resolve('/home')
// returns '/home'</code></pre>
<h4>path.isAbsolute(path)</h4>
<p>判断一个路径是不是绝对路径。<br>返回true or false</p>
<h4>path.relative(from, to)</h4>
<p>计算两个参数的距离位置</p>
<pre><code>path.relative('static', '/Users')
// returns '../../../..'</code></pre>
<h4>path.dirname(p)</h4>
<p>返回文件或者文件所在的文件夹名字</p>
<pre><code>path.dirname('static/a.js')
// returns 'static'
path.dirname('te.js')
// returns '.'</code></pre>
<h4>path.basename(p[, ext])</h4>
<p>返回路径的最后部分</p>
<h4>path.extname(p)</h4>
<p>返回文件的后缀带.的 <br>没有就返回''</p>
<h4>path.sep</h4>
<pre><code>'foo/bar/baz'.split(path.sep)
// returns
['foo', 'bar', 'baz']</code></pre>
<h4>path.parse(pathString)</h4>
<p>解析路径返回一个json</p>
<pre><code>path.parse('/home/user/dir/file.txt')
// returns
{
root : "/",
dir : "/home/user/dir",
base : "file.txt",
ext : ".txt",
name : "file"
}</code></pre>
<h4>path.format(pathObject)</h4>
<p>根据对象组装成一个路径</p>
<pre><code>path.format({
root : "/",
dir : "/home/user/dir",
base : "file.txt",
ext : ".txt",
name : "file"
})
// returns
'/home/user/dir/file.txt'</code></pre>
React API说明
https://segmentfault.com/a/1190000003763081
2015-09-18T13:26:22+08:00
2015-09-18T13:26:22+08:00
二胖手
https://segmentfault.com/u/cycok
0
<h2>组件规格</h2>
<p>当创建一个React组件,并调用 <code>React.createClass()</code>,你需要提供一些<code>Object</code>对象,例如必须的<code>render</code>,还有其他一些可选的<code>Object</code>对象。</p>
<h3>render</h3>
<p>这个函数对象必须存在,且一定存在返回值。</p>
<pre><code>render: function () {
return (<h2>Hello, World!</h2>);
}</code></pre>
<p>官方规范说明这个方法一定要pure(干净),保证职责单一,所有数据通过<code>props</code>和<code>state</code>来。利于组件的复用和维护。写React一定要约束好各种规范!<br>返回值是 <code>ReactElement</code></p>
<h3>getInitialState</h3>
<pre><code>object getInitialState()</code></pre>
<p>在组件装载前会调用一次,函数的返回值对象,可以在<code>this.state</code>查询和使用。</p>
<h3>getDefaultProps</h3>
<p>设置组件props默认值</p>
<pre><code>object getDefaultProps()</code></pre>
<p>在组件装载前会调用一次,函数的返回值对象,可以在<code>this.props</code>查询和使用。<br>和state不同的是,props在每个实例里都可以访问到,只会拷贝一次,而<code>this.state</code>是实例独享的。</p>
<h3>propTypes</h3>
<pre><code>object propTypes</code></pre>
<p>可以约束检测你的参数的,发现不匹配就会<code>console.wran()</code>来提示错误,但是不会报错不执行。</p>
<h3>mixins</h3>
<pre><code>array mixins</code></pre>
<p>支持多个组件之间共享公用的方法,共享使用共同的变量和方法。</p>
<h3>statics</h3>
<pre><code>object statics</code></pre>
<p>给你的组件增加静态的方法。</p>
<pre><code>var MyComponent = React.createClass({
statics: {
customMethod: function(foo) {
return foo === 'bar';
}
},
render: function() {
}
});
MyComponent.customMethod('bar'); // true</code></pre>
<h3>displayName</h3>
<pre><code>string displayName</code></pre>
<p>用于debug时候的定位。</p>
<h2>生命周期方法</h2>
<h3>实例化</h3>
<p>当首次使用组件类时,下面这些方法依次被调用。</p>
<ul>
<li><p>getDefaultProps</p></li>
<li><p>getInitialState</p></li>
<li><p>componentWillMount</p></li>
<li><p>render</p></li>
<li><p>componentDidMount</p></li>
</ul>
<p>当组件类再次被调用时<code>getDefaultProps</code>和 <code>getInitialState</code>方法不会被调用。</p>
<h3>存在期</h3>
<p>当实例已经生成,修改属性时,以下方法会依次被调用</p>
<ul>
<li><p>componentWillReceiveProps</p></li>
<li><p>shouldComponentUpdate</p></li>
<li><p>componentWillUpdate</p></li>
<li><p>render</p></li>
<li><p>componentDidUpdate</p></li>
</ul>
<pre><code>componentWillReceiveProps(nextProp){
//todo
}</code></pre>
<p><code>componentWillReceiveProps</code>是当组件props改变的时候触发</p>
MongoDB 常用指令
https://segmentfault.com/a/1190000003717873
2015-09-07T20:48:47+08:00
2015-09-07T20:48:47+08:00
二胖手
https://segmentfault.com/u/cycok
0
<blockquote><p>MongoDB 常用基础指令 备忘录。</p></blockquote>
<h2>启动MongoDB</h2>
<pre><code>$ ./mongod --dbpath</code></pre>
<ul>
<li><p>--dbpath 默认值/data/db/ 指定数据目录,当mongod启动会锁定文件目录</p></li>
<li><p>--port 指定服务器监听的端口号,默认27017</p></li>
<li><p>--fork 以守护进程的方式运行MongoDB使用时 <strong><em>必须指定日志文件</em></strong></p></li>
<li><p>--logpath 指定日志输出文件覆盖的 --logappend 以追加的方式</p></li>
<li><p>--config 指定配置文件</p></li>
<li><p>--nohttpinterface 关闭http管理接口</p></li>
</ul>
<h2>停止MongoDB</h2>
<p>第一种是linux指令</p>
<pre><code>$ killall mongod
$ kill 10014(SIGTERM)</code></pre>
<p>第二种是进入mongo数据库 <strong>( 推荐 )</strong></p>
<pre><code>>use admin
switched to db admin
>db.shutdownServer();
server should be down ...</code></pre>
<h2>创建文档</h2>
<pre><code>> post = {title: 'is title', content: 'is content'};
> use mydb;
> db.mydb.insert(post);</code></pre>
<h2>读取文档</h2>
<pre><code>> db.mydb.findOne({查询条件},{要显示的字段}) // 查找一个
> db.mydb.find({title: 'is title'},{title: 1, content: 0}) //查找</code></pre>
<p><strong> 查询条件 </strong></p>
<pre><code>> db.user.find({"age" : {"$gte":18, "$lte": 30})
> db.user.find({"username": {"$ne": "joe"}});</code></pre>
<p>查询18~30(含)去掉e就是不含<br>"$ne"不等于,查询username不为joe的集合。<br>"$in":[123,222.555] 多个值<br>"$or":[{"username":"小明"},{title:'其他条件可以用or'}]<br>"$not" 可以用在任何其他条件之上<br><strong> 查询排序 </strong></p>
<pre><code>> db.c.find().limit(50).skip(3).sort({username: 1, age: -1})</code></pre>
<p>limit上限50个跳过前3个排序按照username升序 age 降序</p>
<h2>更改文档</h2>
<p><strong> 文档替换 </strong></p>
<pre><code>> db.users.update({'name':'abc'}, {替换者})</code></pre>
<p><strong> 使用修改器 </strong></p>
<pre><code>> db.users.update({条件},{修改器})</code></pre>
<p>部分更新使用修改器<br>$set:{"$set": {"username":"小明"}}; //设置用户名为小明<br>$inc:{"$inc": {"age":100}}; //年龄加100岁<br>$push:数组添加字段</p>
<h2>删除文档</h2>
<pre><code>> db.users.remove({条件}) //删除某个集合
> db.users.drop() //删除整个文档</code></pre>
H5全屏滑动
https://segmentfault.com/a/1190000003691168
2015-08-31T18:45:11+08:00
2015-08-31T18:45:11+08:00
二胖手
https://segmentfault.com/u/cycok
10
<blockquote><p>移动web时代,学会做一些简单H5页面会很受用。比如最常见的活动营销简历H5页面是一个全屏滚动页面(fullpage)。以下就是一个简单的例子。 <strong>DEMO</strong>:<a href="https://link.segmentfault.com/?enc=NAIwhVUvRlcc384G4ehfPw%3D%3D.5Qpp%2BhDiDjeEmMod0BLw%2FXUu8DjrV8t9VhONlCWmNu7h702eaAkjnWvB14F4s%2BKK" rel="nofollow">Demo地址</a></p></blockquote>
<h2>空的页面</h2>
<hr>
<p>新建一个空的html5页面,在<strong>head</strong>标签里面加入两个meta标签</p>
<pre><code> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"></code></pre>
<p>第一个标签是引导浏览器使用最新内核。<br>第二个标签是控制设备的视口宽度为屏幕宽度,然后静止缩放,模拟原生app的感觉。</p>
<p>这个是apple公司定的规则,并没有写入w3c规范,但是成为了业内标准。浏览器厂商都约定俗成了。<br><img src="/img/bVpEkM" alt="图片描述" title="图片描述"><br>就是这样的一个空的页面了。</p>
<h2>css html</h2>
<hr>
<pre><code><div class="main-wrap">
<div class="main">
<div class="section a">
<h1>这是屌屌的第一屏页面222</h1>
</div>
<div class="section b">
<h1>这是霸气的第二屏页面</h1>
</div>
<div class="section c">
<h1>这是呵呵的第三个屏页面</h1>
</div>
</div>
</div></code></pre>
<pre><code>body{
padding: 0;
margin: 0;
overflow: hidden
}
.section{
width: 100vw;
height: 100vh;
}
h1{
margin: 0px;
}
.main-wrap{
width: 100vw;
height: 100vh;
overflow: hidden;
position: relative;
}
.main {
position: absolute;
top: 0px;
left: 0px;
transition: 500ms cubic-bezier(0.86, 0, 0.07, 1);
}</code></pre>
<p>先解释两个css3属性,<code>width: 100vw</code>是指宽度和设备宽一致同理<code>100vh</code>,<code>transition</code>是<code>css3</code>的一个属性过度。<code>cubic-bezier(0.86, 0, 0.07, 1);</code>是一个自定义 贝泽尔曲线。这是一个磁性滚动的过度,嗯,参数我是抄锤子科技的。</p>
<p>首先清下body和h1的内置样式。<code>main-wrap</code>是最外面的一个DOM节点相当于窗口的作用,是固定不动的,宽高和设备一致。<br><code>main</code>就是包含屏幕块的标签,操作top值,实现动画。写过Banner动画的同学肯定不陌生。类似的原理。然后每个<code>section</code>就是一个屏的内容。</p>
<h2>手势库</h2>
<hr>
<p>移动端和PC端在事件中有很多不同,比如没有hover事件了,click比tap慢几百毫秒了,等等,反正坑很多,同志一起好好学吧~。移动端一共有4种触摸事件:</p>
<ol>
<li><p>touchstart,在用户的手指触摸屏幕的瞬间触发。</p></li>
<li><p>touchmove,在用户移动手机的过程中连续触发。</p></li>
<li><p>touchend,用户的手指离开屏幕的瞬间触发。ios离开webview边界不会触发。</p></li>
<li><p>touchcancel,很特殊,浏览器差异,(不需理会)。</p></li>
</ol>
<p>任何手势就是计算这几个事件内的值加减乘除来判断各种手势。<br>最直接的就是引入一个开源的手势库。Hammer就是我比较推荐的一个手势库。<br>我用的是最新版2.0.4<br><a href="https://link.segmentfault.com/?enc=1NAkAZX9XoFuwFLd0g2QzA%3D%3D.sSgvd0TDcROTJWudbwzcHHnKTWilcntTZcTPHmVx1529loZ61IYio9cz5Np4tBhR" rel="nofollow">Hammer介绍页</a><br><img src="/img/bVpEoX" alt="手势" title="手势"></p>
<h2>JS部分</h2>
<hr>
<pre><code>var sHeight = document.querySelector('.a').clientHeight;
//获取一屏的高度,判断该移动多少
var sLength = document.querySelectorAll('.section').length;
//判断有几屏页面
var sIndex = 0;//标记当前第几页
var sScroll = false;//滚动时就不再触发事件,防止误点
var main = document.querySelector('.main'); //需要移动的DOM
window.onmousewheel = function(e){
//PC端的滚轮事件,嗯不兼容火狐
if(!sScroll){
if(e.wheelDelta>0){
//上一页
if(sIndex == 0){return; }
sIndex--;
scrollTo(sIndex);
}else{
//下一页
if(sIndex == sLength-1){return;}
sIndex++;
scrollTo(sIndex);
}
}
}
function scrollTo(i){
//操作动画的函数
sScroll = true;
main.style.top = -i*sHeight + 'px';
setTimeout(function(){sScroll = false}, 700);
}
var hamm = new Hammer(document.querySelector('.main-wrap'));
hamm.get('swipe').set({ direction: Hammer.DIRECTION_ALL});
//hammer默认关闭上下swipe 设置开启上下滑屏
hamm.on('swipedown', function(){
if(!sScroll){
//上一页
if(sIndex == 0){return; }
sIndex--;
scrollTo(sIndex);
}
});
hamm.on('swipeup', function(){
if(!sScroll){
//下一页
if(sIndex == sLength-1){return;}
sIndex++;
scrollTo(sIndex);
}
});
</code></pre>
<p>最后放张完整的js部分的图:<br><img src="/img/bVpEo2" alt="js" title="js"></p>
Linux下mongodb的安装
https://segmentfault.com/a/1190000003475446
2015-08-22T10:22:02+08:00
2015-08-22T10:22:02+08:00
二胖手
https://segmentfault.com/u/cycok
0
<h2>MongDB Linux安装</h2>
<p><h1>使用场景</h1><br>首先我觉得<code>MongoDB</code>非常的适合小规模网站的数据库。因为它非常的简单易用。 比如个人博客网站的使用。而且我建议只要在Linux下的安装即可。你工作的环境肯定是有网络的。开发的时候直接连到数据库即可。可以用两套data。</p>
<blockquote><p>检测当前环境</p></blockquote>
<pre><code>$ uname -m
x86_64</code></pre>
<p>检测到当前的环境是Linux 64位 所以我们去下载代码吧。貌似官网提供的是已经编译好的二进制文件。所以我们一定要选对哦。下载页面和官方指导页面</p>
<p><a href="https://link.segmentfault.com/?enc=5gV8QumQiy0Ts1bdx0vwkQ%3D%3D.mPbAqwA5nq6Mx%2BC3TadbgeGptSeUNbOm%2FlbNxOxRbwQQ4NzAqCLkgnNH3qSXB9p7" rel="nofollow">下载页面</a><br><a href="https://link.segmentfault.com/?enc=9Obfp7ojAfxVejg0d%2BQTuw%3D%3D.iKNzmWeGM%2F2y7l%2Fs38Z0fTI%2Bq7yZkX9JkjZvD8htmKLgjh8pvtIW94LB2BP8sQiboIavqXaLytd9loreKTpNXcufjMyP87uaT8CTLaQkIqAIBdYMw6HJd%2BhNBuvZuPOzSC7b5OkIsiJlrIfChq8LeQ%3D%3D" rel="nofollow">指导安装</a></p>
<pre><code>$ cd</code></pre>
<p>先切换到当前用户根目录<br>我是在/root目录下的,如果你不是root就是在/home/用户名/ 下面<br>如果不是root遇到权限问题。就sudo 和chmod -R 777来解决吧 简单粗暴。</p>
<blockquote><p>下载解压缩</p></blockquote>
<pre><code>curl -o https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.5.tgz</code></pre>
<p>下完之后呢解压缩。</p>
<pre><code>tar -zxvf mongodb-linux-i686-3.0.5.tgz</code></pre>
<blockquote><p>启动</p></blockquote>
<pre><code>cd mongodb-linux-x86_64-3.0.5
bin/mongod</code></pre>
<p>如果启动失败了 记得先创建一个/data/db文件夹 这是默认启动的文件夹。<br>更多命令参数 可以看文档。</p>
初试express
https://segmentfault.com/a/1190000003064403
2015-08-07T18:19:52+08:00
2015-08-07T18:19:52+08:00
二胖手
https://segmentfault.com/u/cycok
1
<h3>express是什么?</h3>
<p><code>express</code> 是nodejs一个很著名的框架。 其地位就有点像<code>react</code>在js里面的地位。就算你不打算使用它,也可以学习下,取长补短。express的核心就是<strong>中间件</strong></p>
<blockquote>
<p>要实现的功能如下</p>
</blockquote>
<ol>
<li>创建一个http服务器</li>
<li>能够返回静态文件</li>
<li>能够提供api</li>
</ol>
<pre><code>var express = require('express');
var app = express();
app.use(function(req, res){
res.send('hello express!');
});
app.listen(8001,function(){
console.log('监听8001端口');
});
</code></pre>
<p>ok 上述代码就实现功能一。默认监听的本地IP 网址:<a rel="nofollow" href="http://localhost">http://localhost</a> 它对于一切返回值都返回了hello express!<br>
对比于nodejs的hello world.例子。细心的你会发现少了输入res头的步骤。<code>res.writeHead(200,xxx)</code>,没错这是框架已经帮你处理掉的。默认就是<strong>200 text/html</strong>。当然你也可以自定义返回头,res.type()之类,具体请查看api。</p>
<pre><code>var express = require('express');
var app = express();
app.use(express.static('static', {Mixed: false}));
app.use(function(req, res){
res.send('hello express!');
});
app.listen(8001,function(){
console.log('监听8001端口');
});
</code></pre>
<p><img src="/img/bVm1iA" alt="图片描述"></p>
<p>你大概需要这样的文件结构。<code>express.static</code>是express4 目前仅保留的中间件,也是目前唯一保留的一个中间件(可见其钢需,与通用)。查看其中源模块是serve-static。小小的一行中间件其实代码量还是很复杂。具体可以看一篇文章nodejs实现静态服务器。很细致全面的说明了一个静态服务器所要做的事情。<br>
第一个参数'static'是表示静态文件目录名字没有/说明是相对路径哦 '/static'是绝对路径,当你路由写在其他目录里要小心了区分下。<br>
{Mixed: false}是当路径为'/'返回静态文件下的不返回index.html</p>
<pre><code>var express = require('express');
var app = express();
app.use(express.static('static', {Mixed: false}));
app.get('/get',function(req, res){
var data = {msg: '这是get'};
res.json(data);
});
app.get('/post',function(req, res){
var data = {msg: '这是post'};
res.json(data);
});
app.use(function(req, res){
res.send('hello express!');
});
app.listen(8001,function(){
console.log('监听8001端口');
});
</code></pre>
<p>这样就服务器就提供了两个api接口,地址是'/get'和'/post',返回这时候就是一个json对象。用的方法是res.json()区别于res.send()就是组装成json格式。 至此就完成了三个基本功能。迈出了第一步!</p>
react 之 Hello Horld!
https://segmentfault.com/a/1190000002895126
2015-06-11T16:40:25+08:00
2015-06-11T16:40:25+08:00
二胖手
https://segmentfault.com/u/cycok
0
<blockquote>
<p>Hello world!</p>
</blockquote>
<p>其实这是我第一次写文章,好紧张 - -</p>
<hr>
<p>下载react.js<br><a rel="nofollow" href="http://facebook.github.io/react/index.html">点这个就是地址了</a><br>
或者用npm install react<br>
注意找出<strong>react.min.js</strong> 和JSXTransformer.js</p>
<p>然后各位少侠请先新建一个HTML文件,什么名字无所谓吧</p>
<hr>
<pre><code><!DOCTYPE html>
<html>
<head>
<title>react start</title>
</head>
<body>
<div id="example"></div>
<script src="react.min.js"></script>
<script src="JSXTransformer.js"></script>
<script type="text/jsx">
React.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script>
</body>
</html>
</code></pre>
<hr>
<p>很顺利页面就输出了 Hello, world! 我懒得截图了 - -</p>
<p>然后我们开始分析了</p>
<pre><code><script type="text/jsx">
</code></pre>
<p>为虾米 type = text/jsx<br>
这时候我们把</p>
<pre><code><script src="JSXTransformer.js"></script>
</code></pre>
<p>注释掉<br>
发现页面里面什么都没有了 - - 这就对了<br>
会想下script标签加上text里面内容就变成了文本了 不执行了~<br>
那刚才怎么输出呢,肯定和JSXTransformer.js有关咯<br>
哼,我可是过了四级呢!! 一看我就明白了这个是个JSX转换器咯.把jsx类型的文本转换成正常的js<br>
输出 plain javascript对吧 嘿嘿~</p>
<p>这时候把script 的 type去掉 js执行看看</p>
<p>!!报错了 什么鬼<img src="/img/bVmjhv" alt="图片描述"></p>
<p>确实js这么写 语法都不通过了</p>
<p>JSX是facebook自己定的协议 通过JSXTransformer.js转换就正常执行了.<br><strong>好了着时候开始吐槽了!</strong><br>
我明明是来学react 写一个hello world的 为什么多出来一个JSXTransformer啊?<br>
一点心理准备都没有啊! 你叫我学我就学? 这不在我计划之内啊 ,我想一步步来弄啊~。<br>
能不能只用react.js写一个hello world啊!</p>
<h2>能</h2>
<pre><code><!DOCTYPE html>
<html>
<head>
<title>react start</title>
</head>
<body>
<div id="example"></div>
<script src="react.min.js"></script>
<!-- <script src="JSXTransformer.js"></script>-->
<script>
var Hello = React.createClass({
render: function(){
return (
React.createElement('div',{},'Hello world!')
)
}
})
React.render(
React.createElement(Hello),
document.getElementById('example')
);
</script>
</body>
</html>
</code></pre>
<p>还是用JSX吧 虽然一开始让我用 我是拒绝的,但写了两天发现也习惯了,况且人家是大公司对吧他们这么用一定有他们的道理,以后项目做大,自然会领悟其中的道理。</p>