开发者问题收集

React web 中的 Javascript 函数调用

2019-02-05
137

我正在尝试从 ReactJS 调用 JS 函数。我将 MyJS.js 文件添加到 ReactJS 项目中。当我在按钮 onClick 中导入并调用 JS 函数时,例如:handleButtonColor 中的 this.abtest.events.on,当我运行 this.abtest.events.on 调用的 React 代码时,它会抛出 Uncaught TypeError: Cannot read property 'events' of undefined

ReactJS:

import file from './MyJS.js';

class App extends React.Component {   
    constructor() {
            super();

            this.handleButtonColor = this.handleButtonColor.bind(this);
         };

        render() {
                    return (
                        <CustomTemplate title="Testing Sample Reference">
                            <Helmet

                            <p><b>Testing Sample Reference A</b></p>

                                <div>
                                    <button id = "expAButton" onClick = {this.handleButtonColor}>Button Experience A</button>
                                    <button id = "expBButton" onClick = {this.handleButtonColor}>Button Experience B</button>
                                </div> 


                        </CustomTemplate>

                    );
                }
                handleButtonColor() {        

                    this.abtest.events.on('start', function (test) {
                        log('[start] sliced into %s for the %s test', test.slice.name, test.name);
                    });
                    this.abtest.events.on('run', function (test) {
                        log('[run  ] "%s" test is using slice %s', test.name, test.slice.name);
                    });

                      this.abtest('expAButton', 0.75).slices('orange', 'blue').run(function () {
                        document.querySelector('#one').classList.add(this.slice.name);
                        document.querySelector('#one').textContent = '#1 ' + this.slice.name;
                      });
                      this.abtest('expBButton').slices('green', 'yellow').run(function () {
                        document.querySelector('#one').classList.add(this.slice.name);
                        document.querySelector('#one').textContent = '#1 ' + this.slice.name;
                      });
                }

JS 代码 (MyJS.js):

(function() {


    var _tests = {};

    var abtest = function (testname, traffic, colorslices) {
      if (_tests.hasOwnProperty(testname)) {
        return _tests[testname];
      }

      if (typeof traffic === 'undefined') {
        traffic = 1;
      }

      _tests[testname] = new Test(testname, traffic);

      if (colorslices && colorslices.length) {
        _tests[testname].slices(colorslices);
      }

      return _tests[testname];
    };


    abtest.clear = function () {
      for (var test in _tests) {
        if (_tests.hasOwnProperty(test)) {
          _tests[test].clear();
        }
      }

      _tests = {};
    };

    abtest.events = new Events();

    abtest.config = {
      STORAGE_PREFIX: 'ab:'
    };

    function Events() {
      this._events = {};
    }

    Events.prototype.trigger = function (name) {
      var args = Array.prototype.slice.call(arguments, 1);

      if (this._events.hasOwnProperty(name)) {
        for (var x = 0, len = this._events[name].length; x < len; x++) {
          this._events[name][x].apply(window, args);
        }
      }
    };

    Events.prototype.on = function (name, callback) {
      if (!this._events.hasOwnProperty(name)) {
        this._events[name] = [];
      }

      this._events[name].push(callback);
    };

    function Slice (name) {
      this.name = name;
    }

    Slice.prototype.toString = function () {
      return this.name;
    };

    Slice.prototype.toJSON = function () {
      return {
        name: this.name
      };
    };

    function Test (name, traffic) {
      this.name = name;
      this.traffic = traffic;
      this.slice = null;
      this.storage = (typeof localStorage === 'undefined') ? null : localStorage;
      this._slices = {};          
      this._storeslice = new Slice();    
    }


    Test.prototype.slices = function (slices) {
      if (this.slice !== null) {
        throw new Error('Attempted to add slices to already running test.');
      }

      if (Object.prototype.toString.call(slices) !== '[object Array]') {
        slices = Array.prototype.slice.call(arguments, 0);
      }

      for (var x = 0, len = slices.length; x < len; x++) {
        this.add(new Slice(slices[x])); // to add slices..
      }

      return this;
    };

    Test.prototype.add = function (slice) {
      this._slices[slice.name] = slice;
      return this;
    };

    Test.prototype.run = function (callback) {
      var slice = this.urlSlice() || this.storedSlice();

      if (slice && this.hasSlice(slice)) {
        this.slice = this.getSlice(slice);
      }

      else if (Math.random() > this.traffic) {
        this.slice = new Slice('commoncolor');
        abtest.events.trigger('start', this);
      }

      else {
        this.slice = this.chooseSlice();
        abtest.events.trigger('start', this);
      }

      // Save the slice to local storage.
      this.storage.setItem(this.key(), this.slice.name);

      if (typeof callback === 'function') {
        callback.call(this);
      }

      abtest.events.trigger('run', this);

      return this;
    };


    Test.prototype.chooseSlice = function () {
      var slices = [];

      // Get an array of all slice names.
      for (var slice in this._slices) {
        if (this._slices.hasOwnProperty(slice)) {
          slices.push(slice);
        }
      }

      if (slices.length === 0) {
        return new Slice('commoncolor');
      }

      var index = Math.floor(Math.random() / (1.0 / slices.length)); // 0.75 - "0.25 / 1 / 2"; 1 - 
      return this.getSlice(slices[index]);
    };

    Test.prototype.hasSlice = function (name) {
      return (name === 'commoncolor' && this.traffic < 1) || this._slices.hasOwnProperty(name);
    };

    Test.prototype.getSlice = function (name) {
      return name === 'commoncolor' ? new Slice('commoncolor') : this._slices[name];
    };

    Test.prototype.urlSlice = function () {
      var hash = window.location.hash;
      var search = window.location.search;
      var match;

      // Matches '<prefix>:<test>=<slice>'
      // TOOO: Improve this regex. Define what a valid slice name is.
      var re = new RegExp('(' + this.key() + ')=([\\w0-9]+)');

      if (match = hash.match(re)) {
        return match[2];
      }
      else if (match = search.match(re)) {
        return match[2];
      }

      return false;
    };

    Test.prototype.storedSlice = function () {
      return this.storage.getItem(this.key());
    };

    Test.prototype.key = function () {
      return abtest.config.STORAGE_PREFIX + this.name;
    };

    Test.prototype.toString = function () {
      return this.key();
    };


    Test.prototype.clear = function () {
      this.storage.removeItem(this.key());
    };


    Test.prototype.style = function (href) {
      var style = document.createElement('link');
      style.rel = 'stylesheet';
      style.href = href;
      document.head.appendChild(style);
      return this;
    };


    Test.prototype.script = function (src, async) {
      var script = document.createElement('script');
      script.type = 'text/javascript';
      script.async = (typeof async === 'undefined') ? true : !!async;
      script.src = src;
      var firstScript = document.getElementsByTagName('script')[0];
      firstScript.parentNode.insertBefore(script, firstScript);
      return this;
    };

    abtest.Test = Test;
    abtest.Slice = Slice;
    abtest.Storage = (typeof localStorage === 'undefined') ? null : Storage;
    abtest.Events = Events;    

    if (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined') {
      module.exports = abtest;
    }
    else if (typeof define === 'function' && define.amd) {
      define('ab', function () {
        return abtest;
      });
    }
    else {
      window.abtest = abtest;
    }

    })();
2个回答

React 语法是错误的,但我假设您只展示了代码的相关部分。

对于您 render() 某些内容,它应该是扩展 React.Component 基类的类。

此外, this 仅限于访问函数执行的动态范围内的值(可以使用 bindcallapply 进行修改)

在您的特定场景中, this.abtest 将未定义。 您可以尝试使用 window.abtest ,因为它作为全局变量添加到您的其他文件中

Dhananjai Pai
2019-02-05

我修复了这个问题。谢谢。我在 JS 顶级函数中使用了导出。并从 React 中导入它。

user1953977
2019-02-07