【问题标题】:Knockout Validation Breaking when Bundling with WebPack与 WebPack 捆绑时敲除验证中断
【发布时间】:2016-03-04 07:44:14
【问题描述】:

我正在使用 Knockout-Validation 插件创建一个 Knockout Web 应用程序。我想使用 WebPack 进行捆绑。

问题是当我使用 WebPack 时,Knockout-Validation 会中断。

作为一个简单的测试用例,我无需捆绑即可使验证正常工作:https://jsfiddle.net/3y24zvLs/

HTML:

<label>Name</label>
<input type="text" data-bind="value: name">
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>

JS:

function ViewModel() {
    var self = this;
    self.name = ko.observable().extend({required: true});
};

ko.applyBindings(new ViewModel());

我也可以将它用作已注册的 Knockout 组件:http://jsfiddle.net/3y24zvLs/2/

HTML:

<name-component></name-component>

JS:

function ViewModel() {
    var self = this;
    self.name = ko.observable().extend({required: true});
};

ko.components.register('name-component', {
    viewModel: ViewModel,
    template: '<label>Name</label>\
                <input type="text" data-bind="value: name">\
                <pre data-bind="text: ko.toJSON($data, null, 2)"></pre>'
});

ko.applyBindings();

但是,当我尝试使用捆绑验证中断时:

index.html:

<!DOCTYPE html>
<head>
  <script src="Built/main.bundle.js"></script>
</head>
<body>
  <name-component></name-component>
</body>

main.js

var ko = require('../node_modules/knockout/build/output/knockout-latest');
var $ = require('jquery');
require('./ViewModel');

$(function(){
  ko.applyBindings();
})

ViewModel.js

"use strict";

var ko = require('../node_modules/knockout/build/output/knockout-latest');
var kv = require('../node_modules/knockout.validation/dist/knockout.validation');

function ViewModel() {
    var self = this;
    self.name = ko.observable().extend({required: true});
};

ko.components.register('name-component', {
    viewModel: ViewModel,
    template: '<label>Name</label>\
                <input type="text" data-bind="value: name">\
                <pre data-bind="text: ko.toJSON($data, null, 2)"></pre>'
});

webpack.config.js

var webpack = require('webpack'),
    path = require('path');


module.exports = {
  context: path.join(__dirname, 'App'),
  entry: './main.js',
  output: {
    path: path.join(__dirname, 'Built'),
    filename: '[name].bundle.js'
  },
  module: {
    loaders: [
      { test: /\.html$/, loader: 'html-loader'},
      { test: /\.js$/, loader: 'babel-loader'}
    ]
  }
};

有没有人知道验证失败的原因?淘汰赛验证与 WebPack 不兼容吗?也许我应该尝试改用 Gulp 或 Grunt 来捆绑组件并使用 RequireJS 而不是 WebPack/CommonJS?虽然我不完全确定这个开关会有多简单......

非常感谢任何帮助。

【问题讨论】:

    标签: javascript knockout.js webpack knockout-validation


    【解决方案1】:

    我想记下这个问题,因为我刚刚解决了它,但今天早上我浪费了一些时间试图让它发挥作用,所以如果我把它留在这里,希望能防止其他人浪费时间。

    我将 jQuery、Knockout 和 Knockout-Validation 移至全局范围,并消除了一些我遇到的重新定义问题。

    index.html

    <!DOCTYPE html>
    <head>
        <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-debug.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.3/knockout.validation.js"></script>
        <script src="Built/main.bundle.js"></script>
    </head>
    <body>
      <name-component></name-component>
    </body>
    

    ma​​in.js

    /*
      Knockout and jQuery were moved to the global scope. Knockout exports as 
      'ko' so there is no need to redefine it here.
    */
    
    //var ko = require('../node_modules/knockout/build/output/knockout-latest');
    //var $ = require('jquery');
    require('./ViewModel');
    
    $(function(){
      ko.applyBindings();
    })
    

    为了完整起见,这里是其他文件:

    ViewModel.js

    "use strict";
    
    function ViewModel() {
        var self = this;
        self.name = ko.observable().extend({required: true});
    };
    
    ko.components.register('name-component', {
        viewModel: ViewModel,
        template: '<label>Name</label>\
                    <input type="text" data-bind="value: name">\
                    <pre data-bind="text: ko.toJSON($data, null, 2)"></pre>'
    });
    

    webpack.config.js

    var webpack = require('webpack'),
        path = require('path');
    
    
    module.exports = {
      context: path.join(__dirname, 'App'),
      entry: './main.js',
      output: {
        path: path.join(__dirname, 'Built'),
        filename: '[name].bundle.js'
      },
      module: {
        loaders: [
          { test: /\.html$/, loader: 'html-loader'},
          { test: /\.js$/, loader: 'babel-loader'}
        ]
      }
    };
    

    【讨论】:

    • 不知道你是怎么用WebPack做的,但是ko.validation要求ko定义为全局变量。如果您使用 CommonJS 加载 ko,您可能会避免使用它来定义全局 ko。在require.js 中,您需要使用 shim 才能使 thsi 工作:stackoverflow.com/questions/18072784/… 这个解决方案是,嗯,我们称之为“不好”,而不是更突然的说法;)这个问题在 jQuery 插件之类的东西上也很常见这也取决于在全局范围内定义的 $/jQuery。
    • 我让它与 RequireJS 一起工作,但我想使用 WebPack,因为它相当简单,我可以用它来用 babel 转译 es6。你会推荐一个不同的工具吗(例如,gulp、browserfy 等?)就我目前的解决方案“不好”而言,你是否意味着通过全局脚本标签引入 ko、kv 和 jQuery 并不理想?
    • 是的,这就是“不好”的原因。正如您所说,您可以使用 grunt 或 gulp。请记住,还有一个 require js 优化器也允许自定义捆绑。使用 babel transpiler 设置 grunt 并需要 js 优化器应该花费很少的时间。特别是如果你有一些经验。 require 优化器将为您节省时间来缩小和连接。顺便说一句,也有需要 js 的 Babel 插件,这样优化器也可以为你完成这项工作。例如:npmjs.com/package/requirejs-babel-plugin
    • 如果不清楚,如果您使用带有 requirejs 的插件,例如 text!es6!,requirejs 优化器将运行插件(例如 es6 转译),并包含结果在优化(d)包中。所以你只需要编译和优化。忘记缩小、捆绑等。
    猜你喜欢
    • 1970-01-01
    • 2018-06-07
    • 2014-11-08
    • 2018-03-12
    • 2017-09-26
    • 1970-01-01
    • 2012-11-23
    • 2013-01-13
    • 1970-01-01
    相关资源
    最近更新 更多