Javascript 使用 classList.add 时“无法读取属性 'classList' of null”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29942098/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 04:22:08  来源:igfitidea点击:

"Cannot read property 'classList' of null" when using classList.add

javascripttwitter-bootstrapclassiejs

提问by bpunzalan

I am having this error, but since I am not familiar with the code. It came from a theme in startbootstrap (Creative). The file is

我有这个错误,但因为我不熟悉代码。它来自 startbootstrap (Creative) 中的一个主题。该文件是

classie.js

类.js

code:

代码:

/*!
 * classie - class helper functions
 * from bonzo https://github.com/ded/bonzo
 * 
 * classie.has( elem, 'my-class' ) -> true/false
 * classie.add( elem, 'my-new-class' )
 * classie.remove( elem, 'my-unwanted-class' )
 * classie.toggle( elem, 'my-class' )
 */

/*jshint browser: true, strict: true, undef: true */
/*global define: false */

( function( window ) {

'use strict';

// class helper functions from bonzo https://github.com/ded/bonzo

function classReg( className ) {
  return new RegExp("(^|\s+)" + className + "(\s+|$)");
}

// classList support for class management
// altho to be fair, the api sucks because it won't accept multiple classes at once
var hasClass, addClass, removeClass;

if ( 'classList' in document.documentElement ) {
  hasClass = function( elem, c ) {
    return elem.classList.contains( c );
  };
  addClass = function( elem, c ) {
    elem.classList.add( c );
  };
  removeClass = function( elem, c ) {
    elem.classList.remove( c );
  };
}
else {
  hasClass = function( elem, c ) {
    return classReg( c ).test( elem.className );
  };
  addClass = function( elem, c ) {
    if ( !hasClass( elem, c ) ) {
      elem.className = elem.className + ' ' + c;
    }
  };
  removeClass = function( elem, c ) {
    elem.className = elem.className.replace( classReg( c ), ' ' );
  };
}

function toggleClass( elem, c ) {
  var fn = hasClass( elem, c ) ? removeClass : addClass;
  fn( elem, c );
}

var classie = {
  // full names
  hasClass: hasClass,
  addClass: addClass,
  removeClass: removeClass,
  toggleClass: toggleClass,
  // short names
  has: hasClass,
  add: addClass,
  remove: removeClass,
  toggle: toggleClass
};

// transport
if ( typeof define === 'function' && define.amd ) {
  // AMD
  define( classie );
} else {
  // browser global
  window.classie = classie;
}

})( window );

the error is in:

错误在于:

elem.classList.add( c );

elem.classList.add( c );

I am not familiar with the code written. I include this file together with other js files. And it seems that the other js file needs the variable classie.

我对编写的代码不熟悉。我将此文件与其他 js 文件一起包含在内。似乎另一个 js 文件需要变量classie

EDITED:

编辑:

HERE IS THE ERROR IN CONSOLE:

这是控制台中的错误:

Uncaught TypeError: Cannot read property 'classList' of null
  addClass @ classie.js?nngrmm:33
  scrollPage @ cbpAnimatedHeader.js?nngrmm:30

ALSO, I have an error in bootstrap.js.

另外,我在 bootstrap.js 中有错误。

Uncaught TypeError: $(...).find(...).once is not a function
  Drupal.behaviors.bootstrap.attach @ bootstrap.js?nngrmm:16
  (anonymous function) @ drupal.js?nngrmm:76
  x.extend.each @ jquery.min.js?v=1.10.2:4
  Drupal.attachBehaviors @ drupal.js?nngrmm:74
  (anonymous function) @ drupal.js?nngrmm:412
  x.Callbacks.c @ jquery.min.js?v=1.10.2:4
  x.Callbacks.p.fireWith @ jquery.min.js?v=1.10.2:4
  x.extend.ready @ jquery.min.js?v=1.10.2:4
  q @ jquery.min.js?v=1.10.2:4

Somewhere in here:

这里的某个地方:

