Rails 6 + Webpack,数据表,jQuery

Rails 6 + Webpack, Datatables, jQuery

我有一个使用此代码的 "Select All" 按钮:

<script type='text/javascript'>
  $('#check_all').on("click", function() {
    $('input[type="checkbox"]').click();
  });
</script>

自从我升级到 Rails 6 + Webpacker,它就停止工作了。 控制台显示此错误:

Uncaught ReferenceError: $ is not defined

我设法通过更改 environment.js 来修复它:

environment.plugins.append('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    Popper: ['popper.js', 'default']
  })
)

收件人:

environment.plugins.append('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery',
    Popper: ['popper.js', 'default']
  })
)

但是一旦修复,数据表就会中断。

有什么想法可以让他们一起工作吗? 谢谢!

将您自己的 Javascript 移动到包文件中是可维护性的不错选择。但是,我猜这些是动态生成的复选框。绑定运行时它们可能不存在。您可以通过绑定到父元素并使用 event delegation 来解决这个问题。 document.body 是使用 Turbolinks 委托事件的常见绑定选择。

我不喜欢在复选框上调用 click()。结果对用户来说并不总是一致的,它会在浏览器中触发一堆不必要的事件。反转 checked 属性更清晰、更一致。

让 DataTables 作为模块加载需要一个 import shim。这是一个较旧的包,它更喜欢 AMD 而不是 CommonJS,并且在 Webpack 环境中会超越自己。幸运的是,有一个针对旧代码的标准修复,使用 imports-loader. Unfortunately, even then it's got a slightly strange factory export, into which you're expected to inject the window and jQuery variables. Fortunately it's also documented here.

综上所述,这是一个建议 application.js:

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

import $ from 'jquery'

// Add DataTables jQuery plugin
require('imports-loader?define=>false!datatables.net')(window, $)
require('imports-loader?define=>false!datatables.net-select')(window, $)

// Load datatables styles
import 'datatables.net-dt/css/jquery.dataTables.css'
import 'datatables.net-select-dt/css/select.dataTables.css'

$(document).on('turbolinks:load', () => {
  $(document.body).on('click', '#check_all', () => {
    var checkBoxes = $('input[type="checkbox"]')
    checkBoxes.prop("checked", !checkBoxes.prop("checked"))
  })

  // placeholder example for datatable with checkboxes
  $('#example').DataTable({
    columnDefs: [{
      render: (data,type,row) => `<input type="checkbox" value="${row[0]}">`,
      orderable: false,
      targets: 0
    }],
    order: [[ 1, 'asc' ]]
  })
})

您需要 yarn add imports-loader,因为它是一个 Webpack 选项。

这些都不需要 ProvidePlugin。除非您依赖它来注入对第三方代码的导入,否则可以安全地删除它。

运行 yarn add imports-loader

我用的是bootstrap4 datatable,如果你用bootstrap3或者其他CSS框架,请按照这个link安装: https://datatables.net/download/

在我的 config/webpack/loaders/datatable.js

module.exports = {
  test: /datatables\.net.*/,
  use: [{
    loader: 'imports-loader?define=>false'
  }]
}

在我的 config/webpack/environment.js

const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
const coffee =  require('./loaders/coffee')
const datatable =  require('./loaders/datatable')

environment.plugins.append('Provide', new webpack.ProvidePlugin({
  $: 'jquery',
  jQuery: 'jquery',
  jquery: 'jquery',
  'window.jQuery': 'jquery',
  Popper: ['popper.js', 'default']
}))

/**
 * To use jQuery in views
 */
environment.loaders.append('expose', {
  test: require.resolve('jquery'),
  use: [{
    loader: 'expose-loader',
    options: '$'
  }]
})

environment.loaders.prepend('coffee', coffee)
environment.loaders.prepend('coffee', datatable)

module.exports = environment

在我的 app/javascript/packs/dashboard.js

require( 'jszip' );

require("datatables.net-bs4")(window, $);
require("datatables.net-responsive-bs4")(window, $);
require("datatables.net-buttons-bs4")(window, $);
require("datatables.net-select-bs4")(window, $);

require("datatables.net-bs4/css/dataTables.bootstrap4.css");
require("datatables.net-responsive-bs4/css/responsive.bootstrap4.css");
require("datatables.net-buttons-bs4/css/buttons.bootstrap4.min.css");
require("datatables.net-select-bs4/css/select.bootstrap4.css");

用户随意 import './datatable'app/javascript/packs 您喜欢的任何 .js 文件

以上的

None 对我有用。最终按照本指南使其工作:https://inopinatus.org/2019/09/14/webpacker-jquery-and-jquery-plugins/.

yarn add datatables.net-bs4 imports-loader

application.js

require('@rails/ujs').start()
require('@rails/activestorage').start()
require('channels')
require('jquery')
require('bootstrap/dist/js/bootstrap')
window.$ = $

require('imports-loader?define=>false!datatables.net')(window, $)
require('imports-loader?define=>false!datatables.net-bs4')(window, $)