zoukankan      html  css  js  c++  java
  • Python-JS事件与面向对象操作

    目录
    一、函数高级
    循环绑定:
    使用循环绑定会出现的问题及解决方案:

    二、面向对象
    3、构造函数(ES5)

    三、JS选择器
    1、getElement系列(最严谨)
    2、querySelector系列(最方便)
    3、通过id名直接获取
    4.JS中操作页面标签全局属性,映射到HYML中

    四、JS中的事件(基础)

    五、 JS处理操作页面:
    1.操作页面内容:
    2.操作页面样式
    这篇博客我们先将上篇博客中没有介绍完的函数部分介绍完,然后再介绍函数高级

    一、函数高级
    1、函数回调

    函数回调的本质:在一个函数中(调用函数),当满足一定条件,调用参数函数(回调函数)

    回调函数作为调用函数的参数传入

    回调函数通过参数将调用还是内部数据传出

    // 回调的函数
    function callback(data) {}
    // 逻辑函数
    function func(callback) {
       // 函数回调
       if (callback) callback(data);
    }

    2、闭包函数

    什么是闭包: 局部的函数 (被一个函数包裹的函数)

    为什么使用闭包:

    1.一个函数要使用另一个函数的局部变量

    2.闭包会持久化包裹自身的函数的局部变量

    3.解决循环绑定

    闭包目的:不允许提升变量作用域时,该函数的局部变量需要被其他函数使用
    闭包本质:函数的嵌套,内层函数称之为闭包
    闭包的解决案例:①影响局部变量的生命周期,持久化局部变量;②解决变量污染

    闭包的模板示例:

    function outer() {
       var data = {}
       function inner() {
           //1.在inner函数中,使用了outer的局部变量num
           return data;
      }
       return inner;
    }
    //2.借助闭包,将局部变量data的生命周期提升了
    var innerFn=outer()
    var data=innerFn()
    循环绑定:
    .html文件
    <ul>
    <li>列表项</li>
    <li>列表项</li>
    <li>列表项</li>
    </ul>
    循环绑定:

    .js文件
    var lis = document.querySelector('li');
    for (var i = 0; i < lis.length; i++) {
    lis[i].onclick = function () {
    // 打印列表项的索引
    console.log(i);
    }
    }
    使用循环绑定会出现的问题及解决方案:
    出现的问题: 变量污染
    例如:
    在这里使用var来循环绑定的时候,没有办法产生局部作用域,所以每次产生的i值都会被下一次的新i值所替代,就会导致每个块的点击事件中的i值都是一样的,也就是每个点击事件的序号或者说index都是一样的,这就是我们所说的变量污染

    for (var i = 0; i < divs.length; i++) {
    // i = 0 | 1 | 2 | 3
    // 循环绑定
    divs[i].onclick = function () {
    console.log("***", i)
    }
    }
    // i = 3
    console.log(">>>", i);
    解决方案:
    1.获取局部作用域(块级作用域)解决
    使用块级作用域来解决变量污染的问题, 原理就是使得每次循环都产生新的块级作用域, 在本次循环中的i值只在产生它的作用域中能够被访问到, 在作用域外面是访问不到的, 这就解决了每次i 的值都被覆盖的情况, 采用这种办法可以解决变量污染的问题

    for (let i = 0; i < divs.length; i++) {
    // {i=0 <= i} {i=1 <= i} {i=2 <= i}
    // i = 3
    // 循环绑定
    divs[i].onclick = function () {
    console.log("***", i)
    }
    } // for运行结束, i=3会被销毁
    console.log(">>>", i)
    2.利用闭包解决循环绑定中的变量污染问题

    // 使用闭包解决变量污染的格式一(比较明了)
    for (var i = 0; i < divs.length; i++) {
    (function () {
    var index = i;
    divs[index].onclick = function () {
    console.log("###", index)
    }
    })()

    // 使用闭包解决变量污染的格式二(格调高一点)
    /*
    (function (index) {
    divs[index].onclick = function () {
    console.log("###", index)
    }
    })(i)
    */

    // 使用闭包解决变量污染的格式三(格局更明显)
    /*
    (function (i) {
    divs[i].onclick = function () {
    console.log("###", i)
    }
    })(i)
    */
    }

    3.利用标签属性解决

    在循环的时候直接将本次循环的 i 值添加给标签的index属性, 这样每次循环都能给不同的标签添加不同的 i 值,从而进行区分 解决变量污染的问题

        for (var i = 0; i < divs.length; i++) {
            divs[i].index = i;
            divs[i].onclick = function () {
                // console.log("###", i)
                console.log(this.index)
            }
        }
    二、面向对象
    对象: 特征与行为的结合体, 是一个具象的实体

    JS对象语法:

    //单一对象
    var obj={
       // 属性(以key="value"的形式存在)
       name:"Zero",
       // 方法
       teach:function(){
           console.log("教学");
      }
    }

    // 对象使用属性与方法, 采用.语法
    console.log(obj.name);
    obj.teach();

    1、属性与方法(都是以key:"value"的形式存在的)

    1.1 key的类型为字符串类型

    在访问的时候,可以使用下面两种方式: obj.key  |  obj["key"]

    js支持的标识符可以省略引号,反之不可以省略, 不支持的标识符访问方式: 不可以采用点语法,需要采用[ ]语法, eg: obj["background-color"]

    var obj = {
    name: "name",
    "person-age": 18
    }

    // 访问
    obj.name | obj["name"]
    obj.["person-age"]
    1.2 对象可以任意添加或删除属性

    拓展: 获取的页面元素就是标签对象, 可以对其添加任意属性

    var obj = {}; | var obj = new Object();
    // 属性
    obj.prop = "";
    // 方法
    obj.func = function () {}
    // 删除属性与方法
    delete obj.prop
    delete obj.func
    // 添加
    obj.age = 18 //如果age的key已存在就是修改, 不存在就是添加键值对, 添加的key任意
    // 注: 获取的页面元素(标签对象)也可以任意添加/删除 属性
    2、类字典结构使用

    结构
    var dict = {name: "zero", age: 18}
    拓展
    var dict = {"my-name": "zero", fn: function () {}, fun () {}}
    使用
    dict.name | dict["my-name"] | dict.fn()
    3、构造函数(ES5)
    声明与普通函数一样,只是函数采用大驼峰体命名规则

    构造函数内部属性方式不同于普通函数

    ES5中还没有引入类的概念, 所以使用构造函数来模拟类的存在

    我们目前一般都是使用ES5中的构造函数来当做类的使用

    function People(name, age) {  //类似于python中的类来使用
       this.name = name;  //this代表 Person构造函数实例化出的所有具体对象中的某一个
       this.age = age;
       this.eat = function () {
           return 'eat';
      }
    }
    如何使用构造函数中的属性与方法

    //1.通过构造函数实例化出具体对象
    //2.通过对象.语法调用属性与方法
    var p1 = new Person('allen',18);
    var p2 = new Person('eric',19);
    console.log(p1.name)
    console.log(p2.name)
    p1.eat();
    p2.eat();
    4、继承(ES5)

    定义一个父级

    // 父级
    function Sup(name) {
       this.name = name;
       this.fn = function () {
           console.log('fn class');
      }
    }
    // 原型
    console.log(Sup.prototype);
    console.log(sup.__proto__);
    // 子级
    function Sub(name) {
       // 继承属性
       Sup.call(this, name);
    }
    // 继承方法
    Sub.prototype = new Sup;
    // 创建子级对象
    var sub = new Sub("subClass");
    // 使用属性
    console.log(sub.name);
    // 使用方法
    sub.fn();

    // 指向自身构造函数
    Sub.prototype.constructor = Sub;
    5、类及继承(ES6)

    // 父类
    class People {
       // 构造器: 完成对象的声明与初始化
       // 属性在构造器中声明并完成初始化
       constructor (name, age) {
           this.name = name;
           this.age = age;
      }
       // 类中规定实例方法
       eat () {
           console.log('吃吃吃');
      }
       // 类方法: 给类使用的
       static create () {
           console.log('诞生');
      }
    }
    // 子类(使用extends继承父类)
    class Student extends People {
       constructor (name, age) {
           // super关键词
           super(name, age)
      }
    }
    ES6中类的使用:

    //1.实例化类的对象
    let p1=new People('嘿嘿');
    //2.使用属性与方法
    console.log(p1.name)
    p1.eat()
    ES6中的类方法介绍:
    类方法一般是由类来直接进行调用的,不建议使用由类实例化出的对象来调用,因为一般类方法都是一些功能类(工具类)的方法
       

    class Tool {  // 功能类(工具类)中的方法都定义为类方法
            static max (num1, num2) {
                return num1 > num2 ? num1 : num2;
            }
        }
        // 通过Tool类来求两个数中的大值, 需要Tool类的对象出现吗? 不需要 => 功能有类直接使用
        console.log(Tool.max(666, 888));

    JS中的主动抛异常

    throw "自定义异常";
    onsole.log("上面如果出现了异常, 逻辑将会被强制停止,后边的代码不会被执行");
    var num = 10 / 0;
    console.log(num)
    三、JS选择器
    什么是js选择器: 将js与html建立起连接

    js中一般称标签为页面元素

    我们这小节中涉及到的几个对象名词的范围大小:
    window > document  > html > body

    window不仅包括显示页面中的所有内容,还包括窗口上方的内容

    所有显示页面中的内容(展现给用户 看的),都是属于文档(document)对象的内容,包括<!doctype html>

    在文档中(document)中出现的所有内容都是document中的节点

    HTML包括html标签内的所有内容

    body包括bady标签内的所有内容

    节点(了解):在文档(document)中出现的所有内容都是document中的节点

    节点(node): 标签节点(元素element) | 注释节点 | 文本节点 | <!doctype>节点

    标签节点指的是一个完整的标签
    文本节点指的是标签之间的空白符合字符(包括两个标签之间的空白符)

    1、getElement系列(最严谨)
    该选择器是动态的:  当元素有变化时,会自动识别
    获取文档中的标签 => document对象通过点语法去获取具体的目标标签元素

    getElement选择标签的方法:
    1.通过id名获取页面中出现的第一个唯一满足条件的页面元素

    该方法只能由document调用
    原因: 我们要保证一个文档中一个id只能出现一次,doctument检索的就是文档
    而某父级标签只能检索自身内部区域,doctument可以保证文档中只能是一个id,而父级标签只能检索自身标签内部区域,documtnt可以保证文档中自身内部id不重复,能不能保证与外界不重复?
    答案是不能的, 所以从安全角度出发,获取唯一对象的getRlementByID方法只能由能确定唯一id的对象来调用,能被document调用,不能被sup来调用

    var body = document.getElementById('id名');

    console.log(body)
     2、通过class名获取所有满足条件的页面元素

    该方法可以由document及任意页面元素对象调用
    返回值为HTMLCollection (一个类数组结果的对象,使用方式同数组)
    没有匹配到任何结果返回空HTMLCollection对象 ([])
    取到列表之后可以使用索引来取到我们需要的相应元素
    var divs = document.getElementsByClassName('class名');

    console.log(divs)
    3.通过tag(标签)名获取所有满足条件的页面元素

    该方法可以由document及任意页面元素对象调用
    返回值为HTMLCollection (一个类数组结果的对象,使用方式同数组)
    没有匹配到任何结果返回空HTMLCollection对象 ([])
    取到列表之后可以使用索引来取到我们需要的相应元素
    document.getElementsByTagName('tag名');
     

    2、querySelector系列(最方便)
    参数里边是采用css选择器的语法
    对id检索是不严谨的

    querySelector选择标签的方法:

    1.获取第一个匹配到的页面元素

    该方法可以由document及任意页面对象调用/
    var div = document.querySelector('css语法选择器');
    console.log(div)
    2.获取所有匹配到的页面元素(检索所有满足结果)

    该方法可以由document及任意页面对象调用
    返回值为NodeList (一个类数组结果的对象,使用方式同数组)
    取到列表之后可以使用索引来取到我们需要的相应元素
    没有匹配到任何结果返回空NodeList对象 ([])
    参数中也是采用css选择器的语法
    var divs = document.querySelectorAll('css语法选择器');
    console.log(divs)
    3、通过id名直接获取
    可以通过id名直接获取对应的页面元素对象,但是不建议使用

    如使用console.log(id名)可以直接进行打印
    4.JS中操作页面标签全局属性,映射到HYML中
    // 获取页面标签ele的alert全局属性的值,如果没有该全局属性结果为null
    ele.getAttribute("alert")

    ele.setAttribute("att_key","attr_value");
    //页面标签ele已有该全局属性,就是修改值, 没有就是添加该全局属性并赋相应值
    注: 一般应用场景,结合css的属性选择器完成样式修改
    四、JS中的事件(基础)
    什么是事件: 页面标签在满足某种条件下可以完成指定功能的这种过程,称之为事件

    某种条件: 如鼠标点击标签: 单击事件 |  鼠标双击标签: 双击事件 | 鼠标悬浮标签: 悬浮事件 | 键盘按下: 键盘按下事件

    指定功能: 开发者根据实际需求完成相应的功能实现

    钩子函数: 就是满足某种条件被系统回调的函数(完成指定功能)

    点击事件: 明确激活钩子的条件= 激活钩子后该处理什么逻辑指定完成功能

    事件使用简单案例:

    var div = document.querySelector(".div"); // 找到的是第一个.div
    div.onclick = function () {
    // alert(123)
    this.style.backgroundColor = "pink";
    }

    // 明确第一个及第二个
    var divs = document.querySelectorAll('.div');
    divs[1].ondblclick = function () {
    divs[0].style.backgroundColor = "yellow";
    }
    事件使用案例:(事件控制标题栏)

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>js事件控制标题栏</title>
    <style>
    .part1 div {
    100px;
    height: 30px;
    text-align: center;
    line-height: 30px;
    float: left;
    cursor: pointer;
    }
    .part1 {
    overflow: hidden;
    }
    h2 {
    height: 30px;

    }
    </style>
    </head>
    <body>
    <div class="part1">
    <div class="b1">标题栏</div>
    <div class="b2">标题栏</div>
    <div class="b3">标题栏</div>
    <div class="b4">标题栏</div>
    </div>
    <h2></h2>
    </body>

    </html>
    第一种方式:使用事件一步一步实现

    <script>
    var b1 = document.querySelector('.b1');
    // 鼠标悬浮事件
    b1.onmouseenter = function () {
    console.log("鼠标悬浮上了");
    // 悬浮上后,该标签的字体颜色变化橘色
    this.style.color = "#FF6700";
    }
    // 需求并非为鼠标移走,去除颜色
    b1.onmouseleave = function () {
    this.style.color = "#000";
    }
    </script>
    第二种方式:
    使用循环绑定的方式进行多个标题的控制

    在这里使用var和let进行循环绑定时的区别:
    var是没有块级作用域的概念的,也就是说在这里使用var进行循环绑定,i 的值在循环外边也是可以访问的,在循环的时候就会不断被修改,在本题中,i 的值最终会被修改为4

    使用let的时候let具有块级作用域的概念,在每次循环都是会产局部作用域的,在局部作用域中产生的变量,在外部不能被访问的,所以使用了let之后,每次循环 i 的值都是新的,这就简单解决了变量污染的问题

    在这里还要注意在JS中函数的定义和调用不是严格遵守先定义后调用的原则的, 它交给浏览器解析的时候会有一个编译过程,会将文档中产生的所有名称存放起来,所以在函数定义的上边进行函数的调用也是没有问题的,在编译过程结束之后才会执行函数里边的代码体

    <script>
    // 制作数据
    var data = ["标题1", "标题2", "标题3", "标题4"];

    var divs = document.querySelectorAll('.part1 div');
    console.log(divs);

    // 循环绑定 => 会出现变量(i)污染
    for (let i = 0; i < divs.length; i++) {
    divs[i].onmouseenter = function () {
    // 打印自身索引值
    console.log(i);
    // 将自身颜色变为橘色,其他兄弟颜色变为黑色
    // 就是i为橘色, 非i为黑色
    changeColor(i);

    // 悬浮内容
    changeContent(i)
    }
    }
    // console.log(i);

    // 自定义的修改颜色的方法
    function changeColor(index) {
    for (let i = 0; i < divs.length; i++) {
    // 先不管三七二十一,全改成黑色
    divs[i].style.color = "black";
    // 如果是目标选中标签,它的颜色再重新设置为橘色
    if (i == index) {
    divs[i].style.color = "#FF6700";
    }
    }
    }

    var h2 = document.querySelector('h2');
    // 修改内容
    function changeContent(index) {
    h2.innerText = data[index];
    }

    </script>
    五、 JS处理操作页面:
    在进行页面操作之前,必须要先获取页面元素:
    比如我们通过类名获取元素:

    var d1 = document.querySelector('.d1');
    var d2 = document.querySelector('.d2');
    var d3 = document.querySelector('.d3');
    1.操作页面内容:
    innerText是获取文本内容的

     box.innerText
     可以设值, 也可以获取值
        var text = d1.innerText;
        // 获取内容
        console.log(text);
        // 修改(删除)内容
        d1.innerText = "";
        d1.innerText = "修改后的文本内容";
    读写 style属性 样式

    d1.style.backgroundColor = 'red';
    // 1.操作的为行间式
    // 2.可读可写
    // 3.具体属性名采用小驼峰命名法
     

    ② 操作标签内容

    box.innerHTML
    可以设值, 也可以获取值, 能解析html语法代码
    box.outerHTML
    获取包含自身标签信息的所有子内容信息
      // 获取
        var html = d2.innerHTML;
        console.log(html)
        // 修改
        d2.innerHTML = "<b>加粗的文本</b>";  // 可以解析html语法的代码
        // d2.innerText = "<b>加粗的文本</b>";

        // 了解
        console.log(d2.innerHTML);  // 只是标签内部的子标签与子内容
        console.log(d2.outerHTML);  // 不仅包含标签内部的子标签与子内容,还包含自身标签信息
    2.操作页面样式
    1.获取 页面样式

        var bgColor = d3.style.backgroundColor;  // 只能获取行间式
        console.log(bgColor);
    2. 修改

    d3.style.backgroundColor = "yellow";  // 只能修改行间式
    行间式的我们可以进行修改了,那问题就来了

    问题: 那用内联外联设置的样式如何获取?
    内联与外联设置的样式叫: 计算后样式
    getComputedStyle(目标标签, 伪类(null填充)).具体的样式

    bgColor = window.getComputedStyle(d3, null).backgroundColor;  // 兼容性较差
    console.log(bgColor);

    // 可以获取计算后样式, 也可以获取行间式, 但它为只读
    bgColor = getComputedStyle(d3, null).getPropertyValue('background-color');  // 兼容性较好
    console.log(bgColor);

    // 一些不常用的属性会出现浏览器之间的兼容问题, 通过添加前缀来处理
    console.log(d3.style);
    // chrome: -webkit-
    // ie: -ms-
    // opera: -o-
     

    // eg: 背景颜色
    // 推荐
    getComputedStyle(页面元素对象, 伪类).getPropertyValue('background-color');
    // 不推荐
    getComputedStyle(页面元素对象, 伪类).backgroundColor;

    // IE9以下
    页面元素对象.currentStyle.getAttribute('background-color');
    页面元素对象.currentStyle.backgroundColor;

    // 1.页面元素对象由JS选择器获取
    // 2.伪类没有的情况下用null填充
    // 3.计算后样式为只读
    // 4.该方式依旧可以获取行间式样式 (获取逻辑最后的样式)
    操作样式小结:

    box.style.样式名  ==> 可以设值,也可以获取,但操作的只能是行间式
    getComputedStyle(box, null).样式名 ==> 只能获取值,不能设值, 能获取所有方式设置的值(行间式 与 计算后样式)
    注: 获取计算后样式,需要关注值的格式
    结合 css 操作样式

      页面元素对象.className = "";  // 清除类名
      页面元素对象.className = "类名";  // 设置类名
      页面元素对象.className += " 类名";  // 添加类名
    ---------------------
    原文:https://blog.csdn.net/Onion_cy/article/details/85101977
  • 相关阅读:
    Action<T>和Func<T>委托
    异步委托学习笔记
    .Net身份验证里边的几个基本概念(转)
    线程和进程
    WebClient类的使用
    关于NHibernate的更新和读取操作,及碰见的一点问题
    ASP.NET MVC 中将数据从View传递到控制器中的三种方法(表单数据绑定)
    LINQ标准查询操作符学习笔记
    C#3.0中的扩展方法
    NHibernate中的一对多映射
  • 原文地址:https://www.cnblogs.com/du-jun/p/10171116.html
Copyright © 2011-2022 走看看