浏览器

vue.js做的应用中点击搜索功能会改变URI

月盾

用vue.js做的后台管理系统,有一个列表搜索功能,正常登陆进去,直接点击搜索功能,页面就会刷新一遍,原因是url地址变化了

原本地址是:
http://www.mydomain/#!/index
点击搜索以后就变成了
http://www.mydomain/?#!/index

在#!前面自动加了?,导致页面刷新一遍,这样第一次搜索就没意义了.

经过初步排查后发现点击其他按钮不会改变URL地址,对比后发现搜索按钮的type=“submit”,可能是提交表单导致跳转了,那么将type改为button或者直接去掉试试,结果还是不行,干脆也改为标签(加了bootstrap按钮样式),结果好了。为什么将button type改为button不行呢,原因是在标签内标签type会被默认当做submit,(IE浏览器默认type=button)

vue.js中使用focus,blur事件

月盾

在线示例

使用focus,blur可对表单进行验证,除了这两个事件,还有一个watch属性可监听data属性值得变化,具体可打开浏览器控制台看属性值得变化情况,代码可直接在浏览器中查看源码

vue.js在chrome浏览器下输入汉字会带出拼音

月盾

本想写篇vue.js的教程的,但牵扯的知识点比较多,最近又没时间,就记录下过程中遇到问题吧。开发过程中用的360极速浏览器,也没什么问题,但是其他人测试的时候用的是chrome浏览器,输入汉字的时候会连拼音也带进去,比如输入的是“你好”,结果却成了“nihao你好”。

按理说360极速浏览器也用的是chrome内核,不应该出现这两种不同的情况,这个问题先不追究了。还是说说为什么vue.js的输入框会出现拼音的问题。我本以为是浏览器的差异造成这种现象,但是也不是所有输入框都会出现,那一定是程序的问题。

这是一种双向数据绑定常见写法,但是由于我的理解不够透彻,写成了这样:

我的理解是更新的时候要先显示数据,所以就在input里加了value来初始化数据,也是因为加了这个value导致输入汉字出现拼音,也与浏览器有点关系,就是输入的时候chrome浏览器会把输入的汉字拼音拼写也放进输入框,那么数据模型就接收了输入,敲击空格键的时候又输进了汉字,所以就都带进来了。但其实只需要v-model就能实现数据的接收和输出。

js prototype的理解【转】

月盾

prototype属性可算是JavaScript与其他面向对象语言的一大不同之处。 prototype就是“一个给类的对象添加方法的方法”,使用prototype属性,可以给类动态地添加方法,以便在JavaScript中实现“ 继承”的效果。

具体来说,prototype 是在 IE 4 及其以后版本引入的一个针对于某一类的对象的方法,当你用prototype编写一个类后,如果new一个新的对象,浏览器会自动把prototype中 的内容替你附加在对象上。这样,通过利用prototype就可以在JavaScript中实现成员函数的定义,甚至是“继承”的效果。

对于javascript本身而言是基于对象的,任何元素都可以看成对象。然而类型和对象是不同的,而我们所讲的prototype属性即是基于类型的一 种属性。对于prototype的基本使用就如对象的创建及属性赋值一样的简单。直接通过赋值操作即可完成属性的创建。


/**
 * 
关于prototype,
理解这个很有必要

可以在类型上使用proptotype来为类型添加行为。这些行为只能在类型的实例上体现。

JS中允许的类型有Array,
Boolean,
Date,
Enumerator,
Error,
Function,
Number,
Object,
RegExp,
String

以后这样分,没有实例化的类称为类型,实例化的类称为对象实例简称实例

 */
Object.prototype.name = "zhangsan";

Object.prototype.nihao = function () {

    alert("i can method name is " + this.name);

}

var obj = new Object();

obj.nihao();

alert(obj.name);



// 在实例上不能使用prototype,否则会发生编译错误

obj.prototype.sex = "男"; //error,无法给一个实例prototype
var o = {

    name: "zhangsan"

}

o.prototype.age = 30; //error,无法给一个实例prototype
//可以为类型定义“静态”的属性和方法,直接在类型上调用即可
alert(Object.name);

Object.nihao();

//实例不能调用类型的静态属性或方法,否则发生对象未定义的错误。
Object.class = "三年二班"; //类静态属性
var ob = new Object();

