1.组件结构
2.页面调用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>面向对象权限配置组件</title> <link rel="stylesheet" type="text/css" href="assets/UserRoleSelector/css/UserRoleSelector.css"> </head> <body> <button id="showSelector">配置用户角色</button> <script src="assets/UserRoleSelector/js/UserRoleSelector.js"></script> <script> window.onload = function(){ // 通过构造器传入参数,构建UserRoleSelector的实例 var selector = new UserRoleSelector({ // 传参 show : false, // 默认不显示 data : [{"value":"1","text":"系统管理员"}, {"value":"2","text":"部门经理"}, {"value":"3","text":"部门主管"}, {"value":"4","text":"销售经理"}, {"value":"5","text":"财务会计"}, {"value":"6","text":"财务出纳"}], // 数据列表 传入json对象 onSave : function(){ // 保存 传参 参数为组件本身 alert(this.getValues()); // do code // console.log(this); // 问题:改变不了this的引用 // this.getValues(); // 获得当前被选中的数据 this.hide(); // 此时this指向UserRoleSelector } }); document.getElementById("showSelector").onclick = function(){ if(selector.status){ selector.hide(); }else{ selector.show(); // 让组件出现 } } } </script> </body> </html>
3.组件封装:
UserRoleSelector.css
html,body{ width: 100%; height: 100%; margin: 0; padding: 0; font-family: Airal,‘microsoft yahei‘; background-color: #b1b1b1; -moz-user-select: none;/*火狐*/ -webkit-user-select: none;/*webkit浏览器*/ -ms-user-select: none;/*IE10*/ -khtml-user-select: none;/*早期浏览器*/ user-select: none; overflow: hidden; } ul,li{ list-style: none; margin: 0; padding: 0; } .mask{ position: fixed; top: 0; bottom: 0; left: 0; right: 0; background-color: rgba(0,0,0,.5); } .user-role-selector{ position: absolute; top: 50%; left: 50%; margin-left: -290px; margin-top: -250px; background-color: #fff; border-radius: 2px;/*边角半径*/ padding: 50px 20px; width: 540px; height: 400px; } .user-role-selector .data-list{ width: 40%; height: 90%; background-color: #fafafa; border: 1px solid #e5e5e5; float: left; } .user-role-selector .data-list li{ width: 100%; height: 36px; line-height: 36px; text-indent: 10px; color: #666; font-size: 14px; cursor: pointer; } .user-role-selector .data-list li:hover{ background-color: #039ae3; color: #fff; } .user-role-selector .data-list li.selected{ background-color: #666; color: #fff; } .user-role-selector .data-oper{ width: 18%; height: 100%; float: left; padding-top: 25%; } .user-role-selector .data-oper .button{ margin: 20px auto; text-align: center; } .user-role-selector .button{ width: 80px; height: 36px; display: block; border: 1px solid #d9d9d9; line-height: 36px; text-decoration: none; color: #333; background: #f3f3f3; font-size: 14px; } .user-role-selector .button:hover{ background-color: #039ae3; color: #fff; } .user-role-selector .data-bar{ position: absolute; bottom: 20px; left: 0; width: 100%; height: 10%; } .user-role-selector .data-bar .button{ float: right; text-align: center; margin-right: 25px; } .user-role-selector .data-bar .button.close{ background-color: #e84c4c; color: #fff; }
UserRoleSelector.js
// 创建闭包 避免变量污染(全局污染) var UserRoleSelector = (function(){ /** * 1.构建 构造器函数 * 一般首字母大写 */ // 2.定义UserRoleSelector类型构造器 function UserRoleSelector(options) { // 3.用户传入的参数 // this.options = options||{}; // 4.为了避免用户不传入options对象造成的NullPointer(空指针异常) this.init(options||{}); // 5.初始化操作 // this.render(); // 9.生成(渲染)dom结构 this.bind(); // 绑定插件中dom需要的所有事件 } // 11.将要被渲染的dom结构 var html = ‘<div class="user-role-selector">‘ + ‘<ul class="left-list data-list">‘ + // ‘<li>系统管理员</li>‘ + // ‘<li>部门经理</li>‘ + // ‘<li>部门组管</li>‘ + // ‘<li>销售经理</li>‘ + // ‘<li>财务会计</li>‘ + // ‘<li>财务出纳</li>‘ + ‘</ul>‘ + ‘<div class="data-oper">‘ + ‘<a href="#" class="add button">添加</a>‘ + ‘<a href="#" class="del button">删除</a>‘ + ‘</div>‘ + ‘<ul class="right-list data-list"></ul>‘ + ‘<div class="data-bar"><a href="#" class="close button">关闭</a>‘ + ‘<a href="#" class="save button">保存</a></div>‘ + ‘</div>‘; // 6.扩展UserRoleSelector类型实例的功能 UserRoleSelector.prototype = { init:function(options) { // 7.初始化操作 this.options = options; // 8.初始化参数 this.dom = document.createElement("div");// 12.创建元素 this.dom.className = "mask"; this.dom.style.display = this.options.show?"block":"none"; // 由用户决定元素是否显示 this.dom.innerHTML = html; this.status = this.options.show?1:0; // 0代表隐藏 1代表显示 document.body.appendChild(this.dom); // 13.将dom插入到新创建的div元素中 // 27.找到左右列表 便于接受index.html传入数据列表参数 this.left = this.dom.querySelector(".left-list.data-list"); this.right = this.dom.querySelector(".right-list.data-list"); // 32.add、del按钮 this.add = this.dom.querySelector(".button.add"); // 寻找add按钮 this.del = this.dom.querySelector(".button.del"); // 寻找del按钮 // 18.save、close按钮 this.save = this.dom.querySelector(".button.save"); // 寻找save按钮 // console.log(this.save); this.close = this.dom.querySelector(".button.close"); // 寻找close按钮 // 28.循环输出列表数据 var data = this.options.data||[]; for(var i=0;i<data.length;i++){ this.left.innerHTML+="<li data-value=‘"+data[i].value+"‘>"+data[i].text+"</li>"; } this.items = this.left.querySelectorAll("li");// 29.找到所有的li // console.log(this.items.length); }, // render:function() { // 10.渲染dom // this.dom.innerHTML = html; // }, bind:function() { // 16.绑定插件中dom需要的所有事件 var _this = this; // 21.此处this为UserRoleSelector组件本身,将组件的引用保存在局部变量_this中 if(this.options.onSave){ // 23.保存方法 判断用户是否传参 // this.save.onclick = function() { // 24.方法一:外层包一个function 便于改变this的引用 及 接收参数 // _this.options.onSave.call(_this); // 25.call方法 起到函数调用过程中改变this的引用,将作用域改为this(此处指向UserRoleSelector组件本身) // } this.save.onclick = _this.options.onSave.bind(_this); // 26.方法二:调用bind方法,直接参入_this,调用onclick方法,返回的是个函数 起到函数调用过程中,_this对象指向this } // 17.找到当前dom对象中的按钮 写在init方法中 this.close.onclick = function() { // 19.定义close按钮的绑定事件 // this.hide(); // 隐藏组件 _this.hide(); // 22.隐藏组件 使用局部变量_this替换this,使得指向为UserRoleSelector组件 // 20.注意:因为函数的作用域问题,当函数被调用过程中,this指向函数本身,此处为close对象,而我们想指向UserRoleSelector组件,所有需要配置this }; // this.add.onclick = function(){ // // 33.拿到left下面所有被选中的item(.selected) // var selecteds = _this.left.querySelectorAll("li.selected"); // // 34.往right里面append // for(var i=0;i<selecteds.length;i++){ // _this.right.appendChild(selecteds[i]); // } // }; // this.del.onclick = function(){ // // 35.拿到right下面所有被选中的item(.selected) // var selecteds = _this.right.querySelectorAll("li.selected"); // // 36.往left里面append // for(var i=0;i<selecteds.length;i++){ // _this.left.appendChild(selecteds[i]); // } // }; /** * bind 和 call 的区别 * bind返回的是一个函数,将来时 * call返回的是一个对象,现在进行时 */ this.add.onclick = this._operClick.bind(this,this.add); // 39.简化代码 this.del.onclick = this._operClick.bind(this,this.del); // 39.简化代码 // 30.给所有的li,绑定事件 for(var i=0;i<this.items.length;i++){ // this.items[i].onclick = function() { // // 31.给被点击的元素添加样式,再次点击清除被选中样式 // if(this.className.indexOf("selected")!=-1){ // 清除被选中样式 // this.className = ""; // }else{ // 添加被选中样式 // this.className = "selected"; // } // } this.items[i].onclick = this._itemClick; // 38.调用私有方法 } }, show:function() { // 14.定义show方法 this.dom.style.display = "block"; this.status = 1; }, hide:function() { // 15.定义hide方法 this.dom.style.display = "none"; this.status = 0; }, _itemClick:function() { // 37.定义私有方法,提高代码效率,节约内存空间 if(this.className.indexOf("selected")!=-1){ // 清除被选中样式 this.className = ""; }else{ // 添加被选中样式 this.className = "selected"; } }, _operClick:function(target){ // 40.定义私有方法 // console.log(target); // 41.封装方法 var one,two; if(target.className.indexOf("add")!=-1){ one = this.left; two = this.right; }else{ one = this.right; two = this.left; } // 拿到one下面所有被选中的item(.selected) var selecteds = one.querySelectorAll("li.selected"); // 往two里面append for(var i=0;i<selecteds.length;i++){ two.appendChild(selecteds[i]); } }, getValues:function(){ // 43.获得当前被选中的数据 var values = ""; var selecteds = this.right.querySelectorAll("li"); // 44.获得右列表所有数据 // 45.循环输出 for(var i=0;i<selecteds.length;i++){ values+=selecteds[i].getAttribute("data-value"); if(i!=selecteds.length-1){ values+=","; } } return values; } }; // 每一个构造器函数都有一个prototype属性 // 构造器函数 与 普通函数 的区别 // new UserRoleSelector(); // 调用构造器函数 创建一个被持有句柄的闭包空间,运行函数里面的代码(生命周期比普通函数长),this指向就是当前这块这块空间的引用 // show(); // 调用普通函数 创建一个临时闭包空间,运行函数里面的代码,this指向是window对象 return UserRoleSelector; // })();
.
时间: 2024-10-25 19:58:26