MVC,MVP 和 MVVM 的差异对比

架构思想zkbhj 发表了文章 • 0 个评论 • 2609 次浏览 • 2016-09-20 16:36 • 来自相关话题

复杂的软件必须有清晰合理的架构,否则无法开发和维护。

MVC(Model-View-Controller)是最常见的软件架构之一,业界有着广泛应用。它本身很容易理解,但是要讲清楚,它与衍生的 MVP 和 MVVM 架构的区别就不容易了。
 
一、MVC
 
MVC模式的意思是,软件可以分成三个部分。






视图(View):用户界面。
控制器(Controller):业务逻辑
模型(Model):数据保存

各部分之间的通信方式如下。






View 传送指令到 Controller
Controller 完成业务逻辑后,要求 Model 改变状态
Model 将新的数据发送到 View,用户得到反馈

所有通信都是单向的。
 
 
二、互动模式
 
接受用户指令时,MVC 可以分成两种方式。一种是通过 View 接受指令,传递给 Controller。






另一种是直接通过controller接受指令。
 






三、实例:Backbone​
 
实际项目往往采用更灵活的方式,以 Backbone.js 为例。
 






1. 用户可以向 View 发送指令(DOM 事件),再由 View 直接要求 Model 改变状态。

2. 用户也可以直接向 Controller 发送指令(改变 URL 触发 hashChange 事件),再由 Controller 发送给 View。

3. Controller 非常薄,只起到路由的作用,而 View 非常厚,业务逻辑都部署在 View。所以,Backbone 索性取消了 Controller,只保留一个 Router(路由器) 。

 四、MVP
 
MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。






1. 各部分之间的通信,都是双向的。

2. View 与 Model 不发生联系,都通过 Presenter 传递。

3. View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。

 五、MVVM
 
MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。
 





 
唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。Angular 和 Ember 都采用这种模式。 查看全部
复杂的软件必须有清晰合理的架构,否则无法开发和维护。

MVC(Model-View-Controller)是最常见的软件架构之一,业界有着广泛应用。它本身很容易理解,但是要讲清楚,它与衍生的 MVP 和 MVVM 架构的区别就不容易了。
 
一、MVC
 
MVC模式的意思是,软件可以分成三个部分。

bg2015020104.png


视图(View):用户界面。
控制器(Controller):业务逻辑
模型(Model):数据保存


各部分之间的通信方式如下。

bg2015020105.png


View 传送指令到 Controller
Controller 完成业务逻辑后,要求 Model 改变状态
Model 将新的数据发送到 View,用户得到反馈


所有通信都是单向的。
 
 
二、互动模式
 
接受用户指令时,MVC 可以分成两种方式。一种是通过 View 接受指令,传递给 Controller。

bg2015020106.png


另一种是直接通过controller接受指令。
 

bg2015020107.png


三、实例:Backbone​
 
实际项目往往采用更灵活的方式,以 Backbone.js 为例。
 

bg2015020108.png


1. 用户可以向 View 发送指令(DOM 事件),再由 View 直接要求 Model 改变状态。

2. 用户也可以直接向 Controller 发送指令(改变 URL 触发 hashChange 事件),再由 Controller 发送给 View。

3. Controller 非常薄,只起到路由的作用,而 View 非常厚,业务逻辑都部署在 View。所以,Backbone 索性取消了 Controller,只保留一个 Router(路由器) 。


 四、MVP
 
MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。

bg2015020109.png


1. 各部分之间的通信,都是双向的。

2. View 与 Model 不发生联系,都通过 Presenter 传递。

3. View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。


 五、MVVM
 
MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。
 

bg2015020110.png

 
唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。Angular 和 Ember 都采用这种模式。

Redis为何选用6379作为默认端口号

常识zkbhj 发表了文章 • 0 个评论 • 2919 次浏览 • 2016-09-20 11:26 • 来自相关话题

6379在是手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字。MERZ长期以来被antirez及其朋友当作愚蠢的代名词。
 
原文引用

Today on Twitter I saw a tweet related to the ability to remember the Redis port number. There is a trick, the Redis port number, 6379, is MERZ at the phone keyboard. 

Is it a coincidence that it sounds not random enough? Actually not ;) I selected 6379 because of MERZ, and not the other way around. 

