一、面向对象之实现自己的库
1. 课程主题 & 知识点
课程主题:
- 定义函数&返还jQ对象
- ready方法和原生节点处理
- 选择器的封装
- 封装jQ的eq方法和click方法
- jQ的链式操作
- 封装jQ的CSS方法
- cssHooks的扩展功能
知识点:
- 对象成员&类成员
- 判断类型
- 链式调用实现
- 正则表达式
2. jQ的特性说明 & 编码
2-1.如何实现选择器$('XXX')及click方法?以及抽象改写
// 原生js
document.querySelector(".box").onclick = function(){
console.log("click");
}
// jq 【选择器$(“.box”) , click+方法】
$(".box").click(function(){
console.log("click");
})
例:$(".box").click()
$(".box")称函数执行,对象可以使用点点方式,obj.name , obj.click()等等
function $(arg){//“.box”
return { //返还一个对象,能不能抽出-类这种形式?
click(cb){
document.querySelector(arg).onclick = cb;
}
}
}
//对象复用性不强,改写如上方法,抽离成类!(类--实例化后-就是对象)
class JQ {//类
constructor(arg) {
this.ele = document.querySelector(arg);
}
click(cb) {
this.ele.addEventListener("click", cb);
}
}
function $(arg) {
return new JQ(arg);//类的实例化
}
2-2.选择器点多种情况处理?
// 选择器的多种情况处理??(1.参数不同,2.多个元素的处理情况)
$(document.querySelector("div")).click(()=>{
console.log(111);
})
$(".box").click(function(){
console.log("click");
})
$(function(){
console.log("加载完毕");
})
2-3.多元素多事件多处理? click、mouseOver等
$(".box").on("click",function(){
console.log("click");
})
$(".box").on("mouseover mousedown",function(){
console.log("123"); //空格作为链接
})
// 多种情况处理 ?
// --> 多种情况间的异同区分开,判断&处理。多个元素、事件:循环绑定
// 引出链式操作 :return this;
$(".box").on("mouseover",function(){
//都是一个对象 $(‘.box’)
console.log("mouseover");
}).on("mousedown",function(){
console.log("mousedown");
})
})
//多节点,多事件,所以是双循环
on(eventName,cb){
let eventArr = eventName.split(" ");
// 针对多个节点绑定多个事件
// console.log(eventArr);
for(let i=0; i<this.length; i++){
for(let j=0; j<eventArr.length; j++){
this[i].addEventListener(eventArr[j],cb);
}
}
// 可以继续on链式操作,加return this(表示操作对象)
return this;
}
2-4.链式操作
如何实现链式调用?
根据对象的特性,返还jq对象;
- 返还this对象
- 返还实例化对象
//1.返还this及返还实例化对象(只能操作, 之前操作的对象)如下:
$("div").on("click",function(){ //操作是div
console.log(111);
}).eq(0).on("click",function(){ //操作对象还是div
console.log(222);
})
$("div").eq(0).on("click",function(){
console.log(111);
})
let res = $("div").get(0);
console.log(res);
// 2.链式回滚 end
$("div").eq(0).eq(0).end().end().on("click",function(){
console.log(123);
})
let res = $("div").eq(0).eq(0);
console.log(res);
记录保持上次节点:
eq(index){
//return this[index]; 拿到的是原生节点,不包含on等方法
return new Jq(this[index],this);
//返回了新的Jq对象
}
end(){
return this['prevObject'];
}
get(index){
return this[index];
}
2-5.css方法实现
// 1.对象传入 修改样式
$("div").css({width:"100px",height:"100px",background:"red"});
// 2.字符串参数
$("div").css("background","blue");
// 3.获取样式
let res = $("div").css("background");
console.log(res);
// 不定参
// 区分特新分开处理(多次判断);
css(...args){
// console.log(arguments) //打印隐藏参数
// console.log(args);
// 区分不同情况分别处理
if(args.length===1){
//1、一个参数:对象和字符串情况;
if(typeof args[0] === "object"){
// 1 设置多个样式 【对象传入 修改样式】
//$("div").css({width:"100px",height:"100px",background:"red"});
for(let i=0;i<*this*.length;i++){
for(let j in *args*[0]){// 多个元素
this.#setStyle(this[i], j, args[0][j]);
}
}
}else{
//3 获取一个样式:多个元素只会获取第一个元素样式 【获取样式】
//let res = $("div").css("background");
return this.#getStyle(this[0],args[0])
}
}else{
// 2、两个参数 :设置一个样式 【字符串参数】
// $("div").css("background","blue");
// 多个元素设置一个样式
for(let i=0;i<this.length;i++){
this.#setStyle(this[i], args[0], args[1]);
}
}
return this;
}
2-6.提高扩展性 wh: “px”
.cssNumber.wh = true;
$("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");
#getStyle(ele, styleName){
if(styleName in $.cssHooks){
return $.cssHooks[styleName].get(ele);
}
return getComputedStyle(ele, null)[styleName];
}
#setStyle(ele, styleName, styleValue){//提高扩展性
if(typeof styleValue === "number" && !$.cssNumber[styleName]){
styleValue = styleValue + "px";
}
if(styleName in $.cssHooks){
$.cssHooks[styleName].set(ele, styleValue);
}
ele.style[styleName] = styleValue;
}
$.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 = {};
function $(arg){
return new Jq(arg);
}
2-7.课后练习
(1)实现一个animate方法?
$("button").on("click",function(){
$(".box").animate({width:"600px"},function(){
console.log("运动完成");
});
})
//封装:编码
//自定义动画函数
animate(...args) {
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";
console.log(...args); //{width:"300px"},function(){console.log("运动完成"); }
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]);
}
}
console.log(this); //0:div.box 1:div.box
//最后一个参数的函数,动画完成之后—执行函数
if (typeof args[args.length - 1] === "function") {
document.addEventListener("transitionend", args[args.length - 1]);
}
}
(2)Deferred?
// 作业:实现一个aniamte ; 不基于库或者插件
$("button").click(function(){
// slow fast nomal
// $("div").animate({width:"300px"},2000,function(){
// console.log("运动完成");
// });
$("div").animate({width:"300px"},function(){
console.log("运动完成");
})
})