/**
 * @file
 * bootstrap.js
 *
 * Provides general enhancements and fixes to Bootstrap's JS files.
 */

var Drupal = Drupal || {};

(function($, Drupal){
  "use strict";

  Drupal.behaviors.bootstrap = {
    attach: function(context) {
      // Provide some Bootstrap tab/Drupal integration.
      $(context).find('.tabbable').once('bootstrap-tabs', function () {
        var $wrapper = $(this);
        var $tabs = $wrapper.find('.nav-tabs');
        var $content = $wrapper.find('.tab-content');
        var borderRadius = parseInt($content.css('borderBottomRightRadius'), 10);
        var bootstrapTabResize = function() {
          if ($wrapper.hasClass('tabs-left') || $wrapper.hasClass('tabs-right')) {
            $content.css('min-height', $tabs.outerHeight());
          }
        };
        // Add min-height on content for left and right tabs.
        bootstrapTabResize();
        // Detect tab switch.
        if ($wrapper.hasClass('tabs-left') || $wrapper.hasClass('tabs-right')) {
          $tabs.on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
            bootstrapTabResize();
            if ($wrapper.hasClass('tabs-left')) {
              if ($(e.target).parent().is(':first-child')) {
                $content.css('borderTopLeftRadius', '0');
              }
              else {
                $content.css('borderTopLeftRadius', borderRadius + 'px');
              }
            }
            else {
              if ($(e.target).parent().is(':first-child')) {
                $content.css('borderTopRightRadius', '0');
              }
              else {
                $content.css('borderTopRightRadius', borderRadius + 'px');
              }
            }
          });
        }
      });
    }
  };

Error in:

错误:

