Javascript学习笔记

Js获取元素的样式

使用Element.Style 和 Window.getComputedStyle

  • Element.Style语法

    1
    2
    3
    4
    5
    let element = document.getElementById("myElement")
    console.log(element.style.width) //获取元素的宽
    element.style.backgroundColor = //设置元素的背景颜色
    element.style.getPropertyValue('margin') //使用getPropertyValue获取元素margin
    element.style.transform = `translateX(${move}px)` //设置元素的属性

    注意: element.style该方法只能设置和修改内联样式,也就是说如果内联样式没有设置width的话,是无法获取到width的,也无法获取实时的width

  • Window.getComputedStyle语法

    1
    2
    let element = document.getElementById("myElement")
    let style = window.getComputedStyle(element,null).width

    注意: 使用getComputedStyle可以在任何情况获取到元素的样式属性,但是却无法修改,如果需要修改只能使用style

js的事件委派

作用: 解决多次绑定事件的性能问题,以及解决新添加的元素绑定的事件无效的问题。(实现是利用冒泡)

原生javascript的事件委派

  • 语法

    1
    2
    3
    4
    5
    6
    7
    8
    <ul id="ul">
    <li>则是li1</li>
    <li>则是li2</li>
    <li>则是li3</li>
    <li>则是li4</li>
    <li>则是li5</li>
    </ul>
    <button>点我添加li</button>
    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
    window.onload = function(){
    let ul = document.getElementById("ul")
    /*
    为ul绑定click事件,委派到里面的li
    其中利用(event.target)
    */
    //方法1:
    ul.addEventListener('click', function(event){
    //判断event.target是否为li,如果为li再做操作
    if(event.target.tagName == 'li'){
    event.target.style.color = 'red'
    }
    })

    //方法2:
    ul.onclick = function(event){
    //判断event.target是否为li,如果为li再做操作
    if(event.target.tagName == 'li'){
    event.target.style.color = 'red'
    }
    }

    //即使新添加的元素也还是可以绑定到事件
    let button = document.getElementsByTagName("button")[0]
    button.onclick = function(){
    let li = document.createElement("li")
    li.innerHtml = "新添加的li"
    ul.appendChild(li)
    }
    }

使用jquery实现事件委派

  • 语法

    1
    2
    3
    4
    5
    6
    7
    8
    <ul id="ul">
    <li>则是li1</li>
    <li>则是li2</li>
    <li>则是li3</li>
    <li>则是li4</li>
    <li>则是li5</li>
    </ul>
    <button>点我添加li</button>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    $(document).ready(function () {
    //这里我们将事件委派document中,当点击ul里的li时才触发事件

    $(document).on('click', '#ul li', function (event) {
    $(this).css("color", 'red')
    })

    //这里是没有使用事件委派的,新添加的li将无法绑定click事件
    $("li").on("click", function () {
    $(this).css("color", 'red')
    })

    $("button").click(function () {
    $('#ul').append("<li>新添加的li</li>")
    })
    })

监听window窗口size的元素的size变化

window.resize实现

相比新的ResizeObserver API,window.resize性能更差,建议使用ResizeObserver

  • 语法

    1
    2
    //监听window窗口的缩放或者改变大小
    window.addEventListener('resize',function(){...})
  • vue监听window.resize改变main的translateX案例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
      //监听窗口改变大小 实时改变label的left
    const container = this.$refs.container;
    const main = this.$refs.main;
    window.addEventListener("resize", function () {
    let mainWidth = main.clientWidth;
    let containerWidth = container.clientWidth;
    let moveWidth = containerWidth - mainWidth;
    if (mainWidth >= containerWidth) {
    console.log("超过");
    this.$set(
    this.mainStyle,
    "transform",
    `translateX(${moveWidth}px)`
    );
    } else {
    this.$set(this.mainStyle, "transform", `translateX(0)`);
    }
    });

    ResizeObserver API实现

    这个方法接受一个参数,即需要监听的元素 element。当元素的尺寸发生变化时,ResizeObserver 会触发回调函数,并将 ResizeObserverEntry 对象作为参数传入。

  • 语法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    let element = document.getElementById("#myElement")
    const resizeObserver = new ResizeObserver((entries)=>{
    for(let entry of entries){
    console.log('Element:', entry.target) //元素的标签名
    console.log('Width:', entry.contentRect.width) //元素的宽
    }
    })

    //使用方法,监听element元素的长度变化
    resizeObserver.observer(element)
  • vue案例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    const container = this.$refs.container;
    const main = this.$refs.main;
    var observer = new ResizeObserver((entries) => {
    for (let entry of entries) {
    // console.log(entry);
    let mainWidth = main.clientWidth;
    let labelWidth = entry.contentRect.width;
    let moveWidth = labelWidth - mainWidth;
    if (mainWidth >= labelWidth) {
    console.log(moveWidth);
    this.$set(
    this.mainStyle,
    "transform",
    `translateX(${moveWidth}px)`
    );
    } else {
    this.$set(this.mainStyle, "transform", `translateX(0)`);
    }
    }
    });
    observer.observe(container);
  • 两个方法

    1. disconnect()方法取消对所有Element的监听

      1
      2
      3
      btn.addEventListener('click', () => {
      resizeObserver.disconnect();
      })
    2. unobserve(target)方法结束对指定Element的监听

      1
      2
      const element = this.$refs.main;
      resizeObserver.unobserve(element)
  • 几个注意的点以及遇到的问题

    • 在vue的mounted中使用

      在组件的生命周期中,mounted钩子函数可能会被多次调用,导致多次创建Observer实例,进而造成了重复输出。你可以在mounted钩子函数中判断Observer实例是否已经被创建,如果已经被创建,就不再进行重复创建。

      简单来说:

    1. 如果在vue中的mounted中使用,最好使用使用this来定义ResizeObserver实例.
    2. 在mounted中创建的ResizeObserver实例,最好在beforeDestroy生命周期钩子中销毁:
      1
      2
      3
      4
      beforeDestroy() {
      this.containerObserver.disconnect();
      this.containerObserver = null;
      }
      这样可以保证在vue开发时,修改程序保存之后,vue热重载之后出现多次调用ResizeObserver的问题。原因可能是因为重载时,mounted会执行一遍之前的实例,之后再创建新的实例,具体原因不明。

获取元素到视口的距离

getBoundingClientRect()

Element.getBoundingClientRect() 方法返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。

  • 语法
    1
    2
    3
    var element = document.querySelector("div")
    var rect = element.getBoundingClientRect()
    console.log(rect.top) //获取元素到视口的top距离

Javascript学习笔记
http://example.com/2023/02/01/Javascript学习笔记/
作者
Mr.H
发布于
2023年2月1日
许可协议