webpack、jquery和动态表单字段



我在symfony项目中使用webpack和jQuery。我配置了webpack和jquery如下:

// webpack.common.js
const path = require('path');
var webpack = require('webpack');
module.exports = {
entry: {
main: "./src/default/index.js",
commons: "./src/default/js/app.js"
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
module: {
rules: [
{ 
test: /datatables.net.*/, 
use: [{
loader: 'imports-loader',
options: {
additionalCode: 
"var define = false;"
}
}]
},
{
test: require.resolve("jquery"),
loader: "expose-loader",
options: {
exposes: ["$", "jQuery"],
},
},
{
test: /.(scss)$/,
use: [{
// inject CSS to page
loader: 'style-loader'
}, {
// translates CSS into CommonJS modules
loader: 'css-loader'
}, {
// Run postcss actions
loader: 'postcss-loader',
options: {
// `postcssOptions` is needed for postcss 8.x;
// if you use postcss 7.x skip the key
postcssOptions: {
// postcss plugins, can be exported to postcss.config.js
plugins: function () {
return [
require('autoprefixer')
];
}
}
}
}, {
// compiles Sass to CSS
loader: 'sass-loader'
}]
},
{
test: /.css$/i,
use: ["style-loader", "css-loader"],
}
]
},
resolve: {
alias: {
jquery: "jquery/src/jquery"
}
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery"
})
]
}
// index.js
import 'bootstrap';
import './scss/app.scss';
import '@fortawesome/fontawesome-free/js/fontawesome';
import '@fortawesome/fontawesome-free/js/solid';
import '@fortawesome/fontawesome-free/js/regular';
import '@fortawesome/fontawesome-free/js/brands';
require('select2');
require('jquery-ui/ui/widgets/datepicker');
require('jquery-ui/ui/i18n/datepicker-fr.js')
import 'datatables.net';
import dt from 'datatables.net-bs5';
import 'datatables.net-bs5/css/dataTables.bootstrap5.min.css';
dt(window, $);

我的项目使用了一个旧的jQuery插件,我在名为select2Helper的项目中简化了select2的使用。

if ( "undefined" !== typeof jQuery ) {
(function($, window, document) {
$(function() {
$.select2Helper = function(element, options) {
// Do stuff
}

// Add the plugin to jQuery functions (jQuery.fn object)
$.fn.select2Helper = function(options) {

// Iteration through the DOM elements we are attaching the plugin
return this.each(function(){
// If the plugin has not already been attached to the element
if (undefined == $(this).data('select2Helper')) {

// Create new instance of the plugin with current DOM element and user-provided options
var plugin = new $.select2Helper(this, options);

// In the jQuery version of the element,
// store a reference to the plugin object
// for access to the plugin from outside like 
// element.data('select2Helper').foo(), etc.
$(this).data('select2Helper', plugin);
}
});
}
});
});
}

这个插件是基于官方的jQuery插件"如何编写插件";文档

我在webpack之外加载这个插件(旧风格(,所以我需要在webpack之外访问$。此脚本使用Select2插件初始化select表单元素上的自动完成。

到目前为止还不错

当我想动态添加一个使用jQueryselect2插件的字段时(在页面加载后(,我遇到了一个问题。

当我这样做(在表单中添加新的select2字段(并用select2:初始化select字段时

if ( "undefined" !== typeof jQuery ) {
(function($, window, document) {
$(function() {
$('.select2-element').select2Helper(config);
});
}(window.jQuery, window, document));
}

结果是:;Select2Helper未定义">

第一次测试

当我这样做时:

if ( "undefined" !== typeof jQuery ) {
(function($, window, document) {
$(function() {
console.info($.fn);
});
}(window.jQuery, window, document));
}

结果显示select2Helper在$.fn列表($.fn.select2Helper(中。但是页面加载后调用的相同代码显示select2Helper不在列表中。

第二次测试

当我在页面上加载时:

if ( "undefined" !== typeof jQuery ) {
(function($, window, document) {
$(function() {
console.info(jQuery);
console.info($);
});
}(window.jQuery, window, document));
}

console.info(jQuery)的返回与console.info($)的返回不同。在第一个例子中,我在jQuery.fn中没有select2Helper,但它存在于$.fn中。

我发现页面加载后使用的$对象与上面的jQuery对象相同,而不是上面的$对象。

谢谢你的帮助。

我终于找到了解决方案。

我的错误不是来自我的jQuery插件select2Helper或jQuery。是由于缺乏对webpack及其配置的了解。

当我写作:

// webpack.common.js
const path = require('path');
var webpack = require('webpack');
module.exports = {
entry: {
main: "./src/default/index.js",
commons: "./src/default/js/app.js"
},
// ...
}

我定义了两个条目。对于每个条目,webpack构建两个版本的jQuery。我最初的想法是在其他脚本的基础上集成一个额外的脚本,其中包含一些javascript内容。但我意识到这是在构建一个带有app.js文件的commons.bundle.js,其中包含所有内容(jQuery、datatable等(。

我最终得到了一个包含jQuery(和其他内容(的文件main.bundle.js,以及一个也包含jQuery但不是同一个的commons.bundle.js,因此有了两个版本的jQuery。

我直接在index.js中复制/粘贴来自app.js的小javascript内容,现在一切都很好。