ivan 发布于 02月09, 2017

如何优雅地写react

如何优雅的写react

使用react写项目的时候,代码如何写的简洁易懂,小结如下。

优雅的组件应该是这样的....

  • are easy to understand even without comments
  • can be even more performant than clunky code
  • increase the chances of catching bugs before they reach QA
  • are concise and say a lot with a little

"Less is more." — Mies van der Rohe

SFC(The Stateless Functional Component) 函数式无状态组件

我们编写组件的时候,并不是所有的组件都是需要状态的。由于react是以数据驱动,数据决定了react组件的输出结果,所以为了让我们组件更好控制,应该尽量的少使用状态。

栗子

let Hello = props => <div>Hello {props.name}</div>

还可以利用es6的解构赋值再来精简,适用于props的数量少的时候

let Hello = ({name}) => <div>Hello {name}</div>

1.无生命周期函数 一个组件就是一个函数,函数应该是谈不上生命周期的,但是组件却是有生命周期,stateless functions 没有生命周期。当然了,我们其实可以使用高阶组件 去实现生命周期。

2.没有 this 在 stateless functions 中,this 是 undefined,所以是不能使用 this 变量。不过换个角度思考,this 是在运行时随时可以被修改或重新赋值,跟外界环境有着密切的联系,正是不使用this才会让组件变得更纯。

3.使用到refs时不能使用无状态组件,因为无状态组件只是函数,所以它没有实例返回,这点在想用 refs 获取无状态组件的时候要注意

条件判断

JSX不支持if条件判断,使用三元判断来显示不同的组件。

类型1:A或者B

render() {
  <div class="search-results-container">
    {this.props.isGrid
      ? <SearchResultsGrid />
      : <SearchResultsList />}
  </div>
}

类型2:展示或者不展示

render() {
  <div class="search-results-list">
    {this.props.isSoftSort
      ? <SoftSortBanner />
      : null
    }
  </div>
}

这样写没问题,但是那个null总是怪怪的。 一种更优雅的方式:

render() {
  <div class="search-results-list">
    {!!this.props.isSoftSort && <SoftSortBanner />}
  </div>
}

PS:!!不要省略,否则一些逻辑非(比如数字0)就会在react渲染出来。

箭头函数(哦,好用!)

当你只需要一个参数或者多个参数(需要用小括号包裹参数)的简单函数时,可以使用新标准中的箭头函数,它的语法非常简单:标识符=>表达式。无需输入function和return,一些小括号、大括号以及分号也可以省略。

const SoftSort = ({ hardSortUrl, sortByName, onClick }) => {
  return (
    <div className="SearchInfoMessage">
      Showing results sorted by both Relevance and {sortByName}.
      <Link
        href={`?${hardSortUrl}`}
        onClick={(ev) => onClick(ev, hardSortUrl)}>
        Sort results by {sortByName} only
      </Link>
    </div>
  );
};

普通function函数和箭头函数的行为有一个微妙的区别,箭头函数没有它自己的this值,箭头函数内的this值继承自外围作用域。

阅读全文 »

ivan 发布于 09月09, 2016

javascript随机-只是为了贴代码

/**
 * Randomize array element order in-place.
 * Using Durstenfeld shuffle algorithm.
 */
