javascript面向对象分层思维
js本身不是面向对象语言,在我们实际开发中其实很少用到面向对象思想,以前一直以为当要复用的时候才封装成对象,然而随着现在做的项目都后期测试阶段发现面向对象的作用不仅仅只是复用,可能你们会说面向对象还有继承,多态的概念,但在javascript里面多态的概念是不存在,而继承由于web页面的必须先下载js在运行导致js的继承不能像后台那么灵活而且js没有重载以及重写不方便(而且js中重写的意义不是很大),所以在js中很少用到面向对象,可能在一些插件中会看到对象的写法,写js的都会有同样的感觉在写一个插件的时候一般是先用面相过程把插件功能写出来,然后在重构改成对象的方法.但在实际项目开发中要求时间进度和开发成本很少会有那么宽松的时间让你先用面向过程实现功能在重构.实际开发中我们基本都是用面相过程写完就直接提交了.
这种写法发现一个问题就是,当你把这个页面的写完了之后过一段时间突然这个页面的功能需求或是页面布局要调整,你在看这个页面的代码,一下很难快速的把整个页面的代码逻辑步骤梳理清楚,我相信很多写前端都要同感吧! 举个例子:我几年前写的放大镜插件,现在我在放出来发现我写的这个插件在谷歌浏览器第一次渲染的时候没有效果,代码如下:
- 1 /// <reference path="../jquery11.js" />
- 2 (function ($) {
- 3 $.fn.extend({
- 4 jqoom: function (potions) {
- 5 var settings = {
- 6 width: 350,
- 7 height: 350,
- 8 position: "right"
- 9 }
- 10 if (potions) {
- 11 $.extend(settings, potions);
- 12 }
- 13 var ImgUrl = $("img", this).attr("src");
- 14 var ImgMinWidth = $("img", this).width();
- 15 var ImgMinHeigth = $("img", this).height();
- 16 var ImgWidth = 0;
- 17 var ImgHeight = 0;
- 18 var de = true;
- 19
- 20 $(this).hover(function (e) {
- 21 }, function () {
- 22 $("#jqoomz").remove();
- 23 $(document).unbind("mousemove");
- 24 $("#jqoomy").remove();
- 25
- 26 de = true;
- 27 });
- 28 $("img", this).hover(function (e) {
- 29 var pagex = e.x || e.pageX;
- 30 var pagey = e.y || e.pageY;
- 31 var pagex1 = 0;
- 32 var pagey1 = 0;
- 33 var leftcha = 0;
- 34 var topcha = 0;
- 35 _this = $(this).parents("div");
- 36 if ($("#jqoomz").length == 0) {
- 37 _this.after("<div id='jqoomz'></div>");
- 38 var obj = new Image();
- 39 obj.src = ImgUrl;
- 40 obj.onload = function () {
- 41 if (de && obj.height > 0) {
- 42 de = false;
- 43 ImgWidth = obj.width;
- 44 ImgHeight = obj.height;
- 45 finder.call(_this.find("img")[0]);
- 46 }
- 47 };
- 48 $("#jqoomz").width(settings.width).height(settings.height).offset({
- 49 left: $(_this).outerWidth() + $(_this).offset().left,
- 50 top: $(_this)[0].offsetTop
- 51 }).append($("<img></img>").attr("src", ImgUrl));
- 52 if (de && obj.height > 0) {
- 53 de = false;
- 54 ImgWidth = obj.width;
- 55 ImgHeight = obj.height;
- 56 finder.call(this);
- 57 }
- 58 }
- 59 function mover(event) {
- 60 var pagex2 = event.x || event.pageX;
- 61 var pagey2 = event.y || event.pageY;
- 62 if (parseInt(pagex2 + leftcha) <= parseInt($(_this).width() + $(_this).offset().left) && pagex2 >= leftcha + $(_this).offset().left) {
- 63 $(this).offset({left: pagex2 - leftcha});
- 64 } else {
- 65 if (parseInt(pagex2 + leftcha) > parseInt($(_this).width() + $(_this).offset().left) && pagex2)
- 66 $(this).offset({left: $(_this).width() + $(_this).offset().left - leftcha * 2});
- 67 else
- 68 $(this).offset({left: $(_this).offset().left});
- 69 }
- 70 if (parseInt(pagey2 + topcha) <= parseInt($(_this).height() + $(_this).offset().top) && pagey2 >= topcha + $(_this).offset().top) {
- 71 $(this).offset({top: (pagey2 - topcha)});
- 72 //document.getElementById("move").style.top = (pagey2 - (this.pagey - this.divtop)).toString() + "px";
- 73 } else {
- 74 if (parseInt(pagey2 + topcha) > parseInt($(_this).height() + $(_this).offset().top))
- 75 $(this).offset({top: ($(_this).height() + $(_this).offset().top - topcha * 2)});
- 76 //document.getElementById("move").style.top = (this.height - this.divHeight).toString() + "px";
- 77 else
- 78 $(this).offset({top: $(_this).offset().top});
- 79 //document.getElementById("move").style.top = "0px"
- 80 }
- 81 var bilx = ($(this).offset().left - $(_this).offset().left) / (ImgMinWidth / ImgWidth);
- 82 var bily = ($(this).offset().top - $(_this).offset().top) / (ImgMinHeigth / ImgHeight);
- 83 $("#jqoomz img").css({"margin-left": -bilx, "margin-top": -bily});
- 84 }
- 85
- 86 function finder() {
- 87 if (parseFloat($(this).offset().top + $(this).height() - (ImgMinHeigth / ImgHeight * ImgMinHeigth)) >=
- 88 parseFloat(pagey - ImgMinHeigth / ImgHeight * ImgMinHeigth / 2) && parseFloat(pagey - ImgMinHeigth / ImgHeight * ImgMinHeigth / 2) >=
- 89 parseFloat($(this).offset().top)) {
- 90 pagey1 = (pagey - ImgMinHeigth / ImgHeight * ImgMinHeigth / 2);
- 91 } else {
- 92 if ((pagey - ImgMinHeigth / ImgHeight * ImgMinHeigth / 2) < $(this).offset().top) {
- 93 pagey1 = $(this).offset().top;
- 94 } else {
- 95 pagey1 = ($(this).offset().top + $(this).height() - (ImgMinHeigth / ImgHeight * ImgMinHeigth));
- 96 }
- 97 }
- 98 if (($(this).offset().left + $(this).width() - ImgMinWidth / ImgWidth * ImgMinWidth) >=
- 99 (pagex - ImgMinWidth / ImgWidth * ImgMinWidth / 2) && (pagex - ImgMinWidth / ImgWidth * ImgMinWidth / 2) >=
- 100 $(this).offset().left) {
- 101 pagex1 = (pagex - ImgMinWidth / ImgWidth * ImgMinWidth / 2);
- 102 } else {
- 103 if ((pagex - ImgMinWidth / ImgWidth * ImgMinWidth / 2) < $(this).offset().left) {
- 104 pagex1 = $(this).offset().left;
- 105 } else {
- 106 pagex1 = ($(this).offset().left + $(this).width() - ImgMinWidth / ImgWidth * ImgMinWidth);
- 107 }
- 108 }
- 109 leftcha = ImgMinWidth / ImgWidth * ImgMinWidth / 2;
- 110 topcha = ImgMinHeigth / ImgHeight * ImgMinHeigth / 2;
- 111 if ($("#jqoomy").length == 0) {
- 112 $(this).after("<div id='jqoomy'></div>")
- 113 .siblings("#jqoomy")
- 114 .addClass("jqoomy").show()
- 115 .width((ImgMinWidth / ImgWidth * ImgMinWidth))
- 116 .height((ImgMinHeigth / ImgHeight * ImgMinHeigth)).offset({
- 117 top: pagey1,
- 118 left: pagex1
- 119 });
- 120 }
- 121 $(document).on("mousemove", $.proxy(mover, $("#jqoomy")));
- 122 }
- 123 }, function () {
- 124 });
- 125 }
- 126 });
- 127 })(jQuery);
html:
- <!DOCTYPE html>
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title></title>
- <script src="jquery11.js"></script>
- <script src="OppJqoom.js"></script>
- <style type="text/css">
- .jqoom
- {
- width: 350px;
- height: 350px;
- border: solid 1px #DFDFDF;
- z-index: 10;
- }
- .jqoom img
- {
- cursor: pointer;
- z-index: 10;
- max-height: 350px;
- max-width: 350px;
- }
- .jqoomy
- {
- background-color: white;
- position: relative;
- z-index: 999;
- opacity: 0.5;
- cursor: pointer;
- border: solid 1px #DFDFDF;
- }
- #jqoomz
- {
- border: solid 1px #DFDFDF;
- position: absolute;
- overflow: hidden;
- }
- .lef
- {
- border: 1px solid #DFDFDF;
- display: block;
- height: 72px;
- line-height: 72px;
- text-align: center;
- text-decoration: none;
- width: 10px;
- background-color:#EBEBEB;
- float:left;
- }
- .lef:hover
- {
- color:red;
- }
- .jqooz
- {
- float:left;
- width:352px;
- margin-top:20px;
- }
- .jqooz ul
- {
- float: left;
- margin: 0;
- padding: 0;
- width:328px;
- height:72px;
- }
- .jqooz ul li
- {
- display: inline;
- list-style: none outside none;
- margin: 0 10px;
- }
- .jqooz ul li img
- {
- border: 1px solid #DFDFDF;
- max-height: 72px;
- max-width: 120px;
- }
- .jqooz ul li img:hover
- {
- border: 1px solid #ff6600;
- }
- </style>
- <script type="text/javascript">
- $(function () {
- $(".jqoom").jqoom();
- });
- </script>
- </head>
- <body>
- <div class="jqoom">
- <img src="b3.jpg" />
- </div>
- <div class="jqooz">
- <a href="javascript:void(0)" class="lef"><</a>
- <ul>
- <li><a>
- <img src="b3.jpg" /></a></li>
- </ul>
- <a href="javascript:void(0)" class="lef">></a>
- </div>
- </body>
- </html>
效果:
现在我要修改这个插件为什么在谷歌浏览器第一次加载的时候没有效果,那我要重新跟着代码来梳理放大镜里面的整个功能步骤,这个放大镜的功能还不是很复杂,在实际项目中各种函数回调嵌套,取数,数据处理,显示,页面的动态效果都交织在onload或是ready里面你要花几个小时甚至一整天来梳理你要修改页面的代码逻辑,而且还未必能梳理的全面,所以经常会有前端同事在隔了一段时间给之前写的页面添加注释的时候说我自己写代码都开始看不懂了.
本身javascript特点之一是事件监听函数回调,这是它优点,nodejs作者之所以选择js其中一个原因就是javascript的事件监听函数回调带来的优点,但函数回调同时也带来一个缺点就是经常出现return不出数据,典型的例子就是ajax,jQuery传统的ajax成功之后回调success方法,当你要把这个ajax的输出作为另一个ajax的输入的时候你就不得不要嵌套ajax,一旦嵌套多了这个代码的可读性和复杂度就增加了很多!后期的维护也自然增加了难度,Promise出来之后,jQuery、angular也都纷纷加了Promise。为什么javascript在后期维护要花这么大的时间去梳理逻辑?
我们在看看后台java或c#的语言是怎么做,典型的javaweb几乎都是springMVC框架,C#做web毋庸置疑是.net MVC,他们都有共同的特点是c层提供给前台页面ajax调用的方法都是按照所需要的数据一个一个拆分的,还有相对于的m层,mvc其实是两个维度的分层这是我个人观点,一个维度是单个细小的功能分为view,control,model,另一个维度是整个页面分成多个小的功能.所以你发现后台代码要修改其实很容易就把逻辑梳理,那前台javascript也能不能按照整个思路来取分层呢?
这个插件没有涉及到动态取数,所以分层的标准也不一样,在这里我分了两层,第一层是对鼠标移动后图片的一系列算法,第二层是事件绑定分的一系列dom的操作,代码如下:
- /**
- * Created by on 2016/11/2.
- */
- (function ($) {
- //构造函数逻辑主线路
- var OppJqoom = function (_this, potions) {
- this._this = _this;
- this.ImgUrl = $("img", this._this).attr("src");
- this.ImgMinWidth = $("img", this._this).width();
- this.ImgMinHeigth = $("img", this._this).height();
- this.ImgWidth ,this.ImgHeight ,this.leftcha,this.topcha;
- var settings = {
- width: 350,
- height: 350,
- position: "right"
- }
- $.extend(this,settings);
- if (potions) {
- $.extend(this, potions);
- }
- this.domOperation.Jqoomhover.call(this);
- this.domOperation.imghover.call(this);
- };
- OppJqoom.prototype = {
- // 第一层 算法层
- basicOperation: {
- /* 获取遮罩层的top和left*/
- finder: function (that) {
- var pagey1, pagex1;
- if (parseFloat($(this).offset().top + $(this).height() - (that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth)) >=
- parseFloat(this.pagey - that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth / 2) && parseFloat(this.pagey - that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth / 2) >=
- parseFloat($(this).offset().top)) {
- pagey1 = (this.pagey - that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth / 2);
- } else {
- if ((this.pagey - that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth / 2) < $(this).offset().top) {
- pagey1 = $(this).offset().top;
- } else {
- pagey1 = ($(this).offset().top + $(this).height() - (that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth));
- }
- }
- if (($(this).offset().left + $(this).width() - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth) >=
- (this.pagex - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth / 2) && (this.pagex - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth / 2) >=
- $(this).offset().left) {
- pagex1 = (this.pagex - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth / 2);
- } else {
- if ((this.pagex - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth / 2) < $(this).offset().left) {
- pagex1 = $(this).offset().left;
- } else {
- pagex1 = ($(this).offset().left + $(this).width() - that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth);
- }
- }
- that.leftcha = that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth / 2;
- that.topcha = that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth / 2;
- that.domOperation.docMousemove.call(that);
- return {top: pagey1, left: pagex1};
- },
- // 放大镜的图片的top和left
- mover: function (that) {
- if (parseInt(that.pagex2 + that.leftcha) <= parseInt(that._this.width() + that._this.offset().left) && that.pagex2 >= that.leftcha + that._this.offset().left) {
- $(this).offset({left: that.pagex2 - that.leftcha});
- } else {
- if (parseInt(that.pagex2 + that.leftcha) > parseInt(that._this.width() + that._this.offset().left) && that.pagex2)
- $(this).offset({left: that._this.width() + that._this.offset().left - that.leftcha * 2});
- else
- $(this).offset({left: that._this.offset().left});
- }
- if (parseInt(that.pagey2 + that.topcha) <= parseInt(that._this.height() + that._this.offset().top) && that.pagey2 >= that.topcha + that._this.offset().top) {
- $(this).offset({top: (that.pagey2 - that.topcha)});
- //document.getElementById("move").style.top = (pagey2 - (this.pagey - this.divtop)).toString() + "px";
- } else {
- if (parseInt(that.pagey2 + that.topcha) > parseInt(that._this.height() + that._this.offset().top))
- $(this).offset({top: (that._this.height() + that._this.offset().top - that.topcha * 2)});
- //document.getElementById("move").style.top = (this.height - this.divHeight).toString() + "px";
- else
- $(this).offset({top: that._this.offset().top});
- //document.getElementById("move").style.top = "0px"
- }
- var bilx = ($(this).offset().left - that._this.offset().left) / (that.ImgMinWidth / that.ImgWidth);
- var bily = ($(this).offset().top - that._this.offset().top) / (that.ImgMinHeigth / that.ImgHeight);
- return{left:bilx,top:bily};
- }
- },
- // 第二层 事件绑定层
- domOperation: {
- // 鼠标移动到图片的一系列dom的操作
- imghover: function () {
- var that = this;
- $("img", this._this).hover(function (e) {
- this.pagex = e.x || e.pageX;
- this.pagey = e.y || e.pageY;
- var offset;
- var obj = new Image();
- obj.src = that.ImgUrl;
- obj.onload = function () {
- if (obj.height > 0) {
- that.ImgWidth = obj.width;
- that.ImgHeight = obj.height;
- if ($("#jqoomz").length == 0) {
- that._this.after("<div id='jqoomz'></div>");
- }
- offset = that.basicOperation.finder.call(that._this.find("img")[0],that);
- }
- };
- if ($("#jqoomz").length == 0) {
- that.ImgWidth = obj.width;
- that.ImgHeight = obj.height;
- that._this.after("<div id='jqoomz'></div>");
- }
- offset = that.basicOperation.finder.call(this,that);
- if ($("#jqoomy").length == 0) {
- $(this).after("<div id='jqoomy'></div>")
- .siblings("#jqoomy")
- .addClass("jqoomy")
- .show()
- .width((that.ImgMinWidth / that.ImgWidth * that.ImgMinWidth))
- .height((that.ImgMinHeigth / that.ImgHeight * that.ImgMinHeigth))
- .offset({
- top: offset.top,
- left: offset.left
- });
- }
- $("#jqoomz").width(that.width).height(that.height).offset({
- left: that._this.outerWidth() + that._this.offset().left,
- top: that._this[0].offsetTop
- }).append($("<img></img>").attr("src", that.ImgUrl));
- },function () {});
- },
- //鼠标在图片上滑动的一系列dom操作
- docMousemove: function () {
- var that=this;
- $(document).on("mousemove", function (event) {
- that.pagex2 = event.x || event.pageX;
- that.pagey2 = event.y || event.pageY;
- var offset=that.basicOperation.mover.call($("#jqoomy"),that);
- $("#jqoomz img").css({"margin-left": -offset.left, "margin-top": -offset.top});
- });
- },
- //鼠标移除图片的一系列dom操作
- Jqoomhover:function () {
- this._this.hover(function (e) {
- }, function () {
- console.log(111);
- $("#jqoomz").remove();
- $(document).unbind("mousemove");
- $("#jqoomy").remove();
- });
- }
- }
- };
- $.fn.extend({
- jqoom: function (potions) {
- return new OppJqoom(this, potions);
- }
- })
- })(jQuery);
然后加上简单的注释感觉页面的逻辑步骤就很清晰了,当然这种写法一种比较麻烦的就是this的用法,对象中嵌套对象调用里面的方法this是指向自己的对象.
在实际开发中我们可以分为数据读取层,数据处理层,以及dom动态效果层,如果业务比较繁杂也可以在分个数据展现层.
当然这是我个人的理解,可能有很多方面没考虑到,只是提供了一些思路!
javascript面向对象分层思维的更多相关文章
- JavaScript 面向对象(二) —— 案例篇
看案例前可以先看看基础篇:JavaScript 面向对象(一) —— 基础篇 案例——面向对象的选项卡:把面向过程的程序一步步改成面向对象的形式,使其能够更加的通用(但是通用的东西,一般会比较臃肿). ...
- JavaScript面向对象轻松入门之概述(demo by ES5、ES6、TypeScript)
写在前面的话 这是一个JavaScript面向对象系列的文章,本篇文章主要讲概述,介绍面向对象,后面计划还会有5篇文章,讲抽象.封装.继承.多态,最后再来一个综合. 说实话,写JavaScript面向 ...
- JavaScript面向对象(一)——JS OOP基础与JS 中This指向详解
前 言 JRedu 学过程序语言的都知道,我们的程序语言进化是从"面向机器".到"面向过程".再到"面向对象"一步步的发展而来.类似于 ...
- 用大白话扯扯那"神奇"的面向对象编程思维(一)
前言: 每当提到面向对象的时候,初学者肯定都是一脸懵逼的状态,到底什么是面向对象?会用面向对象后有什么牛逼之处吗?不会用是不是就会死掉?答案肯定不会死掉,我们可以来简单的举一 个栗子 1.当你想到熊猫 ...
- 再谈javascript面向对象编程
前言:虽有陈皓<Javascript 面向对象编程>珠玉在前,但是我还是忍不住再画蛇添足的补上一篇文章,主要是因为javascript这门语言魅力.另外这篇文章是一篇入门文章,我也是才开始 ...
- JavaScript面向对象的三大特性
1.JavaScript面向对象的三大特性 JavaScript的三大特性:封装性.继承性.多态性. 2.JavaScript实现封装特性 在一些静态类型的语言如java中,本身语法就提供了这些功能. ...
- 【面向对象】用大白话扯扯那"神奇"的面向对象编程思维(二)
前言: 上一章我们用大白话讲解了一下面向对象的编程思维,那么这一张我们来讲讲如何用面向对象来书写代码.终于到了激动人心的时刻了..... 传送门:https://www.cnblogs.com/sy1 ...
- JavaScript面向对象class
JavaScript面向对象class 本周逆战班学习的主题是“面向对象”,很多人觉得面向对象很难理解,但其实我们早就在面向对象的思想之中了,今天就让我们再重新认识一下他,主要介绍一下ES6中新增的c ...
- JavaScript学习笔记(三)——this、原型、javascript面向对象
一.this 在JavaScript中this表示:谁调用它,this就是谁. JavaScript是由对象组成的,一切皆为对象,万物皆为对象.this是一个动态的对象,根据调用的对象不同而发生变化, ...
随机推荐
- undefined reference to `pthread_create'问题解决
在编译pthread有关的程序时,出现undefined reference to `pthread_create'这样的错误. 问题原因: pthread 库不是 Linux 系统默认的库,连接时需 ...
- ASP.NET 项目 App_Code下无法找到类
APP_CODE 默认情况下,VS2010中新建的WebApplication中是没有App_Code文件夹的,若需要使用,可以自己手动添加文件夹,然后将文件夹名称设置为App_Code,然后在该文件 ...
- .NET中的计时器控件Timer
本章借介绍一些粗浅的Timer控件使用方法. 介绍Timer控件的常用属性和事件 1. Interval 属性表示 Timer控件的时间间隔. 类型是int默认是毫秒. 2. Enabled 属性 表 ...
- 第一章 Collections 类、泛型类和Timing类概述
摘抄<数据结构与算法(C#语言描述)> 删除很多废话 1.1群集(collection)的定义 群集是一种结构化的数据类型.存储数据,并且提供数据的添.删.改操作,以及对群集不同属性值的设 ...
- zend studio导入thinkphp的乱码问题
刚刚导入thinkphp有乱码还有错误怎么办? windows -> preference -> Work space -> text file encodeing设置为 UTF-8 ...
- Silverlight读取Zip文件中的图片与视频
首先看看Demo的截图: 下面我将一步步展示实现这个Demo的过程,这个需求就是读出Zip文件中的图片与视频. Demo整体架构: 首先我们准备几张图片和视频,然后将其压缩至resource.zip文 ...
- event.preventDefault()
<!doctype html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- jQuery ajax Load关闭缓存的方法
[导读] 在jQuery ajax Load关闭缓存的方法很简单,我们只要在$ ajaxSetup中把cache: false就楞以了,当然我们还可以使用一个随机参数来实例了.简单介绍load(url ...
- Scala学习笔记1(安装)
到 官网下载scala tar包 http://www.scala-lang.org/download/ mac Finder里双击解压. 改名成scala 进命令行, mv ~/Downloads ...
- 简单快速的开发框架-SRF
1.是什么 SRF(simply and rapid development framework) 一套基于asp.net mvc的开发框架,致力于提供简单.快速的企业应用开发方案,旨在解决企业应用开 ...