BreezeJS与DurandalJS问题的集成与KnockoutJS的加载方式有关

 今生绝恋2702934494 发布于 2023-02-05 09:04

Durandal.JS和Breeze.JS在一起玩有些麻烦.Durandal基于几个库,其中两个是Require和Knockout.在使用Require引入的模块化模式之前,我的原始项目使用了Breeze模型上的Knockout样式绑定.

在我的旅途中,我发现Breeze可以使用Breeze模型的多个库,例如Backbone,Knockout,Angular和其他框架.当Breeze作为Require模块加载时,Breeze会检查是否存在Knockout模块,别名为"ko".此模块名称与Durandal别名Knockout的方式相冲突,因为Durandal使用模块名称"knockout"代替.

当Breeze加载时,将进行检查以确定如何呈现Breeze模型的数据属性.在我的原始项目中,Breeze将检测全局范围内的Knockout并分配所有属性"ko.observable()"样式属性.

如何才能让这些模块正常播放?我已经尝试了几个Require.JS技巧,比如添加这个Shim :( 来自这篇文章)

breeze: { deps: ['ko', 'jQuery', 'Q'] }

并添加这些虚拟模块定义:

define('ko', ['knockout'], function (ko) { return ko; });
define('Q', ['q'], function (Q) { return Q; });
define('jQuery', ['jquery'], function ($) { return $; });

在我的main.js. 这个组合允许Breeze运行.我能够针对后端API成功执行查询.

但是,结果没有正确地变成Knockout可观察的.相反,Breeze似乎使用本机ES5可观察属性.虽然这实际上有点酷,但它完全打破了我现有的模块.

需要注意的是,正如Druandal文档所建议的那样,我使用他们提供的代码片段来覆盖内部Promise库.

   system.defer = function (action) {
        var deferred = Q.defer();
        action.call(deferred, deferred);
        var promise = deferred.promise;
        deferred.promise = function () {
            return promise;
        };
        return deferred;
    };

这些相同的问题都出现在Q库和jQuery库中,尽管上面的垫片和虚拟模块纠正了这种行为.我不知道下一步该尝试什么.

编辑:响应"显示您的上下文设置"评论:

define([
'breeze',
'q',
'durandal/system',
'lodash'
],
function (breeze, Q, system, _) {
    return new function () {
        var self = this;

        self.create = create;
        self.init = init;

        var EntityQuery = breeze.EntityQuery;
        var BREEZE_URL = '/breeze/AtlasApi/';
        var masterManager = new breeze.EntityManager(BREEZE_URL);
        self.masterManager = masterManager;

        function init() {

            return masterManager.fetchMetadata()
                    .fail(function (error) {
                        system.error(error);
                    });
        };
        function create() {
            var manager = masterManager.createEmptyCopy();

            return manager;
        };
    };
});

上面的模块我在AppStart加载一次并调用Init方法以确保我有元数据.然后我在其他地方调用.create()来创建一个空的,孤立的副本.这在非Require.js环境中非常有效.我使用promises来确保init步骤已经完成.我可以手动运行查询并且它们可以工作,减去Breeze实现实体的方式(再次,作为ES5属性,而不是敲除属性)

