Javascript onload 未触发

嘿,各位,

这可能是一个比较基础的问题,我主要是做后端的。目前我正在尝试将一些 JavaScript 代码连接到前端元素。问题是,我的 window.onload(以及 document.onload,我都试过了)从未触发。我的 JavaScript 位于插件初始化文件夹中:[plugin]/assets/javascripts/initializers/[plugin].js.es6

export default {
  name: "meritmoot",
  initialize() {

    // 我的初始化函数
    function initializeMeritmoot(api) {
      console.log("inside initializeMeritmoot")

      // 按键抬起时执行的函数
      function repInputKeyUp() {
        inputBox = document.getElementById("rep-input")
        console.log("in rep input key up")
        ajax("/reps/search/" + inputBox.value +".json", {type: 'GET'}).then((result) => {
          console.log(result)
          result = JSON.parse(result)
          repList = document.getElementById("rep-list")
          repList.innerHTML = ""
          result.forEach(op => {
            var x = document.createElement("INPUT");
            x.setAttribute("info-tag-id", op.id)
            x.setAttribute("value", op.mm_reference_str)
            repList.appendChild(x)
          });
          console.log(repList)
        });
      };
      console.log("Past Function Def");
      
      // 窗口加载(未发生)
      window.onload = () => {
        console.log("PageLoaded") <-----------------------------------这行从未打印
        document.getElementById('rep-input').onkeyup = repInputKeyUp;
      };
      console.log('leaving initializeMeritmoot');
    }
    console.log("MeritMoot Javascript In Default")
    withPluginApi("0.8.37", api => initializeMeritmoot(api));
  }
};

对于这个问题,大家有什么想法吗?这段 JavaScript 在 Discourse 中的设置是否正确?还是说这是一个通用的 JavaScript 问题?

编辑:尝试使用 addEventListener…

编辑:将 onload 替换为:

  window.addEventListener('onload', function() {
    console.log("PageLoaded")
    document.getElementById('rep-input').onkeyup = repInputKeyUp;
  }, false);

但也没有起作用。

您这里使用的是 EmberJS,而非原生 JavaScript。其行为会有所不同。

最好遵循 EmberJS 的最佳实践。

我建议将您的逻辑附加到现有组件上,或将其添加到插件出口中,并使用 didInsertElement 钩子。

请阅读 EmberJS 指南

3 个赞

谢谢!我注意到 Ember 是 Discourse 的重要组成部分,但没意识到它覆盖了原生功能。我会花时间学习一下。

编辑:我正在使用插件元素 discovery-list-container-top,并连接到 Ruby 后端插件架构。

编辑:ember-rails 和 Discourse 之间有什么关系?Ember 本身似乎是一个全栈环境。查看 GitHub - emberjs/ember-rails: Ember for Rails 3.1+ · GitHub

ember-rails 是一个在 Discourse 中实际使用的 Ruby gem。

Discourse 的工作人员更适合作出评论,但总体而言,EmberJS 负责前端,而 Ruby on Rails 负责后端。当然,Discourse 具有定制架构的元素,其具体配置像任何大型应用一样,至少在某种程度上是独特的。

关于系统运作方式的精彩描述可参见:Creating Routes in Discourse and Showing Data

API 文档位于:https://docs.discourse.org

2 个赞

最近学习了很多 Ember.js 的知识,但看起来是针对错误版本的。据我所知,Discourse 使用的是 Ember.js 1.9(通过查看 ember-rails 文档 和源代码语法可以确认)。Ember.js 的当前版本是 3.17,因此应该参考的指南是 这个。语法差异很大,但我已经掌握了基础知识。完成后,我会将上述代码转换为 Ember.js 版本并发布出来。

2 个赞

在浏览器中运行开发实例时,JavaScript 控制台会显示以下内容:

DEBUG: -------------------------------
DEBUG: Ember  : 3.12.2 
DEBUG: jQuery : 3.4.1 
DEBUG: ------------------------------- 