function shuffleArray(array) {
    for (var i = array.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    return array;
}
Array.prototype.shuffle = function() {
  var i = this.length, j, temp;
  if ( i == 0 ) return this;
  while ( --i ) {
     j = Math.floor( Math.random() * ( i + 1 ) );
     temp = this[i];
     this[i] = this[j];
     this[j] = temp;
  }
  return this;
}

阅读全文 »

ivan 发布于 09月08, 2016

javascript随机函数

随机取一个值: 一般情况下代码逻辑放在后端处理,前端只负责展现。 但是若是若是后端不愿意做,e...那么前端需要能够实现。

需求:实现一个数组的打乱重拍。若是直接从数组中随机取一个值比较简单,直接var item = items[Math.floor(Math.random()*items.length)]得到一个随机值。下面看怎么对数组进行重新排序。

so ... 遇到问题第一步,先查查网上有木有已经实现的比较好的方式~ Fisher-Yates binggo!

Fisher-Yates乱序算法

思路,假如你要洗牌,那么最随机的做法就是从牌堆里随便抽一张出来,然后放在一边,之后从剩下的牌里重复之前的操作,直到所有牌都被抽出来放到另外一堆中。

round 1


随机从数组里取出一个元素,保存到另一个数组,然后重复之,直到原数组中所有元素为空。 查看演示

function shuffle(array) {
    var copy = [],
        n = array.length,
        i;
    // 如果还剩有元素则继续。。。
    while (n) {
        // 随机抽取一个元素
        i = Math.floor(Math.random() * array.length);
        // 如果这个元素之前没有被选中过。。
        if (i in array) {
            copy.push(array[i]);
            delete array[i];
            n--;
        }
    }
    return copy;
}

问题:我们新建一个数组,每次都会随机取一个0-len的随机值,随机值可能一样;另外一方面可能永远运行不完。

注: Math.random()产生[0,1)的小数 delete 操作只将数组元素的值删除,但不影响数组长度,删除后原来位置的值变为undefined

round 2


用Array的splice()方法将其从目标数组中移除同时也更新了目标数组的长度,如此一来下次遍历的时候是从新的长度开始,不会重复处理的情况了。 查看演示

function shuffle(array) {
    var copy = [],
        n = array.length,
        i;
    // 如果还剩有元素。。
    while (n) {
        // 随机选取一个元素
        i = Math.floor(Math.random() * n--);
        // 移动到新数组中
        copy.push(array.splice(i, 1)[0]);
    }
    return copy;
}

round 3


因为调用splice来删除数组元素会导致删除位置之后的所有元素要做shift操作来向前补充,从而达到将数组长度减小的目的,当然这是在后台自动完成的,但这无疑增加了算法的复杂度。

注意到我们要做的仅仅是将数组元素重新排序,已经取出来的元素和剩下的元素之和一定是等于数组原来的总元素个数的。所以可以考虑不创建新的数组来保存已经抽取的元素,可以这样,随机从数组中抽出一个元素,然后与最后个元素交换,相当于把这个随机抽取的元素放到了数组最后面去,表示它已经是被随机过了,同时被换走的那个元素跑到前面去了,会在后续的重复操作中被随机掉。一轮操作过后,下一轮我们只在剩下的n-1个元素也就是数组的前n-1个元素中进行相同的操作,直到进行到第一个。 查看演示

function shuffle(array) {
    var m = array.length,
        t, i;
    // 如果还剩有元素…
    while (m) {
        // 随机选取一个元素…
        i = Math.floor(Math.random() * m--);
        // 与当前元素进行交换
        t = array[m];
        array[m] = array[i];
        array[i] = t;
    }
    return array;
}

不急,还有一个,真是简洁。但是随机效果不好。

round 4


function shuffle(array) {
    return array.sort(function() {
        return Math.random() - 0.5
    });
}

⬆️ 这厮有bug! 在IE 11上。sort方法的返回值应该是0,1,-1。这里返回true和false。 所以,改进之后:

function shuffle(array) {
    return array.sort(function() {
        return Math.random() > 0.5 ? 1: -1;
    });
}

生成一个1-len的数组。

  • Array.from(Array(len).keys()); //返回[0-length]的数组
  • Math.pow(2, len).toString(2).split('').map((i,j) => j);
  • Array(N).fill().map((_, i) => i + 1);
  • Array.from(Array(5)).map((_, i) => i + 1);

阅读全文 »

ivan 发布于 09月01, 2016

有感。

大牌前端小记

1.需求方面 - 开发过程中并没有按照需求文档的内容来完善。需求文档很多细节交互不清晰,后期一直在不断的更改需求/新加需求。 页面布局确定之后又会做出调整。

2.代码方面 - 代码的可维护性,写代码的时候需要考虑代码的强壮性,不要单纯的把代码从一个地方复制粘贴到另外一个地方,了解每个代码的含义以及可能的影响内容。另外使用smarty模版写页面的时候,可以统一foreach循环出来,否则相似内容写的很乱,并且操作事件时会有各种绑定事件,混杂并且不精简,不优雅。

3.bug -bug出现之后,不要着急的想用一个很hack的方式去实现,而是需要考虑底层原因,为什么会出现这样的问题?浏览器兼容性问题还是代码逻辑问题?一上来就用一个很hack的方式去解决问题就会导致各种逻辑混杂在一起,第二天就只有上帝知道你代码逻辑了。

4.心态 -问题一个一个来,并不是每一个需求都要改并不是每个任务都很紧急,对所做事件进行合理排期,不慌张效率才会高。

另外,解别人代码bug一定要三思。改动较小则好,改动较大,建议提早重构。

阅读全文 »

ivan 发布于 08月24, 2016

浏览器窗口定位

需求:

如下图所示,需要知道黄色模块距离浏览器底部的距离,若距离底部距离小于0,需要向上滚动至露出黄色模块。具体布局参数见代码:

<style>
   html,body{padding: 0;margin:0;}
   .wrap{position: relative; width: 100%;height: 800px;  background: #eaeaea;}
   .poi{position:absolute; margin-top: 300px; width: 100%; height: 100px; background: #ef0; text-align: right;}
</style>
<div class="wrap">
   <div class="poi">poi</div>
</div>

不解释:

<script>
   $(function(){
       var wh = $(window).height();
       var dh = $(document).height();
       var sh = $(window).scrollTop();
       var bh = $(".poi").offset().top;
       var h = $(".poi").height();
       var to_btm = wh - bh + sh -h;
       console.log("浏览器视窗高度:"+wh);
       console.log("页面文档高度:"+dh);
       console.log("页面向上滚动高度:"+sh);
       console.log("元素距离页面顶部高度:"+bh);
       console.log("元素自身高度:"+h);
       console.log("元素底部距离浏览器的高度:"+to_btm);
   });
</script>

解释如图:

ps:

$('html,body').animate({scrollTop:bh+100},500);

阅读全文 »

ivan 发布于 08月19, 2016

node路径问题&path模块处理文件路径

常见路径:

node中的文件路径主要有__dirname__filenameprocess.cwd()./../,前三个都是绝对路径,为了便于比较,./../我们通过path.resolve('./')来转换为绝对路径。

举个栗子:

假如我们有这样一个目录结构:

app/
    -lib/
        -common.js
    -model/
        -task.js
        -test.js

在test.js里编写如下的代码:

var path = require("path");
console.log(__dirname);
console.log(__filename);
console.log(process.cwd());
console.log(path.resolve("./"));

在model目录下运行node task.js得到的输出是:

/home/ivan/app/model
/home/ivan/app/model/task.js
/home/ivan/app/model
/home/ivan/app/model

然后在app目录下运行node model/task.js,得到输出结果:

/home/ivan/app/model
/home/ivan/app/model/task.js
/home/ivan/app
/home/ivan/app

依上,我们是否可以得到这样的一个结论:

  • __dirname总是返回被执行的js所在文件夹的绝对路径。
  • __filename总是返回被执行js文件的绝对路径。
  • process.cwd()总是返回运行node命令所在的文件夹的绝对路径。
  • ./process.cwd()一样一样的。

但是经常见到 require('../lib/common')里一直都是各种相对路径写,也没见什么报错呀, 再举个栗子,还是上面的结构,model/task.js里的代码改成:

var fs = require("fs");
var common = require("../lib/common");

fs.readFile("../lib/common.js", function (err, data) {
    if (err) return console.log(err);
    console.log(data);
});

在model目录下运行node task.js,一切OK,都没有报错。然后在app目录下运行node model/task.js,然后很果断的就报错了:

{ [Error: ENOENT: no such file or directory, open "../lib/common.js"]
  errno: -2,
  code: "ENOENT",
  syscall: "open",
  path: "../lib/common.js" }

所以,问题来了。按照前面得到的结论,./process.cwd()一样一样的。那么在model目录下执行的时候,../lib/common.js会被转变成/home/ivan/app/lib/common.js,在app目录下执行的时候,../lib/common.js会被转变成/home/ivan/lib/common.js,这个路径是不存在的,但是从运行结果来看,require('../lib/common')是OK的,只是readFile时报错了。

那么关于./正确的结论出来了: 在require()中使用的是跟__dirname的效果相同,不会因为启动脚本的目录不一样而改变,在其他情况下跟process.cwd()效果相同,是相对于启动脚本所在目录的路径。

总结

所以事实证明前端得到的结论中1,2,3是OK的,最后一个不准确。

只有在require()时才使用相对路径的写法,其他地方一律使用绝对路径,如下:

var path= require(“path”);
//当前目录下
path.dirname(__filename)+"/test.js";
//相邻目录下
path.resolve(__dirname, "../lib/common.js");

扩展

Node.js使用path模块处理文件路径

  • path.normalize(p) 文件路径处理 path模块中的normalize()方法用来规范化路径字符串。可用于处理路径中的"//"、".."、"."等字符

      var path = require("path");
      path.normalize("/foo/bar//baz/asdf/..");
      // 处理后
      "/foo/bar/baz/asdf"
    
  • path.join([path1][, path2][, ...]) 连接路径

    path.join()方法可以连接任意多个路径字符串。要连接的多个路径可做为参数传入。path.join()方法在接边路径的同时也会对路径进行规范化。例如:

      var path = require("path");
      //合法的字符串连接
      path.join("/foo", "bar", "baz/asdf", "..")
      // 连接后
      "/foo/bar/baz/asdf"
    
      //不合法的字符串将抛出异常
      path.join("foo", {}, "bar")
      // 抛出的异常
      TypeError: Arguments to path.join must be strings"
    
  • path.resolve([from ...], to) 路径解析 path.resolve()方法可以将多个路径解析为一个规范化的绝对路径。其处理方式类似于对这些路径逐一进行cd操作,与cd操作不同的是,这引起路径可以是文件,并且可不必实际存在(resolve()方法不会利用底层的文件系统判断路径是否存在,而只是进行路径字符串操作)。例如:

      path.resolve("foo/bar", "/tmp/file/", "..", "a/../subfile")
    

    其处理方式类型于

      cd foo/bar
      cd /tmp/file/
      cd ..
      cd a/../subfile
      pwd
    

    如果解析的不是绝对路径,path.resolve()会将当前工作目录加到解析结果的前面。例如:

      path.resolve("/foo/bar", "./baz")
      // 输出结果为
      "/foo/bar/baz"
    
      path.resolve("/foo/bar", "/tmp/file/")
      // 输出结果为
      "/tmp/file"
    
      path.resolve("wwwroot", "static_files/png/", "../gif/image.gif")
      // 当前的工作路径是 /home/ivan/test,则输出结果为
      "/home/ivan/test/wwwroot/static_files/gif/image.gif"
    
  • path.relative(from, to) 查找两个绝对路径的相对关系 path.relative()方法可以找出一个绝对路径到另一个绝对路径的相对关系。例如:

      var path = require("path");
      path.relative("/Users/ivan/test/app/demo", "/Users/ivan/test/lib");
      // 结果
      "../../lib"
    
  • path.dirname(p) path.basename(p[, ext]) path.extname(p) 提取路径的组成部分

    path.dirname()方法可以提取出一个文件路径中的目录的部分。

    path.basename()方法可以提取出一个文件路径中的文件的部分。

    path.extname()方法可以提取文件的扩展名。例如:

var path = require("path");
path.dirname("/Users/ivan/demo/path.js")
// 结果
"/Users/ivan/demo"

path.basename("/Users/ivan/demo/path.js")
// 结果
"path.js"

path.extname("/Users/ivan/demo/path.js")
// 结果
".js"

path.basename()方法还可以指定第二个参数:文件的扩展名,指定后可以提取文件名。指定扩展名不合法时将返回文件全名。例如:

var path = require("path");

path.basename("/Users/ivan/demo/path.js", ".js")
// 结果
"path"

path.basename("/Users/ivan/demo/path.js", ".html")
// 结果
"path.js"

在早期的Node.js版本中path模块还有个path.exists()方法,用于判断文件是否存在,但已被fs模块中的fs.exists()代替。

以上。

阅读全文 »

ivan 发布于 07月28, 2016

Linux发邮件的方式及乱码问题

Linux发邮件

  • python脚本
  • shell脚本

之前一直使用python脚本来发送邮件,后来发现直接使用sendmail服务来发送邮件更方便一些,所以本文就说一下使用mail来发送邮件。

1 shell作为编辑器,编辑完成后ctrl+d结束

mail -s test qh_test@126.com

2 利用管道发送邮件

echo "mail content" | mail -s "mail title" qh_test@126.com

3 以file的内容为邮件内容发信

mail -s "mail title" qh_test@126.com < file

4 以file的内容为邮件内容向多个用户发信

mail -s "mail title" -c qh_test@126.com qh_test1@126.com < file

问题:

使用第二种发式发送邮件时,本地中文不会出现乱码,但是部署到服务端就会出现乱码,标题稳定出现乱码,内容随机出现乱码。

解决:

1 解决标题乱码

利用base64编码标题内容,例如,如果UTF-8编码的字符串标题进行base64编码后的内容为5qCH6aKY,则邮件标题为:

Subject:=?UTF-8?B?5qCH6aKY?=

2 解决内容乱码

解决内容乱码比较简单,首先内容使用UTF-8编码,然后再修改邮件为Content-type为:

Content-Type:text/html;charset=UTF-8

基于此,那么在nodejs代码中发送邮件就可以这样写:

var title = new Buffer("【ONEBOX】报警");
var mail_title = title.toString("base64");
var mail_title = "=?UTF-8?B?"+mail_title+"?=";
var mail_cont = "这里是发送邮件内容";
var mailList = "qh_test@126.com qh_test1@126.com";
var exec = require("child_process").exec;
exec(`echo "${mail_cont}" | mail -s "$(echo -e "${mail_title}\nContent-Type: text/html")" ${mailList}`);

以上。

阅读全文 »

admin 发布于 07月13, 2016

post/get请求小结(嗯,就是上一篇文章的小结)

问题

使用casperjs发送post请求时,一直无法正确请求。 问题原因:

  1. 传递data格式有误。
  2. 传递data格式无误时,没有加添加Content-Type参数。
  3. 之前关于提交表单有个误区,以为若action中包含参数,并且input中需要传递参数,两者不能同时存在- -.(底部验证中有解疑)

所以,post请求传递的data内容若需要为Json格式,但是若发送的不是单纯的key+value形式,那么需要添加Content-Type参数。以下是正确请求的代码。

casper.thenOpen("http://westpsk.com/api/v2?token=***token***=page&operation=update&ids=3701347013",{
    method: "POST",
    data : {
            "data" : {
                "description": "description test",
                "codes": "<html>test codes</html>"
            },
            "control" : {
                "lock" : 1,
                "version" : 0
            },
            "ext" : {
            }
        },
    headers: {
        "Accept":"application/json",
        "Content-Type":"application/json"
    }
},function(response){
    if(response.status == 200){
        this.echo("update success");
        var json_string = JSON.parse(this.page.plainText);
        // this.echo(json_string.data.codes);
        require("utils").dump(this.page.content);
    }
});

关键点

  1. 请求url中带有参数,并且需要传递body数据。
  2. 传递的数据不是单纯的key+value的json格式,需要设置'Content-Type':'application/json',否则无法正常传递。

疑惑点

现象

发送form表单时候会出现请求参数带不进去的情况。

  • method为get时,q=11不能传过去,input里的表单数据可以取到。
  • method为post,q=11可以传过去,但是input里的表单数据就取不到了。
<form action="http://so.com?q=11" method="get" target="_blank">
    <input name="tab" value="batch">
    <input name="sina-fr" type="hidden" value="bd">
</form>

对于get方式,服务器端用Request.QueryString获取变量的值,浏览器会将表单数据封装为字符串,如name=Google&age=18&qq=123456,然后直接附在表单的 action URL 之后。这两者之间用问号(?)进行分隔。如果GET请求的表单action属性中已经包含参数,浏览器会直接将其过滤掉,再附加form表单数据。

对于post方式,服务器端用Request.Form获取提交的数据,会把发送的数据放置在http包中,form的action属性就是提交数据的url地址。所以它会按照action指定的url进行提交数据,包含url后面跟着的参数和参数值。

因此,GET请求方式的表单的action属性中不能附带任何参数,如果需要附加额外的参数,可以采用如下方式:

  1. 采用POST请求方式,在form中增加属性method="post"即可。
  2. 如果仍然想使用GET请求方式,可以在form表单中添加相应的隐藏文本域,例如:

<input name="method" type="hidden" value="queryUser">

验证:

1.get请求

<div class='form'>
    <form action="post?a=1" method="get" target="_blank">
        <input type="text" name="name" value="ivan">
        <input type="text" name="pwd" value="fe">
        <button class="sub_btn">查询</button>
    </form>
</div>
async postAction(){
    let name = this.get("name");
    let pwd = this.get("pwd");
    this.assign({
        name: name,
        pwd: pwd
    });
    return this.display();
}

结果:

即:get请求时,action中a=1这个参数被丢弃掉了,可以得到input的内容。

2.post请求

<div class='form'>
    <form action="post?a=1" method="post" target="_blank">
        <input type="text" name="name" value="ivan">
        <input type="text" name="pwd" value="fe">
        <button class="sub_btn">查询</button>
    </form>
</div>
async postAction(){
    let name = this.post("name");
    let pwd = this.post("pwd");
    this.assign({
        name: name,
        pwd: pwd
    });
    return this.display();
}

结果:

即:post请求时,action中a=1这个参数可以取到,input的内容也可以获取到。

3.前端使用post请求,后端处理时使用get请求

<div class='form'>
    <form action="post?a=1" method="post" target="_blank">
        <input type="text" name="name" value="ivan">
        <input type="text" name="pwd" value="fe">
        <button class="sub_btn">查询</button>
    </form>
</div>
async postAction(){
    let name = this.get("name");
    let pwd = this.get("pwd");
    this.assign({
        name: name,
        pwd: pwd
    });
    return this.display();
}

即:前端使用post请求,而服务端使用get请求的方式是获取不到input中的内容的,只能拿到action里面的url的内容。(疑问解决)

总结

  1. 通过form表单提交和直接使用nodejs提交性质一样。 所以通过post请求,可以获取到url和data参数,之前之所以获取不到,是因为前后端处理不一致导致的。
  2. 通过post请求的话,若传递的数据格式不是单纯的key+value的形式,那么最好加入'Content-Type': 'application/json'

阅读全文 »

admin 发布于 07月13, 2016

casperjs发送post/get请求,form表单提交的疑惑&原因

casperjs发送post请求

官网接口

To POST some data with utf-8 encoding:

casper.open("http://some.testserver.com/post.php", {
       method: "post",
       headers: {
           "Content-Type": "application/json; charset=utf-8"
       },
       encoding: "utf8", // not enforced by default
       data: {
            "table_flip": "(╯°□°)╯︵ ┻━┻ ",
       }
});

带cookie

/*带cookie发送请求*/
var casper = require("casper").create();
casper.start();

/*更新代码*/
phantom.cookiesEnabled = true;
casper.then(function(){
    phantom.addCookie({
        "name": "thinkjs",
        "value": "******",
        "domain": "westpsk.com"
    });
    casper.thenOpen("http://westpsk.com/admin/api/page",{
        method: "POST",
        data: {
            "title": "description test",
            "pathname": "casperjs_test",
            "is_public": "1",
            "status": "3",
            "type": "1",
            "allow_comment": "1",
            "markdown_content": "hello, it"s the content "
        }
    },function(response){
        if(response.status == 200){
            this.echo("update success");
            var json_string = JSON.parse(this.page.plainText);
            // this.echo(json_string.data.codes);
            require("utils").dump(this.page.content);
        }
    });
});

post请求传递的data内容若需要为Json格式,但是发送的时候不是单纯的key+value形式,那么需要添加Content-Type参数。(thx@minmin排查问题)

casper.thenOpen("http://westpsk.com/api/v2?token=***token***=page&operation=update&ids=3701347013",{
    method: "POST",
    data : {
            "data" : {
                "description": "description test",
                "codes": "<html>test codes</html>"
            },
            "control" : {
                "lock" : 1,
                "version" : 0
            },
            "ext" : {
            }
        },
    headers: {
        "Accept":"application/json",
        "Content-Type":"application/json"
    }
},function(response){
    if(response.status == 200){
        this.echo("update success");
        var json_string = JSON.parse(this.page.plainText);
        // this.echo(json_string.data.codes);
        require("utils").dump(this.page.content);
    }
});

疑惑点

现象

发送form表单时候会出现请求参数带不进去的情况。

  • method为get时,q=11不能传过去,input里的表单数据可以取到。
  • method为post,q=11可以传过去,但是input里的表单数据就取不到了。
<form action="http://so.com?q=11" method="get" target="_blank">
    <input name="tab" value="batch">
    <input name="sina-fr" type="hidden" value="bd">
</form>

经查询发现,浏览器会将表单数据封装为字符串,如name=Google&age=18&qq=123456,然后直接附在表单的 action URL 之后。这两者之间用问号(?)进行分隔。如果GET请求的表单action属性中已经包含参数,浏览器会直接将其过滤掉,再附加form表单数据。

而使用post请求,无法传递url和input内容,可能是接口请求的服务端没有做相应的处理。 (疑问)

对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。Request从几个集合取数据是有顺序的,从前到后的顺序依次是 QueryString,Form,最后是ServerVariables。Request对象按照这样的顺序依次搜索这几个集合中的变量,如果有符合的就中止,后面的就不管了。

因此,GET请求方式的表单的action属性中不能附带任何参数,如果需要附加额外的参数,可以采用如下方式:

  1. 采用POST请求方式,在form中增加属性method="post"即可。
  2. 如果仍然想使用GET请求方式,可以在form表单中添加相应的隐藏文本域,例如:

<input name="method" type="hidden" value="queryUser">

页面通过表单(form)向服务器提交数据的时候有两种形式,一个是POST,另一个是GET。两种的一个区别是GET会直接把数据附加在url的后面,而POST发送的数据放置在http包中。form的action属性就是提交数据的url地址,method属性可以指定是GET或POST。

需要注意的是如果采用GET方式,那么action url中参数都会被丢弃,提交时候只会把form中的数据拼接在url向服务器提交;但是POST的方式则不会这样,它会按照action指定的url进行提交数据,包含url后面跟着的参数和参数值。

问题:

form表单发送请求时,url中带有参数,body中也包含需要传输的参数,那么可以正常传输么?表单提交与单纯的post请求性质是不是一样。

像遇到的不一样的情况,是不是服务端限制了传输方式,服务端获取的时候只验证了get方法,没有验证post方法,导致出现只能取到url中的参数,不能取到input中的参数?

验证:

1.get请求

<div class='form'>
    <form action="post?a=1" method="get" target="_blank">
        <input type="text" name="name" value="ivan">
        <input type="text" name="pwd" value="fe">
        <button class="sub_btn">查询</button>
    </form>
</div>
async postAction(){
    let name = this.get("name");
    let pwd = this.get("pwd");
    this.assign({
        name: name,
        pwd: pwd
    });
    return this.display();
}

结果:

即:get请求时,action中a=1这个参数被丢弃掉了,可以得到input的内容。

2.post请求

<div class='form'>
    <form action="post?a=1" method="post" target="_blank">
        <input type="text" name="name" value="ivan">
        <input type="text" name="pwd" value="fe">
        <button class="sub_btn">查询</button>
    </form>
</div>
async postAction(){
    let name = this.post("name");
    let pwd = this.post("pwd");
    this.assign({
        name: name,
        pwd: pwd
    });
    return this.display();
}

结果:

即:post请求时,action中a=1这个参数可以取到,input的内容也可以获取到。

3.前端使用post请求,后端处理时使用get请求

<div class='form'>
    <form action="post?a=1" method="post" target="_blank">
        <input type="text" name="name" value="ivan">
        <input type="text" name="pwd" value="fe">
        <button class="sub_btn">查询</button>
    </form>
</div>
async postAction(){
    let name = this.get("name");
    let pwd = this.get("pwd");
    this.assign({
        name: name,
        pwd: pwd
    });
    return this.display();
}

即:前端使用post请求,而服务端使用get请求的方式是获取不到input中的内容的,只能拿到action里面的url的内容。

解决

  1. 通过form表单提交和直接使用nodejs提交性质一样。 所以通过post请求,可以获取到url和data参数,之前之所以获取不到,可能是因为服务端没有对post请求做处理,导致只取到了url中参数,并没有获取到请求输入的参数。
  2. 通过post请求的话,若传递的数据格式不是单纯的key+value的形式,那么最好加入'Content-Type': 'application/json'

参考

阅读全文 »

admin 发布于 07月05, 2016

font-family的配置

概述

CCS属性font-family允许您通过给定一个有先后顺序的,由字体名或者字体族名组成的列表来为选定的元素设置字体。 属性的值用逗号隔开。浏览器会选择列表中第一个该计算机上有安装的字体,或者是通过 @font-face 指定的可以直接下载的字体。

语法

/* 一个字体名和一个通用的字体族名 */
font-family: Gill Sans Extrabold, sans-serif;
font-family: "Goudy Bookletter 1911", sans-serif;

/* 仅有通用的字体族名 */
font-family: sans-serif;
font-family: serif;
font-family: fantasy;
font-family: cursive;
font-family: monospace;

font-family: inherit

取值

一个字体族的名字。例如"Times" 和 "Helvetica" 都是字体族。字体族名可以包含空格,但包含空格时应该用引号。

通用字体族名是一种备选机制,用于在指定的字体不可用时给出较好的字体。通用字体族名都是关键字,所以不可以加引号。 在列表的末尾应该至少有一个通用字体族名。 以下是该属性可能的取值以及他们的定义。

有效的字体族名

字体族名或者是引号包括的字符串,或者是不含引号的一个或多个合法标识串构成的。这意味着在没有带引号的字体族名的开头是不能使用标点符号字符和数字字符的。

以下声明是正确的

font-family: Gill Sans Extrabold, sans-serif;
font-family: "Goudy Bookletter 1911", sans-serif;

以下声明是不正确的

font-family: Goudy Bookletter 1911, sans-serif;
font-family: Red/Black, sans-serif;
font-family: "Lucida" Grande, sans-serif;
font-family: Ahem!, sans-serif;
font-family: test@foo, sans-serif;
font-family: #POUND, sans-serif;
font-family: Hawaii 5-0, sans-serif;

标准语法

如何阅读 CSS 语法。
[ <family-name> | <generic-family> ]#
where 
<family-name> = <string> | <IDENT>+
<generic-family> = serif | sans-serif | cursive | fantasy | monospace

特殊情况,\5b8b\4f53的意思

\5b8b\4f53的意思是宋体

在IE9会遇见写的DIVCSS网页,文字有时不能垂直居中,究竟IE9 line-height设置文字不能垂直居中原因是什么? IE9不支持line-height原因:中文ie9不支持英文字体,相信大家在IE9看见自己使用line-height设置垂直居中文字不能垂直居中,这是与你设置字体有关,通常大家习惯设置font-family:Arial, Helvetica, sans-serif;

ie9中line-height失效解决方法: 只需设置好字体,添加个宋体即可解决 如CSS代码font-family:Arial, "宋体",Helvetica, sans-serif; 设置字体时候注意,还需设置大家都默认系统自带字体,如黑体,宋体。 在中文IE9中不认英文字体,所以IE9找不到设置中文字体,所以对导致字体上下垂直失效。 试了一下改成:font:12px/1.5 arial,“Sim sun”,helvetica,sans-serif;也可以OK 补充:按着font:12px/1.5 arial,“Sim sun”,helvetica,sans-serif;这个写法,有同学反馈mac下网页的字体由原来默认的细黑体和黑体,被宋体替换,这样浏览的效果很不爽。 解决文字:把"Sim sun" 改成 unicode格式即:\5b8b\4f53。 最后:font:12px/1.5 arial,\5b8b\4f53,helvetica,sans-serif; 整理几个常用字体的unicode表示

  • 新细明体 \65b0\7ec6\660e\4f53
  • 细明体 \7ec6\660e\4f53
  • 标楷体 \6807\6977\4f53
  • 黑体 \9ed1\4f53
  • 宋体 \5b8b\4f53
  • 新宋体 \65b0\5b8b\4f53
  • 仿宋 \4eff\5b8b
  • 楷体 \6977\4f53
  • 仿宋_gb2312 \4eff\5b8b_gb2312

note

不同的字体会有不同的展示。

baidu: font : 14px Arial,Helvetica,sans-serif

so: font-family : 'Source Han Sans','Microsoft YaHei','FZLanTingHei-R','Hei','arial','sans-serif'

  • 各个手机系统有自己的默认字体,且都不支持微软雅黑
  • 如无特殊需求,手机端无需定义中文字体,使用系统默认
  • 英文字体和数字字体可使用 Helvetica ,三种系统都支持

阅读全文 »