1 个回答
  • 看起来你正试图通过requireJS加载每个库.我记得开箱即用的Durandal方法是直接加载第三方脚本(在require之外)并且仅对应用程序脚本使用require.

    这简化了事情,但它不是唯一的方法,很多人都想使用require来加载他们的所有脚本.

    我们最近(v.1.4.7)更新了" Todo-Require "样本以证明这种方法.我意识到它不是Durandal应用程序,但我希望你能找到你需要的方向.

    我将在此复制我认为对您有所帮助的要点.

    的index.html

    ...
    <body>
        <div id="applicationHost"></div>
    
        <!-- Require + main. All scripts retrieved async by requireJS -->
        <script data-main="Scripts/app/main" src="Scripts/require.js"></script>
    </body>
    ...
    

    main.js

    (function () {
        requirejs.config({
            paths: {
                'breeze': '../breeze.debug',
                'jquery': '../jquery-1.8.3.min',
                'ko':     '../knockout-2.2.0',
                'Q':      '../q'
            }
        });
    
        //  Launch the app
        //  Start by requiring the 3rd party libraries that Breeze should find
        define(['require', 'ko', 'jquery', 'logger', 'Q'], function (require, ko, $, logger) {
            logger.info('Breeze Todo is booting');
    
            // require the 'viewModel' shell 
            // require '../text' which is an html-loader require plugin; 
            //     see http://requirejs.org/docs/api.html#text
            require(['viewModel', '../text!view.html'],
    
            function (viewModel, viewHtml) {
                var $view = $(viewHtml);
                ko.applyBindings(viewModel, $view.get(0));
                $("#applicationHost").append($view);
            });
        });
    })();
    

    注意我们如何使用路径来定位库并获得按照Breeze期望的那样建立的模块名称.

    另请注意,我们强制requireJS加载Breeze 之前加载这些依赖的第三方库.这非常重要.在Breeze开始寻找它们时,它们必须在requireJS IoC容器中; 如果他们不在那里,Breeze认为他们永远不会在那里.

    这就是为什么你看到Breeze将你的实体属性视为ES5属性.该define在你的电话"背景设置"负荷"KO"和"清风" 在同一时间.这意味着当Breeze在自己的初始化阶段查找时,无法保证会加载'ko'.

    如果在Breeze查找时没有加载'ko',Breeze假定您没有使用Knockout并且回退到其原生模型库("backingStore")...它将实体构建为ES5属性.这恰好是Angular应用程序的正确选择.这不是KO应用程序的正确选择.

    最后,如果Durandal期望一个模块的名称不同(我会接受你的话),使用requireJS "map"配置来定义同义词,如下例所示:

    requirejs.config({
        paths: {
            'breeze': '../breeze.debug',
            'jquery': '../jquery-1.8.3.min',
            'ko':     '../knockout-2.2.0',
            'Q':      '../q'
        },
        map: {
            '*': { 'knockout': 'ko' }
        }
    });
    

    现在当Durandal请求'淘汰'时,requireJS会将它映射到(已经加载的)'ko'模块.

    这种"地图"技术代替了"虚拟模块"方法,它同样有效:

    define('knockout', [ko], function (ko) { return ko; });
    

    在查看示例代码时,您可能想知道此应用程序何时加载Breeze.答案:什么时候viewModel解决了.它viewModel有自己的依赖,包括dataservice它本身依赖于Breeze.依赖注入难道不是很了不起?:-)

    替代

    您也可以以不同的方式解决问题.

    根据您的问题,您可以启动并运行Breeze和Durandal,但Breeze模型库似乎是为Breeze的本机"backingStore"配置的,它将实体属性写为ES5 getter/setter属性.

    您可以在以后更改选择在启动过程中,也许dataservice还是datacontext模块,你先用微风交互并创建一个EntityManager.

    在您进行第一次Breeze互动之前,请致电

    breeze.config.initializeAdapterInstance("modelLibrary", "ko", true);
    

    这将Knockout建立为Breeze在创建/实现实体时应使用的模型库.此后,将使用KO可观察属性创建实体.

    这是至关重要的淘汰赛被加载requireJS IoC容器和访问为"KO" 之前进行此配置更改,否则微风会抛出异常.

    不要指望Breeze等到requireJS异步加载'ko'.适配器初始化是一个同步过程.在Breeze寻找它之前必须加载'ko'.

    杜兰达2.0

    我被告知Durandal v2.0在某种程度上改变了我在Durandal v.1.x中熟悉的设置模式.我相信我的答案仍然存在密切关系.

    我还不熟悉Durandal v.2.我很兴奋,因为它提供了使用ES5属性getter/setter而不是可观察性函数的可能性.我喜欢那一吨!

    成本这个特定的功能(这你就没有必须使用)是你必须在ES5兼容的浏览器......这意味着你不能在仍然很受欢迎IE8都跑.ES5属性没有polyfill.

    大多数......但不是全部...单页应用程序可以在此限制内运行.

    不幸的是,根据Durandal的架构师,在目前的2.0版本中,ES5属性不适用于Breeze.两个图书馆争夺那些吸气者和二传手.因此,您可以将Durandal v2.0与Breeze一起使用,但您现在必须使用可观察的函数属性.

    我们希望这个故事能够在第2.1节中得到改进

    总共

    希望这些想法和变化能让你走上成功的道路.

    2023-02-05 09:07 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有