alert(ob.class); //error 实例不能调用类型的静态属性和方法
//可以在外部使用prototype为自定义的类型添加属性和方法。
function Mytest() {

    this.name = "zhangsan";

    this.age = 20;

}

Mytest.prototype.hello = function () {

    alert(this.name);

}

var m = new Mytest();

m.hello();

//在外部不能通过prototype改变自定义类型的属性或方法。
//该例子可以看到:调用的属性和方法仍是最初定义的结果。
Mytest.prototype.name = "lisi";

var mm = new Mytest();

alert(mm.name);

//可以在对象实例上改变或增加属性。(这个是肯定的)
//也可以在对象上改变或增加方法。(和普遍的面向对象的概念不同)
mm.name2 = "lisi";

mm.hello = function () {

    alert(this.name2);

}

//mm.hello();
//继承,这个例子说明了一个类型如何从另一个类型继承。
function Mytest2() { }

Mytest2.prototype = new Mytest;

var m2 = new Mytest2();

alert(m2.name);

//这个例子说明了子类如何重写父类的属性或方法。
Mytest2.prototype.name = "wangwu";

Mytest2.prototype.hello = function () {

    alert('i can mytest2 extend Mytest save method hello');

}

var m3 = new Mytest2();

m3.hello();

//子类中的name属性值不会被父类覆盖
function Mytest3() {

    this.name = "子类中的name属性值不会被父类覆盖";

    this.age = 20;

}

Mytest3.prototype = new Mytest();

var m4 = new Mytest3();

alert(m4.name);

    Object.prototype.name = "zhangsan";

    Object.prototype.nihao = function(){

        alert("i can method name is "+this.name);

    }

    var obj = new Object();

    obj.nihao();

    alert(obj.name);



    / / 在实例上不能使用prototype否则会发生编译错误

obj.prototype.sex = "男"; //error,无法给一个实例prototype
var o = {

    name: "zhangsan"

}

o.prototype.age = 30; //error,无法给一个实例prototype
//可以为类型定义“静态”的属性和方法,直接在类型上调用即可
alert(Object.name);

Object.nihao();

//实例不能调用类型的静态属性或方法,否则发生对象未定义的错误。
Object.class = "三年二班"; //类静态属性
var ob = new Object();

alert(ob.class); //error 实例不能调用类型的静态属性和方法
//可以在外部使用prototype为自定义的类型添加属性和方法。
function Mytest() {

    this.name = "zhangsan";

    this.age = 20;

}

Mytest.prototype.hello = function() {

    alert(this.name);

}

var m = new Mytest();

m.hello();

//在外部不能通过prototype改变自定义类型的属性或方法。
//该例子可以看到:调用的属性和方法仍是最初定义的结果。
Mytest.prototype.name = "lisi";

var mm = new Mytest();

alert(mm.name);

//可以在对象实例上改变或增加属性。(这个是肯定的)
//也可以在对象上改变或增加方法。(和普遍的面向对象的概念不同)
mm.name2 = "lisi";

mm.hello = function() {

    alert(this.name2);

}

//mm.hello();
//继承,这个例子说明了一个类型如何从另一个类型继承。
function Mytest2() {}

Mytest2.prototype = new Mytest;

var m2 = new Mytest2();

alert(m2.name);

//这个例子说明了子类如何重写父类的属性或方法。
Mytest2.prototype.name = "wangwu";

Mytest2.prototype.hello = function() {

    alert('i can mytest2 extend Mytest save method hello');

}

var m3 = new Mytest2();

m3.hello();

//子类中的name属性值不会被父类覆盖
function Mytest3() {

    this.name = "子类中的name属性值不会被父类覆盖";

    this.age = 20;

}

Mytest3.prototype = new Mytest();

var m4 = new Mytest3();

alert(m4.name);

来源:http://my.oschina.net/tongjh/blog/265209

检测网站中未使用的css样式

月盾

网站的css样式文件在多次修改后会有很多样式废弃不再使用,使得维护起来困难,还可能出现重名样式,后面的覆盖掉前面的效果,所以有必要清除掉不再使用的样式。可以使用的工具很多,不过在使用了Dust-Me Selectors觉得足够了。

https://addons.mozilla.org/en-US/firefox/addon/dust-me-selectors/

打开上面网址安装

直接点击这个小扫把会检测当前页面没有使用的样式,不过这样的结果还不是我们想要的,因为当前页面没有使用不代表其他页面也没有使用。我们更需要的是找出整个网站中未使用的样式。

