前端

vue.js click点击事件获取当前元素对象

月盾

Vue.js可以传递$event对象

<body id="app">
  <ul>
	<li v-on:click="say('hello!', $event)">点击当前行文本</li>
	<li>li2</li>
	<li>li3</li>
  </ul>
  <script>
   new Vue({
	   el: '#app',
	   data: {
		message: 'Hello Vue.js!'
	   },
	   methods: {
		say: function(msg, event) {
		   //获取点击对象
		   var el = event.currentTarget;
		   alert("当前对象的内容:"+el.innerHTML);
		}
	}
   })
  </script>
 </body>

函数调用处传递$event

v-on:click="say('hello!', $event)"

函数中获取到的event.currentTarget对象就是当前元素

在线示例

请查看HTML页面示例源码

vue.js对表单值初始化

月盾

新建表单有些input输入框需要默认值,比如性别需要一个男或女默认值。再比如一个日期选择框需要默认今天。如果按照HTML的方式设置不会起作用

<input type="radio" name="gender" value="0" checked="checked" v-model="gender">男
<input type="radio" name="gender" value="1" v-model="gender">女
<input type="date" value="2016-01-06" v-model="date">

在vue.js页面中上面这种设置方式是不会起作用的,性别不会选中,日期也不会有值。解决办法是对v-model属性设值,在初始化时给gender=0,那么默认会选中性别男,给date=“2016-01-06"日期控件也有值。

vue.js中使用focus,blur事件

月盾

在线示例

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

vue.js开发gulp监听文件变化自动编译

月盾

直接看代码:

var gulp = require('gulp')
var webpack = require("gulp-webpack");
var webpackConfig = require("./webpack.config.js");
// gulp.task("webpack", function(callback) {
//   var myConfig = Object.create(webpackConfig);
//   webpack(myConfig, function(err, stats) {
//           console.log(">>>>>err:"+JSON.stringify(err))
//           console.log(">>>>>stats:"+stats)
//         if(err) throw new Error("webpack", err);
//         callback();
//     });
// });

/**
 * 编译时有错误提示
 */
gulp.task("webpack", function(){
    return gulp.src("./app.js")
    .pipe(webpack(Object.create(webpackConfig)))
    .pipe(gulp.dest("./dist/"))
});

gulp.watch('./views/*', ['webpack']);

webpack.config.js配置

var webpack = require("webpack");
module.exports = {
    entry: //"./app.js",
        {
            app:"./app.js"
            // vendor: ["./javascripts/test"]
        },
    output: {
        path: __dirname + "/dist/",
        filename: "bundle.js"
    },
    module: {
        loaders: [
            {
                test: /\.scss$/,
                loaders: ['style', 'css', 'sass']
            },
            //{ test: /\.css$/, loader: "style!css" },
            { test: /\.vue$/, loader: 'vue-loader'},
            { test: /\.(jpg|png|gif)$/, loader: "file-loader?name=images/[hash].[ext]"}
        ]
    },
    // devtool: '#source-map',
    // plugins:[
    //     new webpack.optimize.CommonsChunkPlugin({
    //         name: "vendor",//和上面配置的入口对应
    //         filename: "common.js"//导出的文件的名称
    //     })
    // ]
};

不得不承认自己还是有很多不知道的配置,刚发表完本文就得知一种更高效的方式:直接用webpack自带的监听参数:>webpack -w即可实现,并且编译速度更快,从几秒降到了毫秒。

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

js控制优酷视频播放暂停

月盾

js控制优酷视频播放暂停