但你说得对,Discourse 的一些约定并未完全反映指南中的最新语法:slight_smile:

2 个赞

谢谢你的帮助,Robert!有一段时间我确实有点力不从心!无论如何,正如所承诺的,这是最终成果。我最终使用了 onload 函数,它会在 DOM 加载完成后触发。我曾尝试使用 jQuery,但后来听说 Ember.js 正在弃用它。

import { ajax } from 'discourse/lib/ajax';
// 也可以更新高亮逻辑,使其在 split(" ") 时也生效。当然,如果我有这个想法的话。

export default Ember.Component.extend({
  runOnceRan: false,
  myAws: "",
  subbedReps: [],
  // 更新输入框中代表建议选项
  updatePossibles: function (substr) {
    var compContext = this; // 组件上下文
    if (substr == "") {
      return;
    }
    // 获取建议
    substr = encodeURIComponent(substr);
    ajax(`meritmoot/reps/search/${substr}.json`, { type: "GET" }).then( result => {
      result = result.api;
      let pv = []; // 可能的值
      for(let i = 0; i < result.length; i++) {
        let newItem = {
          label: result[i].mm_reference_str,
          value: result[i].id,
          id: result[i].id,
        }
        pv.push(newItem);
      }
      console.log(pv)
      compContext.myAws.list = pv;
      // 更新 Awesomplete 内部逻辑
      compContext.myAws.evaluate();
      // 显示 Awesomplete 建议
      compContext.myAws.open();
    });
  },
  runOnce: function () {
    // 让我们知道它已运行...
    console.log("in runOnce")
    const substrInput = document.getElementById("rep-input");
    const compContext = this;
    
    // 为 substrInput(rep-input)创建自定义 Awesomplete(选项列表)。
    this.myAws = new Awesomplete(substrInput);
    console.log(substrInput)

    // 所有列表项都应显示,因为它们在 substr 值变化时会被有偏见地选中
    this.myAws.filter = function (text, input) {
      return true
    }

    // 随时显示,开启自动补全。
    this.myAws.minChars = 0;
    this.myAws.autocomplete = "on";

    // 选项被选中时进行处理。
    document.addEventListener('awesomplete-selectcomplete', function(e) {
        if(e.srcElement == substrInput) {
          let id = e.text.value;
          substrInput.value = "";
          
          // 将选择发送到后端
          let uriid = encodeURIComponent(id)
          ajax(`meritmoot/reps/${uriid}`, {type: "PUT" }).then( result => {
            console.log("put passed back:");
            console.log(result);
          });

          // 更新前端选择
          let l = compContext.get("subbedReps");
          l.pushObject(id) // 需要使用 pushObject 而不是 push(https://github.com/emberjs/ember.js/issues/10405)
          compContext.set("subbedReps", l);

          // 1. 完成:创建一个将用户 ID 与订阅代表匹配的表格。
          // 2. 完成:创建一种向该表格添加订阅代表的方法。进行中(需要 GET、PUT、DELETE)
          // 3. 在 substrInput 旁边显示代表
          // 3. 创建一种在主题旁边查看投票的方法。
          // 4. 完成所有这些后,刷新此处查看投票的机制。
        }
      }, false);
    
    // 获取用户保存的代表并显示它们。
    ajax(`meritmoot/reps`, {type: "GET"}).then( result => {
      console.log("get passed back:");
      console.log(result);
      compContext.set("subbedReps", result.mmfollows);
      console.log("subbedReps")
      console.log(compContext.get("subbedReps"));
    });

    // 输入时更新建议
    document.addEventListener('input', function(e) {
        if(e.explicitOriginalTarget == substrInput) {
          compContext.updatePossibles(substrInput.value);
        }
      }, false)
    console.log(this.myAws);
  },
  didRender() {
    this._super(...arguments);
    if( ! this.runOnceRan ) {
      this.runOnce();
      this.set("runOnceRan", true);
    }
  }
});

2 个赞