Everything started with Alessia Merz, an Italian Showgirl (make sure to check some (not safe for work) photo as well). 

I and my friends are used to create our own slang, that is evolving since... 20 or 25 years. Well one adjective that we use consistently since 10 years is "merz", but the meaning of the word changed so much in the course of the time. 

Initially it started because we were really delighted by the stupidity of the sentences that the showgirl was able to state in the italian TV. So we started using "MERZ" when something was... stupid. "Hey, that's merz!". And so forth. But then with some time the meaning shifted in something stupid as pointless, but with very technical value, or with an impressive amount of skills and patience and work involved, but still... stupid. 

For instance creating a 3D map of your hometown by sampling the points with a GPS and a broken car going around for the whole night, or analyzing tons of lottery data searching for biases, perfectly knowing that we'll never spend a single penny in a lottery ticket anyway, and so forth. "Merz" basically means... hack value, but is also referred to people not just things, people that act in a funny way just for hack value, or to be fun, and so forth. 

So when I had to pick a port number for Redis I had no troubles, whatever number MERZ was at the phone, it was the Redis port number. 查看全部
6379在是手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字。MERZ长期以来被antirez及其朋友当作愚蠢的代名词。
 
原文引用


Today on Twitter I saw a tweet related to the ability to remember the Redis port number. There is a trick, the Redis port number, 6379, is MERZ at the phone keyboard. 

Is it a coincidence that it sounds not random enough? Actually not ;) I selected 6379 because of MERZ, and not the other way around. 

Everything started with Alessia Merz, an Italian Showgirl (make sure to check some (not safe for work) photo as well). 

I and my friends are used to create our own slang, that is evolving since... 20 or 25 years. Well one adjective that we use consistently since 10 years is "merz", but the meaning of the word changed so much in the course of the time. 

Initially it started because we were really delighted by the stupidity of the sentences that the showgirl was able to state in the italian TV. So we started using "MERZ" when something was... stupid. "Hey, that's merz!". And so forth. But then with some time the meaning shifted in something stupid as pointless, but with very technical value, or with an impressive amount of skills and patience and work involved, but still... stupid. 

For instance creating a 3D map of your hometown by sampling the points with a GPS and a broken car going around for the whole night, or analyzing tons of lottery data searching for biases, perfectly knowing that we'll never spend a single penny in a lottery ticket anyway, and so forth. "Merz" basically means... hack value, but is also referred to people not just things, people that act in a funny way just for hack value, or to be fun, and so forth. 

So when I had to pick a port number for Redis I had no troubles, whatever number MERZ was at the phone, it was the Redis port number.


前端优秀代码片段

前端开发zkbhj 发表了文章 • 0 个评论 • 2971 次浏览 • 2016-09-19 15:38 • 来自相关话题

 //购物车控制显示
$("#head_car").hover(function(){
$(this).css("background", "#FBFEE9");
$(".head_car_text").css("color", "#ff6700");
$("#car_content").css({"width":"300px"}).animate({
height:"100px"
},400).finish();
},function(){
$(this).css("background", "#424242");
$(".head_car_text").css("color", "#b0b0b0");
$("#car_content").css({"width":"300px"}).animate({
height:"0px"
},400);
})
//导航栏控制显示
$(".menu_li").hover(function(){
$("#menu_content_bg").css("border","1px solid #D0D0D0");
$(this).css("color","#ff6700");
$("#"+$(this).attr("control")).show();
$("#menu_content_bg").height(230);
},function(){
$("#"+$(this).attr("control")).hide();
$(this).css("color"," #424242");
$("#menu_content_bg").height(0);
$("#menu_content_bg").css("border","0px solid #D0D0D0");
})
//搜索框失去和获取焦点border颜色改变
$("#find_input").focus(function(){
$("#find_wrap").css("border","1px solid #ff6700");
$("#find_but").css("border-left","1px solid #ff6700");
})
$("#find_input").blur(function(){
$("#find_wrap").css("border","1px solid #F0F0F0");
$("#find_but").css("border-left","1px solid #F0F0F0");
})
//搜索按钮的背景颜色改变
$("#find_but").hover(function(){
$(this).css({"background":"#ff6700",color:"#fff"});
},function(){
$(this).css({"background":"#fff",color:"#424242"});
})
//菜单栏的显示
$("#banner_menu_wrap").children().hover(function(){
$(this).css("background","#ff6700");
$(this).children(".banner_menu_content").css("border","1px solid #F0F0F0").show();
},function(){
$(this).css("background","none");
$(this).children(".banner_menu_content").css("border","0px solid #F0F0F0").hide();
}) 查看全部
 