$(context).find('.tabbable').once('bootstrap-tabs', function () {

$(context).find('.tabbable').once('bootstrap-tabs', function () {

Need help. Thanks.

需要帮忙。谢谢。

回答by Ercunningham

I ran into the same issue today but for a different theme and wanted to post my resolution to help others in the future.

我今天遇到了同样的问题,但主题不同,我想发布我的决议以帮助将来的其他人。

The issue is with cbpAnimatedHeader.js file. That file defines the "scrollPage" function, which calls upon the "classie" function. That is why you are initially seeing that the error is with the classie.js file. In the scrollPage function, the variable "header" is used:

问题在于 cbpAnimatedHeader.js 文件。该文件定义了调用“classie”函数的“scrollPage”函数。这就是为什么您最初看到错误与 classie.js 文件有关。在 scrollPage 函数中,使用了变量“header”:

if ( sy >= changeHeaderOn ) {
        classie.add(header, 'navbar-shrink' );
    }
    else {
        classie.remove(header, 'navbar-shrink' );
    }

However, header is not being defined in a way that the scrollPage function can read it. To fix the error, you can either define header globally or within the scrollPage function. I chose to just copy the variable definition into the function. Here's the final result in cbpAnimatedHeader.js:

但是,标头并未以 scrollPage 函数可以读取的方式定义。要修复错误,您可以全局定义标题或在 scrollPage 函数中定义标题。我选择只将变量定义复制到函数中。这是cbpAnimatedHeader.js 中的最终结果:

function scrollPage() {
    var sy = scrollY(),
    header = document.querySelector( '.navbar-fixed-top' );
    if ( sy >= changeHeaderOn ) {
        classie.add(header, 'navbar-shrink' );
    }
    else {
        classie.remove(header, 'navbar-shrink' );
    }
    didScroll = false;
}

回答by punkbyte

I realized that my issue was I moved the cbpAnimatedHeader.js file from the bottom of the body to the head. Because of this, header was null because the html hadn't rendered yet.

我意识到我的问题是我将 cbpAnimatedHeader.js 文件从身体底部移动到头部。因此,header 为空,因为 html 尚未呈现。

Instead of adding the header lookup to the scrollPage function I wrapped the whole thing in a jQuery document ready.

我没有将标题查找添加到 scrollPage 函数中,而是将整个内容包装在一个准备好的 jQuery 文档中。

$(function(){
  var cbpAnimatedHeader = (function() {

      var docElem = document.documentElement,
          header = document.querySelector( '.navbar-fixed-top' ),
          didScroll = false,
          changeHeaderOn = 300;

      function init() {
          window.addEventListener( 'scroll', function( event ) {
              if( !didScroll ) {
                  didScroll = true;
                  setTimeout( scrollPage, 250 );
              }
          }, false );
      }

      function scrollPage() {
          var sy = scrollY();
          header = document.querySelector( '.navbar-fixed-top' );
          if ( sy >= changeHeaderOn ) {
              classie.add( header, 'navbar-shrink' );
          }
          else {
              classie.remove( header, 'navbar-shrink' );
          }
          didScroll = false;
      }

      function scrollY() {
          return window.pageYOffset || docElem.scrollTop;
      }

      init();

  })();
});

回答by tatorface

Adding my solution here as I was getting the exact same error, but it had nothing to do with the actual Classie plugin.

在这里添加我的解决方案,因为我遇到了完全相同的错误,但这与实际的 Classie 插件无关。

I was using the script from here to shrink the upper menu on my site on scroll: http://callmenick.com/post/animated-resizing-header-on-scroll.

我正在使用这里的脚本在滚动时缩小我网站上的上部菜单:http: //callmenick.com/post/animated-resizing-header-on-scroll

I added additional elements to the page that needed the .smallerclass added to them as they would also move up and shrink when scrolled to move up to the smaller menu. I was adding responsive elements as well that were NOT always defined within the given page. That was the problem, I had tried to use the addClass function in Classie on some responsive elements that actually didn't exist when scrolling, so it would throw a handful of these errors each time the page was scrolled.

我向需要.smaller添加类的页面添加了额外的元素,因为当滚动到较小的菜单时,它们也会向上移动和收缩。我也在添加响应元素,这些元素并不总是在给定页面中定义。这就是问题所在,我曾尝试在一些滚动时实际上不存在的响应元素上使用 Classie 中的 addClass 函数,因此每次滚动页面时它都会抛出一些这些错误。

So I implemented a check to make sure the responsive elements exist before attempting to add the .smallerclass to them.

因此,我在尝试将.smaller类添加到响应元素之前进行了检查以确保响应元素存在。

From:

从:

window.addEventListener('scroll', function(e){  
    var header = document.querySelector("header");
    var responsive_element = document.querySelector(".responsive_element"); // responsive, not always on the page

    var distanceY = window.pageYOffset || document.documentElement.scrollTop,
        shrinkOn = 160;

    if (distanceY > shrinkOn) {

        classie.addClass(header,"smaller");
        classie.addClass(responsive_element,"smaller");

    } else {

        if (classie.has(header,"smaller")) {

            classie.removeClass(header,"smaller");
            classie.removeClass(responsive_element,"smaller");

        }

    }

});

To:

到:

window.addEventListener('scroll', function(e){

    var responsive = false; // to find out if we have those missing elements on the page
    var header = document.querySelector("header"); // always exists

    var distanceY = window.pageYOffset || document.documentElement.scrollTop,
        shrinkOn = 160;

    if (document.querySelector(".responsive_element") != null) {    
    responsive = true; // if we are in mobile mode
    }

    // only deal with the mobile element if it exists
    if (responsive) {
    var responsive_element = document.querySelector(".responsive_element");
    } 


    if (distanceY > shrinkOn) {

        classie.addClass(header,"smaller");

        // only add the smaller class if the element exists
        if (responsive) {
        classie.addClass(responsive_element,"smaller");
        }


    } else {

        if (classie.has(header,"smaller")) {

            classie.removeClass(header,"smaller");

            // only remove the smaller class if the element exists
            if (responsive) {
            classie.removeClass(responsive_element,"smaller");
            }

        }

    }

});