Blogdetails

用java的思想方式写javascript

月盾

javascript和java有相似之处也有很大区别,对于初学者来说很容易被名称迷惑,其实当初javascript就是借着java的顺风车进行推广的。

由于javascript是动态语言,java是静态语言,所以两者在编写方式上有很大区别,主要是因为javascript没有类的概念,在ES6标准发布之前要构造一个对象需要用new关键字实例化一个function或者直接使用对象字面量。不过ES6标准的发布,使得javascript也可像java一样声明类了。

在使用nodejs开发大型应用时需要到类的概念来封装一个复杂的逻辑,我们可以从现在开始逐步使用ES6开发,但是基于现有的支持环境,很多时候还得用ES5编写代码,那么这时候怎么来抽象一个类和实例化对象?

以Java的思想方式来编写JavaScript,首先是一个构造函数:

function Person(name, age){
	this.name = name;
	this.age = age;
}

这就像是Java的构造函数,可以new一个对象出来

var tom = new Person("Tom",12);

构造函数的用处是在创建对象的时候就初始化了属性的值,不用再单独赋值,不需要再像这样赋值:

var tom = new Person();

tom.name = "Tom";
tom.age = 13;

有了构造函数,还要有普通函数:

tom.sayHello = function(){

	console.log("my name is "+this.name);//my name is Tom

}

接下来是静态函数:静态方法就是由类名直接调用的的方法,不需要new一个对象

function Person(name, age){
	this.name = name;

	this.age = age;

}

Person.getAge = function(){

	console.log(this.age);

}

Person.age = 12;

Person.getAge();//类似于Java中的静态方法只能使用静态变量,所以此处也需要一个静态age

至于普通函数与静态函数有什么区别?区别就在于静态函数会一开始就加载到内存中,当然就比较占用内存了,普通函数是在new以后才被初始化,函数使用完就释放内存。

fullcalendar点击prve或者next按钮翻月触发事件调用

月盾
$('#calendar').fullCalendar({
    lang: "zh-cn",
    header: {
        left: 'prev, next, today',
        center: 'title',
        right: 'month'
    },
    height: 500,
    dayClick: function(date, jsEvent, view) {
        //点击空白日期调用
    },
    eventClick: function(calEvent, jsEvent, view) {
    //点击已有数据的日期调用
    },
    defaultDate: moment(),//默认日期
    events:function(start, end, callback){
    //点击prev上一月, next下一月等事件时调用
    }
});

系统开发中默认值的设置

月盾

多人协作开发过程中会遇到一些字段设置默认值的情况,但是这个默认值到底该由哪一阶段来设置?比如有三个阶段:前端或移动端,接口程序,数据库。说个具体场景,APP上有个医生需要显示挂号费,这个挂号费是由后台管理系统添加的,但是在添加医生这个过程不是一次性完成的,先是添加员工信息,角色为医生,这个挂号费是添加完成员工信息以后在医生管理里设置的,那么在完成添加员工后还没来得及设置挂号费医生就显示到了APP中,由于这个医生没有挂号费,就会导致用户误解或者APP程序报错。这时候问题来了,挂号费该有个默认值吧!但是这个默认值由谁来设置呢?尤其是程序上线以后出现问题大家都不想背这个黑锅,移动端问接口,你要传个默认值给我,接口对后台管理说你怎么没传个默认值给我?后台管理说,就不能在数据库设置吗,没有值我干嘛还要传?究竟该由谁来设置这个默认值,好像谁都可以,但是有很多字段要设置的时候就有很多工作量要做了,需要判断用户有没有填,没有填就设置默认值。一堆的if判断,很不明智的做法,而且也不能保证万无一失。

最后总结:默认值由数据库来设置,这是最简单的方法,可以为程序省去很多判断,而且数据库不为null的设置可以为索引字段带来好处,节省空间。

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 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属性值得变化,具体可打开浏览器控制台看属性值得变化情况,代码可直接在浏览器中查看源码

webuploader模态框按钮不起作用或每次打开都会变大

月盾

在bootstra模态框中放置webuploader上传控件,每次打开模态框按钮都会成倍放大,原因是每次打开模态框都会进行一次初始化,在原来按钮的基础上又加了一层样式,那么初始化一次应该可以吧。

https://qn-img.hopefly.top/anniubianda.png

修改后的确不会再放大了,可以又有新问题出现了,就是不能点击上传文件了。

上传实例初始化一次,先然按钮正常显示, var uploader = WebUploader.create({}), 再通过uploader提供的API重新添加一个按钮uploader.addButton({}),这样类似于将前一个按钮覆盖了。

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即可实现,并且编译速度更快,从几秒降到了毫秒。