选择第一项“Spider Sitemap”,就像是百度蜘蛛爬取整个网站数据一样。

输入网址,本地网址和网络地址都可以检测,点击“Start”后很快就有结果了,如果页面较多会费时些。

可以看到有橘黄色部分就是没有使用的样式,但是这也不能完全代表就是没有使用过,上面三个未使用的样式是我对于博客内容的图片和引用块使用的样式,因为本地的测试内容中的确没有使用这三个样式,但是线上的网站却使用了,遇到这种情况就需要仔细甄别了。

再看一下扫描的页面日志

基本的页面都有扫描过了。此时可以手动删除掉没有使用的样式,这个插件对于简单的网站够用了,但是大型网站就不准确了,当然有些其他工具还可以导出检测后的结果。有必要的可以去下载。

一次简单的前端页面优化

月盾

公司之前的产品管理对于小编们的使用情况及其糟糕,每次打开一个页面都要等待好久,这也是由于时间紧张,开始做的时候就只管进度没有时间优化。我大概看了下,光是登录页和一个空白首页就有78个请求,1.1M的数据。其他功能页面不少于这个数,这是因为所有页面共用了一个头文件,而这个头文件把所有有用没有的css文件和js文件都加载进来了,所以这次做的新后台管理系统绝不能这么做了。

前端性能优化

首先,css按需加载,当然有一些css是每个页面必须的就放到一个公共页面中include进来,对于一些新增的插件就在需要的时候添加到对应的页面。

其次,js的加载方式也进行特别优化,一种方式是把js放在body结束标签之前,可以避免js的加载阻塞页面渲染,还有可以使用异步加载方式 defer是针对IE浏览器的,async是其他非IE内核浏览器异步加载属性。但是,我还是使用了requirejs来加载js,一方面是为了页面加载更快,另一方面是可以做到js模块化。

前端性能优化

初步结果显示,所有页面加载速度平均在0.5秒,有些页面几乎看不出来重新加载过程,瞬间完成。优化也算是有一定的效果了。其中要说一下requirejs的一些优缺点,requirejs优点是可以实现js异步加载和模块化开发,不过让我有点不适应的是在HTML页面中不能使用onclick=func这种方式的事件处理,会提示找不到函数,只能在页面加载完成后用jquery进行事件监听,一些动态加载的页面数据也需要在加载以后重新绑定事件。

2015-11-08日更新

自从使用了requirejs后,凡是做页面需要js的时候首先想到的就是requirejs,感觉入坑跳不出来,反而弄巧成拙了。requirejs本意是异步加载多个js文件以防止页面阻塞,在一个网站或项目中也尽量合并多个文件里的内容以减少网络请求,一次加载一个大的文件比多次加载多个小文件来的划算的多,还有,requirejs虽然有好处但是并不是任何时候都有,比如页面很简单,js内容也很少的时候就完全不该用它。最后有一个不得不说的缺点,在上面已经提过,就是事件绑定,因为不能使用onclick=func()这种方式调用函数,只能用$(function(){})这种方式绑定事件,那么在网络不好的情况下,有些文件加载缓慢,导致不能绑定事件,如果一个按钮是这种方式绑定的事件,结果就是非要等到页面加载完才能点击,很让人着急。

前端工具gulp的用途和使用方法

月盾

在接触前端开始就听说过grunt和gulp是很叼的前端构建工具,但不知道到底有多叼,只是听说可以自动编译less,sass为css,目前还没有使用less和sass,所以也就没有尝试使用grunt和gulp。但是作为一个技术爱好者还是经不住诱惑,照着网上的教程简单使用了一下,总算是知道有什么用处了,因为都说gulp比grunt更简单好用,就以gulp的使用方法为例来说明一下。

文件合并:关于文件合并很多人存在这样的疑惑,在前端开发中到底该把所有js和css写在一个文件里还是各个页面分开写,我的建议是开发的时候分开写,上线的时候合并为一个,这样的好处是对于浏览器来说,不同页面中相同的文件默认会请求一次缓存下来,其他页面请求相同文件时就直接从缓存中读取,减少文件的网络请求可以提高网页速度,所以文件合并的是很有必要的。

2.文件压缩:既然都合并了,何不再压缩一下呢

3.语法检查:这个功能一般会和下面第4条功能配合使用,当文件修改的时候检查是否有语法错误,并在命令行中输出错误信息。