//购物车控制显示
$("#head_car").hover(function(){
$(this).css("background", "#FBFEE9");
$(".head_car_text").css("color", "#ff6700");
$("#car_content").css({"width":"300px"}).animate({
height:"100px"
},400).finish();
},function(){
$(this).css("background", "#424242");
$(".head_car_text").css("color", "#b0b0b0");
$("#car_content").css({"width":"300px"}).animate({
height:"0px"
},400);
})

//导航栏控制显示
$(".menu_li").hover(function(){
$("#menu_content_bg").css("border","1px solid #D0D0D0");
$(this).css("color","#ff6700");
$("#"+$(this).attr("control")).show();
$("#menu_content_bg").height(230);
},function(){
$("#"+$(this).attr("control")).hide();
$(this).css("color"," #424242");
$("#menu_content_bg").height(0);
$("#menu_content_bg").css("border","0px solid #D0D0D0");
})

//搜索框失去和获取焦点border颜色改变
$("#find_input").focus(function(){
$("#find_wrap").css("border","1px solid #ff6700");
$("#find_but").css("border-left","1px solid #ff6700");
})
$("#find_input").blur(function(){
$("#find_wrap").css("border","1px solid #F0F0F0");
$("#find_but").css("border-left","1px solid #F0F0F0");
})

//搜索按钮的背景颜色改变
$("#find_but").hover(function(){
$(this).css({"background":"#ff6700",color:"#fff"});
},function(){
$(this).css({"background":"#fff",color:"#424242"});
})

//菜单栏的显示
$("#banner_menu_wrap").children().hover(function(){
$(this).css("background","#ff6700");
$(this).children(".banner_menu_content").css("border","1px solid #F0F0F0").show();
},function(){
$(this).css("background","none");
$(this).children(".banner_menu_content").css("border","0px solid #F0F0F0").hide();
})

jquery中ajax请求error函数和及其参数详细说明

前端开发zkbhj 发表了文章 • 0 个评论 • 1507 次浏览 • 2016-09-19 10:38 • 来自相关话题

使用jquery的ajax方法向服务器发送请求的时候,常常需要使用到error函数进行错误信息的处理,本文详细的说明了ajax中error函数和函数中各个参数的用法。

一般error函数返回的参数有三个: function(jqXHR jqXHR, String textStatus, String errorThrown)。常见调用代码如下:
$.ajax({
url: '/Home/AjaxGetData',
success: function (data) {
alert(data);
},
error: function (jqXHR, textStatus, errorThrown) {
/*错误信息处理*/
}
});这里对这三个参数做详细说明。
 
第一个参数 jqXHR jqXHR:这里的jqXHR是一个jqXHR对象,在Jquery1.4和1.4版本之前返回的是XMLHttpRequest对象,1.5版本以后则开始使用jqXHR对象,该对象是一个超集,就是该对象不仅包括XMLHttpRequest对象,还包含其他更多的详细属性和信息。

这里主要有4个属性:
readyState :当前状态,0-未初始化,1-正在载入,2-已经载入,3-数据进行交互,4-完成。status  :返回的HTTP状态码,比如常见的404,500等错误代码。statusText :对应状态码的错误信息,比如404错误信息是not found,500是Internal Server Error。responseText :服务器响应返回的文本信息
第二个参数 String textStatus:返回的是字符串类型,表示返回的状态,根据服务器不同的错误可能返回下面这些信息:"timeout"(超时), "error"(错误), "abort"(中止), "parsererror"(解析错误),还有可能返回空值。
 
第三个参数 String errorThrown:也是字符串类型,表示服务器抛出返回的错误信息,如果产生的是HTTP错误,那么返回的信息就是HTTP状态码对应的错误信息,比如404的Not Found,500错误的Internal Server Error。
 
示例代码:
 
