面向对象封装自己的库
主题
一、定义函数返还JQ对象
二、ready方法和原生节点处理
三、选择器器封装
四、封装JQ的eq方法
五、封装JQ的click方法
六、jQ中的链式操作
七、封装JQ的css方法
八、cssHooks扩展功能
知识点
- 对象成员与类成员
- 判断类型
- 链式调用实现
- 正则表达式
jquery特性说明
知己知彼,百战不殆;想要知道jq功能如何实现,先要了解其特性;
###如何实现链式调用
根据对象的特性,发还jq对象;
- 返还this对象
js
class Jq{
click(){
console.log("click...");
return this;
}
}
let myjq = new Jq();
myjq.click().click();
- 返还实例化对象
处理ready和原生节点
- 针对ready方法做兼容处理
- 原生节点直接保存
js
if (typeof arg === "string") {
let els = document.querySelectorAll(arg);
} else if (typeof arg === 'function') {
window.addEventListener("DOMContentLoaded",arg,false);
} else {
if(typeof arg.length === 'undefined'){
// 一个对象;
this[0] = arg;
this.length = 1;
}else{
// 对象类数组;
this.addEle(arg);
}
}
###选择器器封装
- $(".box")选择节点实现
封装jq的eq方法
注意返还对象,实现链式调用
js
eq(index){
// 继续操作
// return this[index];
return new Jq(this[index],this);
}
###实现end方法
返还上次操作的节点;
js
end(){
return this.prevObject;
}
实现jq里的click方法
绑定click事件
js
click(fn) {
for (let i = 0; i < this.length; i++) {
this[i].addEventListener("click", fn, false);
}
}
实现on方法
和click方法类似,可以处理多个事件;
实现css方法
获取样式封装
设置样式封装
cssNumber
js{ animationIterationCount: true, columnCount: true, fillOpacity: true, flexGrow: true, flexShrink: true, fontWeight: true, gridArea: true, gridColumn: true, gridColumnEnd: true, gridColumnStart: true, gridRow: true, gridRowEnd: true, gridRowStart: true, lineHeight: true, opacity: true, order: true, orphans: true, widows: true, zIndex: true, zoom: true }
使用类仿JQuery功能封装
myjqtest.html
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./myjq.js"></script>
<style>
.box {
background: red;
width: 100px;
height: 100px;
}
.box2 {
background: yellow;
}
</style>
</head>
<body>
<div class="box" style="background: red;">111</div>
<div class="box" style="background: blue;">222</div>
<h1>自己的jq</h1>
<!-- <button>点击1</button>
<button>点击2</button> -->
<div class="box">div1</div>
<!-- <div class="box2">div2</div> -->
<button>点击</button>
</body>
<script>
// jq
// $(".box").click(function(){
// console.log("click");
// })
// $(document.querySelector("div")).click(()=>{
// console.log(111);
// })
// $(function(){
// console.log("加载完毕");
// })
// let res = $(".box");
// console.log(res);
// $(".box").click(()=>{
// console.log("click");
// })
// $(document.querySelectorAll(".box")).click(()=>{
// console.log(123);
// })
// $(".box").on("mouseover mousedown",function(){
// console.log("123");
// })
// $(".box").on("mouseover",function(){
// console.log("mouseover");
// }).on("mousedown",function(){
// console.log("mousedown");
// })
// let res = $(".box").eq(0);
// // console.log(res.on);
// // res.on();
// res.on("click",function(){
// console.log(123);
// })
// 回滚
// $("div").eq(0).eq(0).end().end().on("click",function(){
// console.log(123);
// })
// let res = $("div").eq(0).eq(0);
// console.log(res);
// $("div").css({width:"100px",height:"100px",background:"blue"});
// let res = $("div").css("background");
// console.log(res);
// $("div").css("background","black");
// $("div").css({width:100,height:"100px",background:"red",opacity:.3});
$.cssHooks.wh = {
get(ele){
console.log("get",ele);
return getComputedStyle(ele,null)['width'] + "-" + getComputedStyle(ele,null)['height'];
},
set(ele,styleValue){
console.log("set",ele,styleValue);
ele.style['width'] = styleValue;
ele.style['height'] = styleValue;
}
}
// $("div").css("wh","300px");
// let res = $("div").css("wh");
// console.log(res);
$("div").css("wh","300px");
// jq-->js框架
// 一、原生实现如下功能??[fn1,fn2...]
// $("button").click(()=>{});
// $("button").click(() => {
// console.log(123);
// })
// console.log($("button"));
// $("button").click(()=>{
// console.log(123);
// })
// console.log(document.querySelectorAll("button"));
// console.log(document.querySelector("button"));
// $(document.querySelector("button")).click(() => {
// console.log(123);
// })
// $("button").on("mouseover mousedown", () => {
// console.log("执行了");
// })
// $("button").eq(1).eq(0).on("click",function(){
// console.log("click");
// })
// console.log($("button").eq(0).eq(0));
// $("button").eq(0).eq(0).end().end().on("click",function(){
// console.log("click");
// })
// let res = $("div").css("background");
// console.log(res);
// 外部扩展
// $.cssNumber.wh = true;
// $(".box").css("background","blue");
// $(".box").css({"opacity":0.4});
// $.cssHooks.wh = {
// get(ele) {
// // console.log(ele);
// return getComputedStyle(ele, null)['width'] + "-" + getComputedStyle(ele, null)['height'];
// },
// set(ele, styleValue) {
// ele.style['width'] = styleValue;
// ele.style['height'] = styleValue;
// }
// }
// // let res = $(".box").css("wh") // get
// // console.log(res);
// $(".box").css("wh", "200px");
// 作业:实现一个aniamte ; 不基于库或者插件
$("button").click(function(){
// slow fast nomal
// $("div").animate({width:"300px"},2000,function(){
// console.log("运动完成");
// });
$("div").animate({width:"300px"},function(){
console.log("运动完成");
})
})
</script>
</html>
myjq.js
js
// function $(arg){
// return {
// click(cb){
// document.querySelector(arg).onclick = cb;
// }
// }
// }
// const config = {
// animationIterationCount: true,
// columnCount: true,
// fillOpacity: true,
// flexGrow: true,
// flexShrink: true,
// fontWeight: true,
// gridArea: true,
// gridColumn: true,
// gridColumnEnd: true,
// gridColumnStart: true,
// gridRow: true,
// gridRowEnd: true,
// gridRowStart: true,
// lineHeight: true,
// opacity: true,
// order: true,
// orphans: true,
// widows: true,
// zIndex: true,
// zoom: true
// }
class Jq{
constructor(arg,root){
if(typeof root === "undefined"){
this['prevObject'] = [document];
}else{
this['prevObject'] = root;
}
// 通过类型区分不同的情况分别处理
if (typeof arg === 'string') {
// 字符串情况
// this[0] = document.querySelector(arg);
let eles = document.querySelectorAll(arg);
// 多个元素保存
this.#addEles(eles);
} else if (typeof arg === 'function') {
// 函数
document.addEventListener("DOMContentLoaded", arg);
} else {
// 对象
if (typeof arg.length === 'undefined') {
// 一个节点
this[0] = arg;
this.length = 1;
} else {
// 多个节点
this.#addEles(arg);
}
}
}
#addEles(eles){
// console.log(eles)
for(let i=0;i<eles.length;i++){
this[i] = eles[i];
}
this.length = eles.length;
}
click(fn) {
// 多个元素绑定
for (let i = 0; i < this.length; i++) {
this[i].addEventListener("click", fn);
}
// this[0].addEventListener("click",fn);
}
on(eventName, fn) {
let eventArr = eventName.split(" ");
// 多层循环
// 多个元素
for (let i = 0; i < this.length; i++) {
// 多个事件
for (let j = 0; j < eventArr.length; j++) {
this[i].addEventListener(eventArr[j], fn);
}
}
return this;
}
eq(index) {
// 对象不变链式
// return this;
// 对象有改变
return new Jq(this[index], this);
}
end() {
return this['preObject'];
}
css(...args) {
// console.log(arguments)
//不定参问题
if (args.length === 1) {
// 1、3 情况
if (typeof args[0] === 'string') {
// 1情况
return this.#getStyle(this[0], args[0]);
} else {
// 3情况 对象 多个节点 多个样式
for(let i=0;i<this.length;i++){
for(let j in args[0]){
this.#setStyle(this[i],j,args[0][j]);
}
}
}
} else {
// 2情况 字符串
for(let i=0;i<this.length;i++){
this.#setStyle(this[i],args[0],args[1]);
}
}
}
#getStyle(ele, styleName) {
// 调取cssHooks里的 get
if(styleName in $.cssHooks){
return $.cssHooks[styleName].get(ele);
}
return getComputedStyle(ele, null)[styleName];
}
#setStyle(ele,styleName,styleValue){
// console.log(styleName in $.cssNumber);
if(typeof styleValue === "number" && !(styleName in $.cssNumber)){
styleValue = styleValue + "px";
}
// 调取cssHooks里的 set
if(styleName in $.cssHooks) {
$.cssHooks[styleName].set(ele,styleValue);
}
ele.style[styleName] = styleValue;
}
animate(...args){
let timer = 500;
if(typeof args[1] !== "function"){
if(typeof args[1] === 'string'){
switch( args[1]){
case 'slow':
timer = 1000;
break;
case 'fast':
timer = 200;
break;
case 'nomal':
timer = 600;
break;
}
}else if(typeof args[1] === "number"){
timer = args[1];
}
}
let timerSecond = timer/1000 + "s";
for(let i=0;i<this.length;i++){
this[i].style.transition = timerSecond+' all';
for(let j in args[0]){
this.#setStyle(this[i],j,args[0][j]);
}
}
if(typeof args[args.length-1] === "function"){
document.addEventListener("transitionend",args[args.length-1]);
}
}
}
function $(arg) {
return new Jq(arg);
// return {
// click(fn){
// document.querySelector(arg).onclick = function(){
// fn && fn();
// // fn();
// }
// }
// }
}
// 给未来扩展 对外暴露了配置
$.cssNumber = {
animationIterationCount: true,
columnCount: true,
fillOpacity: true,
flexGrow: true,
flexShrink: true,
fontWeight: true,
gridArea: true,
gridColumn: true,
gridColumnEnd: true,
gridColumnStart: true,
gridRow: true,
gridRowEnd: true,
gridRowStart: true,
lineHeight: true,
opacity: true,
order: true,
orphans: true,
widows: true,
zIndex: true,
zoom: true
}
$.cssHooks = {};
// fn && fn() 等同于下面
// if(fn){
// fn();
// }
function $(arg){
return new Jq(arg);
}
总结
类及对象
链式调用
对象的包装
拓展功能