4.监听文件变化:监听某个目录下文件是否修改,修改的话就执行特定的操作,比如上面几个操作。     以上4点是比较常用的功能,更多功能根据自己需要添加

var gulp = require('gulp');
var jshint = require('gulp-jshint');//语法检查
var concat = require('gulp-concat');//合并文件
var uglify = require('gulp-uglify');//压缩代码
var rename = require('gulp-rename');//重命名
 
// 语法检查
gulp.task('jshint', function () {
return gulp.src('public/javascripts/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
 
// 合并文件之后压缩代码
gulp.task('minify', function (){
return gulp.src('public/javascripts/*.js')
.pipe(concat('all.js'))
.pipe(gulp.dest('public/javascripts/dist'))
.pipe(uglify())
.pipe(rename('all.min.js'))
.pipe(gulp.dest('public/javascripts/dist'));
});
 
// 监视文件的变化
gulp.task('watch', function () {
gulp.watch('public/javascripts/*.js', ['jshint', 'minify']);
});
 
// 注册缺省任务
gulp.task('default', ['jshint', 'minify', 'watch']);
// gulp.task('default', ['jshint', 'minify']);

目录结构:

让你的Node.js应用跑得更快的10个技巧

月盾

Node.js 受益于它的事件驱动和异步的特征,所以已经很快了。但是,在现代网络中只是快是不行的。如果你打算用 Node.js 开发你的下一个Web应用的话,那么你就应该无所不用,让你的应用更快,异常的快。本文将介绍10条经过检验得知可大大提高Node速度的应用技巧。废话不多说,让我们逐条来看看。

**1.**并行

创建 Web 应用的时候,你可能要多次调用内部 API 来获取各种数据。比如说,假设在 Dashboard 页面上,你要执行下面这几个调用:

  • 用户信息 -getUserProfile().
  • 当前活动 -getRecentActivity().
  • 订阅内容 -getSubscriptions().
  • 通知内容 -getNotifications().

为了拿到这些信息,你应该会为每个方法创建独立的中间件,然后将它们链接到 Dashboard 路由上。不过问题是,这些方法的执行是线性的,上一个没结束之前下一个不会开始。可行解决案是并行调用它们。

如你所知由于异步性,Node.js 非常擅长并行调用多个方法。我们不能暴殄天物。我上面提到的那些方法没有依赖性,所以我们可以并行执行它们。这样我们可以削减中间件数量,大幅提高速度。

我们可以用 async.js 来处理并行,它是一个专门用来调教 JavaScript 异步的 Node 模块。下面代码演示怎样用 async.js 并行调用多个方法的:

如果你想更深入了解 async.js ,请移步它的 GitHub 页面。

2. 异步

根据设计 Node.js 是单线程的。基于这点,同步代码会堵塞整个应用。比如说,多数的文件系统 API 都有它们的同步版本。下面代码演示了文件读取的同步和异步两种操作:

不过要是你执行那种长时间的阻塞操作,主线程就会被阻塞到这些操作完成为止。这大大降低你应用的性能。所以,最好确保你的代码里用的都是异步版本 API,最起码你应该在性能节点异步。而且,你在选用第三方模块的时候也要很小心。因为当你想方设法把同步操作从你代码中剔除之后,一个外部库的同步调用会让你前功尽弃,降低你的应用性能。

3. 缓存

如果你用到一些不经常变化的数据,你应该把它们缓存起来,改善性能。比如说,下面的代码是获取最新帖子并显示的例子:

如果你不经常发贴的话,你可以把帖子列表缓存起来,然后一段时间之后再把它们清理掉。比如,我们可以用 Redis 模块来达到这个目的。当然,你必须在你的服务器上装 Redis。然后你可以用叫做 node_redis 的客户端来保存键/值对。下面的例子演示我们怎么缓存帖子:

看到了吧,我们首先检查 Redis 缓存,看看是否有帖子。如果有,我们从缓存中拿这些帖子列表。否则我们就检索数据库内容,然后把结果缓存。此外,一定时间之后,我们可以清理 Redis 缓存,这样就可以更新内容了。

4. gzip 压缩

开启 gzip 压缩对你的 Web 应用会产生巨大影响。当一个 gzip 压缩浏览器请求某些资源的时候,服务器会在响应返回给浏览器之前进行压缩。如果你不用 gzip 压缩你的静态资源,浏览器拿到它们可能会花费更长时间。