$.ajax({
url: '/AJAX请求的URL',
success: function (data) {
alert(data);
},
error: function (jqXHR, textStatus, errorThrown) {
/*弹出jqXHR对象的信息*/
alert(jqXHR.responseText);
alert(jqXHR.status);
alert(jqXHR.readyState);
alert(jqXHR.statusText);
/*弹出其他两个参数的信息*/
alert(textStatus);
alert(errorThrown);
}
});
官方文档地址:http://api.jquery.com/jQuery.ajax/ 查看全部
使用jquery的ajax方法向服务器发送请求的时候,常常需要使用到error函数进行错误信息的处理,本文详细的说明了ajax中error函数和函数中各个参数的用法。

一般error函数返回的参数有三个: function(jqXHR jqXHR, String textStatus, String errorThrown)。常见调用代码如下:
$.ajax({
url: '/Home/AjaxGetData',
success: function (data) {
alert(data);
},
error: function (jqXHR, textStatus, errorThrown) {
/*错误信息处理*/
}
});
这里对这三个参数做详细说明。
 
第一个参数 jqXHR jqXHR:这里的jqXHR是一个jqXHR对象,在Jquery1.4和1.4版本之前返回的是XMLHttpRequest对象,1.5版本以后则开始使用jqXHR对象,该对象是一个超集,就是该对象不仅包括XMLHttpRequest对象,还包含其他更多的详细属性和信息。

这里主要有4个属性:
  • readyState :当前状态,0-未初始化,1-正在载入,2-已经载入,3-数据进行交互,4-完成。
  • status  :返回的HTTP状态码,比如常见的404,500等错误代码。
  • statusText :对应状态码的错误信息,比如404错误信息是not found,500是Internal Server Error。
  • responseText :服务器响应返回的文本信息

第二个参数 String textStatus:返回的是字符串类型,表示返回的状态,根据服务器不同的错误可能返回下面这些信息:"timeout"(超时), "error"(错误), "abort"(中止), "parsererror"(解析错误),还有可能返回空值。
 
第三个参数 String errorThrown:也是字符串类型,表示服务器抛出返回的错误信息,如果产生的是HTTP错误,那么返回的信息就是HTTP状态码对应的错误信息,比如404的Not Found,500错误的Internal Server Error。
 
示例代码:
 
$.ajax({
url: '/AJAX请求的URL',
success: function (data) {
alert(data);
},
error: function (jqXHR, textStatus, errorThrown) {
/*弹出jqXHR对象的信息*/
alert(jqXHR.responseText);
alert(jqXHR.status);
alert(jqXHR.readyState);
alert(jqXHR.statusText);
/*弹出其他两个参数的信息*/
alert(textStatus);
alert(errorThrown);
}
});

官方文档地址:http://api.jquery.com/jQuery.ajax/

如何用JS判断手机端还是PC端访问?

回复

前端开发zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 4777 次浏览 • 2016-09-18 17:39 • 来自相关话题

雪碧图

专业名词zkbhj 发表了文章 • 0 个评论 • 1332 次浏览 • 2016-09-14 11:01 • 来自相关话题

CSS Sprites技术被国内一些人称为CSS雪碧图,其实就是把网页中一些背景图片整合到一张图片文件中,再利用CSS的“background-image”,“background- repeat”,“background-position”的组合进行背景定位,background-position可以用数字精确的定位出背景图片的位置。

CSS 雪碧图技术不是什么新东西,在网页应用中已经有几年了,现在的网页开发在图标图片的应用上已经趋向于使用字体图标,这是一种比CSS雪碧图技术更优雅的图标应用方式。

在网站中的导航最常见最明显,一些地方的零碎小图标也多使用。
CSS知识点:background-image
backgorund-position

特点:

相对于当个小图标,它节省文件体积和服务请求次数。将所有零碎的网页背景图片整合到一起,这样做可以有效的减少http对图片的请求次数,而不需要加载多次加载零碎的背景图片,所以合理的利用好它可以有效的提高网页的加载速度。
一般情况下,你需要保存为PNG-24的文件格式。
可以设计出丰富多彩的颜色体表。

难点:

你需预先确定每个小图标的大小
注意小图标与小图标之间的距离
细心、耐心
PNG-24的图片格式:PNG-24可减少毛边。background-position 索引值 查看全部

CSS Sprites技术被国内一些人称为CSS雪碧图,其实就是把网页中一些背景图片整合到一张图片文件中,再利用CSS的“background-image”,“background- repeat”,“background-position”的组合进行背景定位,background-position可以用数字精确的定位出背景图片的位置。

