面向对象 实例 1:选项卡的制作 干巴巴的说知识点,味同嚼蜡啊,所以还是举个栗子,动动手,理解的更好一些~
这个实例的目的:把原先面向过程的思想转变为面向对象的思想 。
起步:制作一个选项卡 先写一个选项卡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <body> <div class ="tab1" > <button style ="background: red" > 按钮一</button > <button > 按钮二</button > <button > 按钮三</button > <p > 内容一</p > <p style ="display: none" > 内容二</p > <p style ="display: none" > 内容三</p > </div > </body> <script > let btns = document .querySelectorAll (".tab1 button" ); let ps = document .querySelectorAll (".tab1 p" ); btns.forEach ((value, key ) => { value.onclick = function ( ) { ps.forEach ((v, k ) => { if (key == k) { btns[k].style .background = "red" ; ps[k].style .display = "block" ; } else { btns[k].style .background = "" ; ps[k].style .display = "none" ; } }) } }); </script >
多个选项卡 乡亲们注意了,项目经理进村了,带着新的需求进村啦!!
新需求:如果是多个选项卡呢,5 个、10 个、100 个?我们不会一个一个复制吧?
新需求:第一个选项卡添加下一页功能,第二个选项卡添加轮播功能
思想:如果是多个选项卡复用,可以用封装调用的方法,就是把 Tab 封装一下,以后直接调用
而添加独特的功能时,我们这里有三个场景
如果是所有 选项卡共性的功能 :封装
如果是 部分有 的功能(比方说 100 个选项卡里有 50 个):传配置参数,然后判断
如果是 独一无二的 功能:单独处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 function Tab (btns, ps, isNextPre = false , isAutoPlay = false ) { btns.forEach ((value, key ) => { value.onclick = function ( ) { psFor (key); }; }); if (isNextPre) { let num = 0 ; document .querySelector (".nextPre" ).onclick = function ( ) { num++; num = num > 2 ? 0 : num; psFor (num); }; } if (isAutoPlay) { document .querySelector (".autoPlay" ).onclick = function ( ) { let num = 0 ; setInterval (() => { num++; num = num > 2 ? 0 : num; psFor (num); }, 1000 ); }; } function psFor (key ) { ps.forEach ((v, k ) => { if (key == k) { btns[k].style .background = "red" ; ps[k].style .display = "block" ; } else { btns[k].style .background = "" ; ps[k].style .display = "none" ; } }); } } let btns = document .querySelectorAll (".tab1 button" );let ps = document .querySelectorAll (".tab1 p" );Tab (btns, ps, true );let btns2 = document .querySelectorAll (".tab2 button" );let ps2 = document .querySelectorAll (".tab2 p" );Tab (btns2, ps2, false , true );
提取功能 在上一个例子的基础上,我们做一些优化
优化:把独特的功能给提取出来,而不是放到共有的函数里
如何优化呢?用返还对象的方法(对象里可以包含函数,属性等值),我们可以在外部单独处理,例子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 function Tab (btns, ps, isNextPre = false , isAutoPlay = false ) { btns.forEach ((value, key ) => { value.onclick = function ( ) { psFor (key); }; }); function psFor (key ) { ps.forEach ((v, k ) => { if (key == k) { btns[k].style .background = "red" ; ps[k].style .display = "block" ; } else { btns[k].style .background = "" ; ps[k].style .display = "none" ; } }); } let obj = {}; obj.psFor = psFor; obj.eleLength = btns.length ; return obj; } let btns = document .querySelectorAll (".tab1 button" );let ps = document .querySelectorAll (".tab1 p" );let tab1 = Tab (btns, ps); let num = 0 ;document .querySelector (".nextPre" ).onclick = function ( ) { num++; num = num > tab1.eleLength - 1 ? 0 : num; tab1.psFor (num); }; let btns2 = document .querySelectorAll (".tab2 button" );let ps2 = document .querySelectorAll (".tab2 p" );let tab2 = Tab (btns2, ps2);let num2 = 0 ;document .querySelector (".autoPlay" ).onclick = function ( ) { let num2 = 0 ; setInterval (() => { num2++; num2 = num2 > tab2.eleLength - 1 ? 0 : num2; tab2.psFor (num2); }, 1000 ); };
至此,一个工厂模式 的选项卡,暂时告一段落,接下来介绍些基础的知识~
工厂模式 有的人就要问了:啥是工厂模式啊?
这里的工厂啊,就是我们把原料放到工厂里,然后它咕嘟咕嘟的加工,之后吐出来一个产品!
我们要做的呢,就是设计出这样的一个工厂!
面向对象的思路:抽象事物 --> 分析属性和方法
以下是一个 tab
选项卡的工厂模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function Tab ( ) { let obj = {}; obj.tablength = 1 ; obj.psFor = function ( ) { console .log ("psFor...." ); }; return obj; } let tab1 = Tab ();let tab2 = Tab ();
其实工厂模式,我们是不常用的,因为它有以下缺点:
对象识别问题 ,不知道实例化的对象是从那个工厂出来的
性能问题 :占内存,如下代码可证实
1 2 3 4 5 let tab1 = Tab ();let tab2 = Tab ();console .log ("tab1.psFor===tab2.psFor" , tab1.psFor === tab2.psFor );
那么如何解决这个问题呢?
解决的方法是:使用构造函数,把方法放到公共空间,原型 prototype 上 讲解原型的话又会引申出另一个知识点, new 运算符
new 运算符 我们先看一个例子
1 2 3 4 5 function test ( ) { console .log ("test.." ); } test (); new test ();
其中 new test
并没有写()
,但是 test
函数还是执行了,猜测一下应该是 new
帮我们执行的。
这里不深入讨论 new
,说个总结,new 运算符的功能有如下几点:
执行函数;
自动创建一个空对象;
把创建的对象指向另外一个对象;
把空对象和函数里的 this 衔接起来;(this 指向实例化对象)
隐式返还 this;
简化工厂模式 —> 构造函数 从工厂模式到 new
构造函数,其实简单了不少
1 2 3 4 5 function Tab ( ) { this .name = "张三" ; }
用了构造函数,就会提供一个原型 prototype
从工厂模式到构造函数的主要的思路就是:
属性放到构造函数中
方法放到 prototype
原型上,(prototype
是公共空间,如果把方法放到构造函数中,就会在创建的时候又创建一个空间,消耗内存,所以把方法放到公共空间。)
以下是两个模式的例子:
1 2 3 4 5 6 7 8 9 10 11 12 function Tab ( ) { let obj = {}; obj.tablength = 1 ; obj.psFor = function ( ) { console .log ("psFor...." ); }; return obj; } let tab1 = Tab ();let tab2 = Tab ();console .log (tab1.psFor === tab2.psFor );
1 2 3 4 5 6 7 8 9 10 11 function Tab ( ) { this .name = "张三" ; } Tab .prototype .psFor = function ( ) { console .log ("psFor..." ); }; let tab1 = new Tab ();let tab2 = new Tab ();console .log (tab1.psFor === tab2.psFor ); console .log (tab1.__proto__ === Tab .prototype );
构造函数有两个要求
首字符大写(约定俗成的)
属性放在构造函数 ;方法放在原型上 ,原型提供公共的空间(如果方法放到构造函数中,他也会占用内存 ,跟工厂模式就没有什么区别了)
实例化对象也是由两部分组成 :构造函数+原型,原型和构造函数里公用一个this
,也就是指向实例化的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function Tab (name ) { this .name = name; } Tab .prototype .hobby = function ( ) { console .log (this .name ); }; let tab1 = new Tab ("张三" );tab1.hobby (); let tab2 = new Tab ("李四" );tab2.hobby (); console .log (tab1.hobby === tab2.hobby );
每个原型上都有一个预定义属性:constructor
,这个属性指向构造函数
构造器有啥用呢:可以判断对象类型
1 2 3 4 5 6 7 let str = "1212fdsf" ;if (str.constructor === String ) { console .log ("字符串" ); } else { console .log ("不是" ); }
仿写 new 上面提到了 new
的几个功能,接下来尝试手写一个 new
注意两点: 修改指针 和 修改原型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function Tab ( ) { this .name = "张三" ; } function myNew (constructor, ...arg ) { let obj = {}; constructor.call (obj, ...arg); obj.__proto__ = constructor.prototype ; return obj; } Tab .prototype .psFor = function ( ) { console .log ("psFor..." ); }; let tab1 = myNew (Tab );console .log (tab1);
至此第一个实例结束了。
实例 2:方块拖动(面向过程=>面向对象) 接着第二个实例,样式和 dom
如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .mydiv1 { width: 100px; height: 100px; background: red; position: absolute; } .mydiv2 { width: 100px; height: 100px; background: blue; position: absolute; left: 300px; } </style> </head> <body> <div class="mydiv1"></div> <div class="mydiv2"></div> </body>
面向过程 的代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 mydiv1.onmousedown = (e ) => { let ev = e || window .event ; let x = ev.clientX - mydiv1.offsetLeft ; let y = ev.clientY - mydiv1.offsetTop ; mydiv1.onmousemove = (e ) => { let ev = e || window .event ; let xx = ev.clientX ; let yy = ev.clientY ; mydiv1.style .left = xx - x + "px" ; mydiv1.style .top = yy - y + "px" ; }; mydiv1.onmouseup = function ( ) { mydiv1.onmousemove = "" ; }; };
我们要转换为面向对象 ,思路如下:
首先分析属性:div
元素
接着分析方法:鼠标按下、鼠标抬起、鼠标拖动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 function Drag (ele ) { this .ele = ele; this .downFn (); } Drag .prototype .downFn = function ( ) { this .ele .onmousedown = (e ) => { let ev = e || window .event ; let x = ev.clientX - this .ele .offsetLeft ; let y = ev.clientY - this .ele .offsetTop ; this .moveFn (x, y); this .upFn (); }; }; Drag .prototype .moveFn = function (x, y ) { this .ele .onmousemove = (e ) => { let ev = e || window .event ; let xx = ev.clientX ; let yy = ev.clientY ; this .setStyle (xx - x, yy - y); }; }; Drag .prototype .setStyle = function (leftNum, topNum ) { this .ele .style .left = leftNum + "px" ; this .ele .style .top = topNum + "px" ; }; Drag .prototype .upFn = function ( ) { this .ele .onmouseup = () => { this .ele .onmousemove = "" ; }; }; let mydiv1 = document .querySelector (".mydiv1" );let mydiv2 = document .querySelector (".mydiv2" );let drag1 = new Drag (mydiv1);let drag2 = new Drag (mydiv2);
扩充功能的方法:继承 基础 如果 Son
想要继承 Dad
中的属性,可以通过 apply
,call
,bind
这些方法继承过来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function Dad (height ) { this .name = "张三" ; this .age = 20 ; this .height = height; this .money = "$1000000" ; } function Son (height ) { Dad .call (this , height); } let newSon = new Son ("178cm" );console .log (newSon);
其中关键的一步Dad.call(this,xxx)
如何理解这个?
我是这么记得,方法.call(要继承的对象,参数)
按照这个例子,也就是说构造函数中的 Dad
里的方法啊,属性啊,拿过来指向了 Son
实例化对象了。 这里会有点难理解,但是理解这里很有必要!
但是父亲原型上的方法能不能继承呢?
答案是可以的,以下就是一个简单方法,不过有 bug,下文会讲到为什么会有 bug,以及如何修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function Dad (height ) { this .name = "张三" ; this .age = 20 ; this .height = height; this .money = "$1000000" ; } Dad .prototype .hobby = function ( ) { console .log ("喜欢高尔夫" ); }; function Son (height ) { Dad .call (this , height); } let newSon = new Son ("178cm" );newSon.hobby ();
传递地址 有个很简单的方法,添加个Son.prototype = Dad.prototype;
但是这样又会带来传址 问题(prototype
是对象),也就是说,修改子类的属性,会影响到父类,反之同理。
知道复杂数据类型是传递地址这个原因了,问题解决也就有方向了,
解决方法 1:组合继承 要消除这种影响,可以用到组合继承,注意原型中的预定义属性会被覆盖掉,所以还要写回来
1 2 3 4 5 6 let Link = function ( ) {};Link .prototype = Dad .prototype ;Son .prototype = new Link ();Son .prototype .constructor = Son ;
方法一实战:拖拽色块(扩充功能)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 <script> function Drag (ele ) { this .ele = ele; this .downFn (); } Drag .prototype .downFn = function ( ) { this .ele .onmousedown = e => { let ev = e || window .event ; let x = ev.clientX - this .ele .offsetLeft ; let y = ev.clientY - this .ele .offsetTop ; this .moveFn (x, y); this .upFn (); } } Drag .prototype .moveFn = function (x, y ) { this .ele .onmousemove = e => { let ev = e || window .event ; let xx = ev.clientX ; let yy = ev.clientY ; this .setStyle (xx - x, yy - y); } } Drag .prototype .setStyle = function (leftNum, topNum ) { this .ele .style .left = leftNum + "px" ; this .ele .style .top = topNum + "px" ; } Drag .prototype .upFn = function ( ) { this .ele .onmouseup = () => { this .ele .onmousemove = "" ; } } let mydiv1 = document .querySelector (".mydiv1" ); let drag1 = new Drag (mydiv1); function LimitDrag (ele ) { Drag .call (this , ele); } let Link = function ( ) { }; Link .prototype = Drag .prototype ; LimitDrag .prototype = new Link (); LimitDrag .prototype .constructor = LimitDrag ; LimitDrag .prototype .setStyle = function (leftNum, topNum ) { leftNum = leftNum < 0 ? 0 : leftNum; topNum = topNum < 0 ? 0 : topNum; this .ele .style .left = leftNum + "px" ; this .ele .style .top = topNum + "px" ; } let mydiv2 = document .querySelector (".mydiv2" ); let drag2 = new LimitDrag (mydiv2); </script>
解决方法 2:深拷贝
判断是不是数组 Array.isArray()
需要留意的是对象下的null
也要判断。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function deepCopy (obj ) { let newObj = Array .isArray (obj) ? [] : {}; for (let i in obj) { if (obj.hasOwnProperty (i)) { if (typeof obj[i] === "object" ) { if (obj[i] === null ) { newObj[i] = null ; } else { newObj[i] = deepCopy (obj[i]); } } else { newObj[i] = obj[i]; } } } return newObj; }
然后调用一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 let obj = { name : "张三" , age : 20 , arr : [1 , 2 , 3 ], obj3 : {}, test : undefined , fn : function ( ) { console .log ("fn..." ); }, test2 : null , }; let obj2 = deepCopy (obj);obj2.age = 30 ; console .log (obj, obj2);
补充知识点:序列化(缺陷) 序列化复制对象,会丢失函数和值为undefined
的参数,所以用的时候要小心。
1 2 3 4 5 6 7 8 9 10 11 let obj = { name : "张三" , test : undefined , fn : function ( ) { console .log ("fn..." ); }, }; let obj2 = JSON .parse (JSON .stringify (obj));console .log (obj, obj2);
补充知识点:for in for in
会循环原型上的属性,我们深复制的时候是不需要复制原型上的属性的。
1 2 3 4 5 6 7 8 9 let obj = { name : "张三" , }; obj.__proto__ .age = 30 ; for (let i in obj) { console .log (i); }
原型链 原型其实是个对象
查找顺序
构造函数
Drag.prototype
Object.prototype
1 2 3 4 5 6 7 8 9 function Drag ( ) { } Drag .prototype .ele = "prototype value...." ;let obj = new Object ();Object .prototype .ele = "object value..." ;console .log (Object .prototype .__proto__ ); let drag1 = new Drag ();console .log (drag1.ele );
ES6 类 静态属性 方法和属性并不属于构造函数,而是属于实例化对象本身的。
当然也有属于构造函数本身,叫静态属性 ,静态方法 。用 static
来声明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Drag { static height = "178cm" ; static test ( ) { console .log ("test..." ); } constructor ( ) { this .name = "张三" ; } hobby ( ) { console .log ("篮球" ); } } Drag .height = "178cm" ;
ES6 类继承 用关键字 extend
来继承,属性用 super()
来拿过来
class Son extends Father
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Drag { static height = "178cm" ; static test ( ) { console .log ("test..." ); } constructor (age ) { this .name = "张三" ; this .age = age; } hobby ( ) { console .log ("篮球" ); } setStyle ( ) { console .log ("父类逻辑" ); } } class LimitDrag extends Drag { constructor (age ) { super (age); } setStyle ( ) { super .setStyle (); console .log ("子类逻辑" ); } } let drag2 = new LimitDrag (20 );drag2.setStyle ();
包装对象 为什么基本数据类型(比方说 string
,number
)也会有某些方法呢,是因为系统帮我们包装了,以下是模拟系统的操作
1 2 3 4 5 6 7 function mysplit (str, method, arg ) { let temp = new String (str); return temp[method](arg); } let arr = mysplit (str, "split" , " " );console .log (arr);
判断对象类型* constructor
能够判断实例化对象是从哪一个构造函数里出来的,也就是判断它的类型
1 2 3 4 5 6 7 function Person ( ) { this .name = "张三" ; } let zhangsan = new Person ();console .log (zhangsan.constructor === Person );
instanceof
不仅判断 Array ,还去判断原型链 Object
1 2 3 let arr = [];console .log (arr instanceof Array ); console .log (arr instanceof Object );
typeof
1 2 3 4 let arr = [];let obj = {};console .log (typeof arr); console .log (typeof obj);
Object.prototype.toString.call(arr)
1 2 3 4 let res = Object .prototype .toString .call (arr);let res2 = Object .prototype .toString .call (obj);console .log (res);console .log (res === "[object Array]" );
组件样式模板 封装组件的两个原则
合并配置推荐的方法 assign
,下面是一个栗子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Dailog { constructor (options ) { this .opts = Object .assign ( { width : "30%" , height : "200px" , title : "测试标题" , content : "测试内容" , dragable : true , maskable : true , isCancel : false , }, options ); } } let dailog1 = new Dailog ({ width : "40%" , height : "250px" , title : "测试标题" , isCancel : true , maskable : false , });
自定义事件 函数当成事件来执行 ,栗子如下
好处是:当有多个人来修改代码的时候,各执行各的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class MyEvent { constructor ( ) { this .handle = {}; } addEvent (eventName, fn ) { if (typeof this .handle [eventName] === "undefined" ) { this .handle [eventName] = []; } this .handle [eventName].push (fn); } trigger (eventName ) { if (!(eventName in this .handle )) { return ; } this .handle [eventName].forEach ((v ) => { v (); }); } removeEvent (eventName, fn ) { if (!(eventName in this .handle )) { return ; } for (let i = 0 ; i < this .handle [eventName].length ; i++) { if (this .handle [eventName][i] === fn) { this .handle [eventName].splice (i, 1 ); break ; } } } } let newEvent = new MyEvent ();newEvent.addEvent ("myEvent" , fn1); newEvent.addEvent ("myEvent" , fn2); newEvent.removeEvent ("myEvent" , fn2); newEvent.trigger ("myEvent" );
系统自定义事件 + 传参 如果想使用系统的自定义事件的话 首先,需要在我们的类上继承 EventTarget
1 class Dailog extends EventTarget {}
然后,添加一个监听:this.addEventListener("你的自定义事件名字",要调用的事件函数名);
接着可以用 new Event()
或者 new CustomEvent()
来创建事件对象,区别是,后者可以在detail
中传递参数
1 2 3 4 5 6 7 8 9 let success = new CustomEvent ("success" ,{ detail :value }); success (e ) { console .log (e.detail ); },
super
拿到父类,继承过来
举个栗子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 class Dailog extends EventTarget { constructor (options ) { super (); this .opts = Object .assign ( { width : "30%" , height : "200px" , title : "测试标题" , content : "测试内容" , dragable : true , maskable : true , isCancel : false , success ( ) { console .log ("默认点击确定了!!" ); }, cancel ( ) { console .log ("默认点击取消!!" ); }, }, options ); this .init (); } init ( ) { this .renderView (); let cancel = new Event ("cancel" ); this .addEventListener ("cancel" , this .opts .cancel ); this .addEventListener ("success" , this .opts .success ); this .dailogHtml .onclick = (e ) => { switch (e.target .className ) { case "k-close" : this .close (); this .dispatchEvent (cancel); break ; case "k-cancel" : this .close (); this .dispatchEvent (cancel); break ; case "k-primary" : this .close (); this .confim (); break ; } }; } confim (value ) { let success = new CustomEvent ("success" , { detail : value, }); this .dispatchEvent (success); } close ( ) { this .dailogHtml .querySelector (".k-wrapper" ).style .display = "none" ; this .dailogHtml .querySelector (".k-dialog" ).style .display = "none" ; } open ( ) { if (this .opts .maskable ) { this .dailogHtml .querySelector (".k-wrapper" ).style .display = "block" ; } this .dailogHtml .querySelector (".k-dialog" ).style .display = "block" ; } renderView ( ) { this .dailogHtml = document .createElement ("div" ); this .dailogHtml .innerHTML = `<div class="k-wrapper"></div> <div class="k-dialog" style="width:${this .opts.width} ;height:${ this .opts.height } "> <div class="k-header"> <span class="k-title">${ this .opts.title } </span><span class="k-close">X</span> </div> <div class="k-body"> <span>${this .opts.content} </span> </div> <div class="k-footer"> ${ this .opts.isCancel ? '<span class="k-cancel">取消</span>' : "" } <span class="k-primary">确定</span> </div> </div>` ; document .querySelector ("body" ).appendChild (this .dailogHtml ); } } class ExtendsDailog extends Dailog { constructor (options ) { super (options); this .renderInput (); } renderInput ( ) { let myInput = document .createElement ("input" ); myInput.type = "text" ; myInput.classList .add ("input-inner" ); this .dailogHtml .querySelector (".k-body" ).appendChild (myInput); } confim ( ) { let value = this .dailogHtml .querySelector (".input-inner" ).value ; super .confim (value); } } let dailog2 = new ExtendsDailog ({ width : "40%" , height : "250px" , title : "测试标题" , isCancel : true , maskable : false , success (e ) { console .log ("点击确定了!!" , e.detail ); }, cancel ( ) { console .log ("点击取消!!" ); }, }); document .querySelector (".dailog2" ).onclick = function ( ) { dailog2.open (); };
Jquery 我整理到这里了~
JQuery 源码简单刨析,分析源码不再痛苦~