<!DOCTYPE html>  
<html>  
    <head>  
        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">  
        <title>js控制优酷视频播放</title>  
        <script src="http://player.youku.com/jsapi"></script>  
        <script>  
            player = new YKU.Player("youkuplayer",{  
                styleid: "0",  
                client_id: "d8781b239fdad45b",  
                vid: "XMjg1MTcyNDQ0",  
                autoplay: false,  
                show_related: true,  
                events:{  
                    onPlayEnd: function(){ /*your code*/ },  
                    onPlayStart: function(){ /*your code*/ },  
                    onPlayerReady: function(){ /*your code*/ }  
                }  
            });  
            function playVideo(){  
                try{  
                    player.playVideo();  
                } catch(err){  
                    alert("*"+err);  
                }  
  
            }  
            function pauseVideo(){  
                player.pauseVideo();  
  
            }  
            function seekTo(s){  
                player.seekTo(s);  
            }  
            function currentTime(){  
                return player.currentTime();  
            }  
        </script>  
    </head>  
    <body>  
        <div id="youkuplayer" style="width:100%;height:400px;"></div>  
        <br />  
        <input type="button" onclick="playVideo();" value="播放" style="height:30px;width:50px;">  
        <input type="button" onclick="pauseVideo();" value="暂停" style="height:30px;width:50px;">  
    </body>  
</html>

无插件实现动态瀑布流加载数据

月盾

以前在页面中动态加载帖子数据使用了waterfall.js插件,当初折腾了不少时间才搞定,这次又有一个页面需要动态加载数据,自然想到了waterfall插件,但是结果很不理想,waterfall的很多参数不管是什么用处,反正看着很头疼,最麻烦的是它会改变页面样式和布局,实在不想调整了,还是自己实现这个功能吧!

首先看下面代码:

var pageIndex = 2;

(function loadmore() {

    //绑定滚动事件  
    $(window).bind("scroll",  function() {

        if ($(this).scrollTop() + $(window).height() + 40 >= $(document).height() &amp;&amp; $(this).scrollTop() >= 40) {

            $(window).unbind("scroll"); //到底后先移除滚动事件  
            $.get("/portal/getTopic?pageIndex=" + pageIndex + "&amp;pageSize=3",  
            function(data) {

                $("#container").append(data);

                pageIndex++;

                loadmore(); //数据加载成功重新绑定滚动事件  
            },  
            "html");

        };

    });

})();

没错,就这么点,这已经是实现功能的最简单版本了。代码的基本流程是给页面绑定滚动事件,判断是否滚动到最底部,然后加载数据。但实际上并不是这么简单就能行的,有很多意外情况需要解决。

先来说明如何判断页面是否滚动到最底部,$(this).scrollTop()用来计算滚动条顶端距离窗口顶部的距离,整个滚动条高度大约等于整个页面高度。当滚动条滚动到最底部的时候,滚动条顶端距离窗口顶部并不是整个页面的高度,还需要加上当前窗口所占高度才是整个页面正真的高度。所以就是$(this).scrollTop() + $(window).height()=$(document).height(),但是我们为什么还要加40呢?因为一般滚动到底部加载并不是完全要滚动到最低端才加载,而是差不多已经到底的时候就要开始加载,既然是差不多到底那么$(this).scrollTop() + $(window).height()就是还不完全等于整个页面高度,因为还有40没有滚动,所以加上了才是整个页面高度。此时滚动到距离最底部还有40像素的时候,再滚动一点就会大于页面高度,就该加载数据了。代码中还有&amp;&amp; $(this).scrollTop() >= 40是为了监听有滚动发生,总不能在没有滚动事件发生时就加载。

已经能够监听到是否滚动到底部了,但是滚动事件是稍微滚动一点就能触发好多次,就会请求好多次数据,就算数据没有返回稍微滚动就会继续发送同样请求,所以在数据没有返回之前要把监听滚动移除掉,$(window).unbind("scroll");等数据添加到页面以后再重新绑定滚动事件。

一次简单的前端页面优化

月盾

公司之前的产品管理对于小编们的使用情况及其糟糕,每次打开一个页面都要等待好久,这也是由于时间紧张,开始做的时候就只管进度没有时间优化。我大概看了下,光是登录页和一个空白首页就有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(){})这种方式绑定事件,那么在网络不好的情况下,有些文件加载缓慢,导致不能绑定事件,如果一个按钮是这种方式绑定的事件,结果就是非要等到页面加载完才能点击,很让人着急。