CSS 雪碧图技术不是什么新东西,在网页应用中已经有几年了,现在的网页开发在图标图片的应用上已经趋向于使用字体图标,这是一种比CSS雪碧图技术更优雅的图标应用方式。

在网站中的导航最常见最明显,一些地方的零碎小图标也多使用。
CSS知识点:background-image
backgorund-position

特点:

相对于当个小图标,它节省文件体积和服务请求次数。将所有零碎的网页背景图片整合到一起,这样做可以有效的减少http对图片的请求次数,而不需要加载多次加载零碎的背景图片,所以合理的利用好它可以有效的提高网页的加载速度。
一般情况下,你需要保存为PNG-24的文件格式。
可以设计出丰富多彩的颜色体表。

难点:

你需预先确定每个小图标的大小
注意小图标与小图标之间的距离
细心、耐心
PNG-24的图片格式:PNG-24可减少毛边。background-position 索引值

JS如何判断接口返回值中是否存在某个字段?

回复

前端开发zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 6631 次浏览 • 2016-09-14 10:11 • 来自相关话题

怎么校验接口请求来源?

回复

PHPzkbhj 回复了问题 • 1 人关注 • 1 个回复 • 3751 次浏览 • 2016-09-09 18:35 • 来自相关话题

怎么校验接口请求来源?

回复

PHPzkbhj 发起了问题 • 1 人关注 • 0 个回复 • 4259 次浏览 • 2016-09-09 18:33 • 来自相关话题

Mysql查询时ORDER BY的一些使用技巧

数据库zkbhj 发表了文章 • 0 个评论 • 1381 次浏览 • 2016-09-09 15:34 • 来自相关话题

1. 只按日期排序,忽略年份> select date, description from table_name order by month(date),dayofmonth(date);
注意:单纯使用dayofyear来排序会导致错误,如2-29与非闰年的3-1日同等级

 
2. 排序点分式IP> select ip from table_name order by inet_aton(ip);
或者在设计表时就使用 int unsigned 来表示ip。


3. 将某列中特定值排在最前
例如想把表中lulu的名字排在最前显示,其他按字母排序> select name from table_name order by if(name='lulu',0,1),name ;
也可以把if的条件根据需要换成相应的语句。

 
4. 将某列内容按照用户自定义的顺序排序
例如想把表中的名字按lulu,xixi,baba,mama的非常规顺序排序输出:> select name from table_name order by field(name,'lulu','xixi','baba','mama');

 
5. 对枚举类型排序
枚举类型默认为数字排序,如果希望以字符串形式排序。> select name from table_name order by cast(name as char);
如果希望更改enum的排序默认顺序,可以alter tablealter table table_name modify name enum('lulu','xixi','mama','baba');


6. 按csv类型的字符串的某字串排序
例如某列m_str内容是形如abc-321-mno-jkl的形式,希望对第二列进行排序> select m_str from table_name
order by substring_index(substring_index(m_str,'-',2),'-',-1); 查看全部
1. 只按日期排序,忽略年份
> select date, description from table_name order by month(date),dayofmonth(date);

注意:单纯使用dayofyear来排序会导致错误,如2-29与非闰年的3-1日同等级

 
2. 排序点分式IP
> select ip from table_name order by inet_aton(ip);

或者在设计表时就使用 int unsigned 来表示ip。


3. 将某列中特定值排在最前
例如想把表中lulu的名字排在最前显示,其他按字母排序
> select name from table_name order by if(name='lulu',0,1),name ;

也可以把if的条件根据需要换成相应的语句。

 
4. 将某列内容按照用户自定义的顺序排序
例如想把表中的名字按lulu,xixi,baba,mama的非常规顺序排序输出:
> select name from table_name order by field(name,'lulu','xixi','baba','mama');


 
5. 对枚举类型排序
枚举类型默认为数字排序,如果希望以字符串形式排序。
> select name from table_name order by cast(name as char);

如果希望更改enum的排序默认顺序,可以alter table
alter table table_name modify name enum('lulu','xixi','mama','baba');



6. 按csv类型的字符串的某字串排序
例如某列m_str内容是形如abc-321-mno-jkl的形式,希望对第二列进行排序
> select m_str from table_name
order by substring_index(substring_index(m_str,'-',2),'-',-1);