1

Используется генератор нокаута Yeoman (в начале 2015 года), который включает в себя require.js и router.js. Просто используйте загрузчик KO.Нокаут: обратитесь к компоненту A, чтобы вызвать функцию A из компонента B?

Am попытки вызвать функцию (ko.observable или нет) в компоненте «а» от компоненты «б». Все ниже пуха пытается сделать просто:

// In componentB: 

ComponentA.sayFoo(); 

Read KO документы на компоненты и погрузчиков, взломанных в течение нескольких часов, и т.д. Я не хочу накладных расходов сказать postal.js - и также не удалось получить подписки (KO pub/sub) для работы - я предполагаю по той же причине: модели представления, созданные таким образом, не имеют ссылок друг на друга (?) - поэтому подписчики в одном модуле не видят издатели в другой (правда?) (... немного над моей головой здесь% -)

1) Это потому, что модули не видят друг друга ... что этот сгенерированный код не помещает материал KO в глобальное пространство имен?

2) Попытка добраться от одного модуля к другому, кажется, зависит от получения ref через обратные панели, используя приведенную ниже функцию или это неверно? :

ko.components.get (name, callback) ; 

startup.js использованием требуется выглядит следующим образом:

define(['jquery', 'knockout', './router', 'bootstrap', 'knockout-projections'], function($, ko, router) { 

// Components can be packaged as AMD modules, such as the following: 

    ko.components.register('component-a', { require: 'components/a/component-a' }); 
    ko.components.register('component-b', { require: 'components/b/component-b' }); 

// [Scaffolded component registrations will be inserted here. To retain this feature, don't remove this comment.] 
// [Scaffold component's N/A (I think?)] 

// Start the application 
    ko.applyBindings({ route: router.currentRoute }); 
}); 

(компонент) модуль А прямо вперед, как это:

define(['knockout', 'text!./component-a'], function(ko, templateMarkup) { 

    function ComponentA (params) { console.log ('CompA'); } ; 

    ComponentA.prototype.sayFoo = function() { console.log ('FOO!'); } ; 
    ComponentA.prototype.dispose = function(){}; 

    return { viewModel: ComponentA, template: templateMarkup }; 
}); 

Аналогично , модуль B:

define(['knockout', 'text!./component-b'], function(ko, templateMarkup) { 

    function ComponentB (params) { console.log ('Compb'); } ; 

    ComponentB.prototype.doFoo = function() { 
    //// B Needs to fire ComponentA.foo() … SEE CODE ATTEMPT BELOW 
    }; 

    ComponentB.prototype.dispose = function(){}; 

    return { viewModel: ComponentB, template: templateMarkup }; 
}); 

Так вот где я застрял:

ComponentB.prototype.doFoo = function() { 
     ko.components.get ('component-a', (function (parms) { 
      console.log ('parms.viewModel : ' + parms.viewModel); 
      // parms.viewModel is (unexpectedly) undefined ! So how to get the ref? 
      console.log ('parms.template : ' + parms.template); 
      // does have expected html objects, eg. [object HTMLwhatever], [object HTML...] 
})) ; 

Это должно быть легко, или я беззвучно оставляя что-то очевидное !?

Возможно, модули необходимо определить/настроить по-другому?

Любые предложения помогут! Thx

ответ

2

Это не то, как вы обычно общаетесь между компонентами нокаута.

варианты:

1) Используйте https://github.com/rniemeyer/knockout-postbox. Это, пожалуй, лучший вариант, так как он прекрасно сочетается с нокаутом. Это хорошо документировано, и если у вас есть проблемы с настройкой, вы всегда можете обратиться за помощью.

2) Используйте любой другой глобальный javascript EventBus (f.i. postal.js) и выпустите/подписайтесь на события в ваших компонентах.

3) Пусть ваш корневой ViewModel передает общие наблюдаемые данные каждому компоненту в качестве параметров - таким образом каждый компонент может изменять/подписываться на одно и то же наблюдаемое.

4) (Возможно, что вы хотите, хотя самое худшее решение для масштабирования). Если вы дадите идентификаторы различным компонентам, вы можете использовать ko.dataFor(document.getElementById("id")) для прямого доступа к свойствам и методам ваших компонентов.

EDIT: В ответ на комментарий:

Я не смог определить, что/где вид модели корень: ko.applyBindings ({маршрут: router.currentRoute}) является ключ, но router.js свернуто. Предложения о том, как это определить?

Точно - в вашем случае объект { route: router.currentRoute } является вашим корневым ViewModel. В настоящее время у него есть только одно свойство, называемое route, но вы можете это точно расширить.

Например:

var rootViewModel = { 
    route: router.currentRoute, 
    mySharedObservable: ko.observable('hi!') 
} 

ko.applyBindings(rootViewModel); 

Затем вы можете передать, что наблюдаемые на несколько компонентов в качестве параметра, например так:

<div id="component-a" data-bind="component: { name: 'component-a', params: {router: $root.router, mySharedObservable: $root.mySharedObservable} }"></div> 
<div id="component-b" data-bind="component: { name: 'component-b', params: {router: $root.router, mySharedObservable: $root.mySharedObservable} }"></div> 

И, наконец, вы можете использовать новый наблюдаемыми внутри компонента, как это :

function ComponentB (params) { 
    this.mySharedObservable = params && params.mySharedObservable; 
    console.log(this.mySharedObservable());// This should log 'hi!' 
}; 

Теперь вы можете подписаться на наблюдаемое, изменить его и так далее на. Он будет разделяться между компонентами, поэтому его изменение одним компонентом инициирует подписки во всех компонентах.

+0

thx vtosh - RE 4) - несмотря на то, что он не масштабируется и не является жестко закодированным, это может быть лучше ... Мне нужно всего лишь сделать несколько кросс-компонентных обменов. RE 3) часть проблемы заключается в том, что я использовал «консервированный» генератор без глубокого понимания всей созданной им архитектуры. Я не смог определить, что/где модель корневого представления: ko.applyBindings ({route: router.currentRoute}) - это ключ, но router.js запутан. Предложения о том, как это определить? thx снова –

+1

См. обновленный ответ. – vtosh

+0

оцените помощь здесь! Не удалось заставить редактируемую версию работать, хотя я думаю, что понимаю намерение. 'this.mySharedObservable = params && params.mySharedObservable;' дает неопределенные ... так что я думаю, что это не передано. Этот синтаксис выглядит странно - почему «params &&», а не только «this.mySharedObservable = params.mySharedObservable»? (Я тоже это пробовал, но все еще не определен). –

1

Моим стандартным подходом было бы управлять связью через родительскую виртуальную машину.

Родительская виртуальная машина может создать подписку [1] и передать ее как компоненту А, так и компоненту В в качестве параметра; то ComponentA может подписаться на подписку, а ComponentB может инициировать подписку.

//ComponentA 
function ComponentA (params) { 
    var shouldSayFoo = params.shouldSayFoo; 

    this.shouldSayFooSubscription = shouldSayFoo.subscribe(function() { 
     this.sayFoo(); 
    }); 
} ; 

ComponentA.prototype.sayFoo = function() { console.log ('FOO!'); } ; 
ComponentA.prototype.dispose = function() { this.shouldSayFooSubscription.dispose(); }; 

//In ComponentB 
function ComponentB (params) { 
    this._triggerFoo = params.triggerFoo; //Same subscribable as shouldSayFoo in ComponentA 
} 

ComponentB.prototype.doFoo = function() { 
    this._triggerFoo.notifySubscribers(); //notifySubscribers triggers any .subscription callbacks 
} 

Если Componenta и ComponentB являются братьями и сестрами, и вы не делать такого рода вещи все время, это работает как прилично простое решение. Если компоненты «дальние родственники» или если вы так много делаете, то я бы предложил какой-то паб-суб. И преимущество этого подхода может быть использовано множеством отдельных пар «A-B», не мешая друг другу, что сложнее с системой pub-sub.

[1]: A ko.subscribable представляет собой объект с подмножеством наблюдаемой функциональности (ko.observable наследует от ko.subscribable): она не позволяет считывать или записывать значения, но позволяет делать .subscribe и .notifySubscribers. (По какой-то причине они созданы с помощью new). Вы также можете использовать наблюдаемое, это просто небольшое замешательство в намерении создать наблюдаемое, если вы не намерены удерживать его.

+0

thx Retsam - Как я уже говорил выше, моя настоящая проблема заключалась в использовании консервированного генератора, который я не совсем понял ... теперь это немного меня: -0 ... Я не уверен, компоненты даже имеют модель представления в качестве родителя (или не знаю, где она). Вот почему я не мог заставить pub/sub работать. Тупой. Хорошо, пытаясь понять код, который вы опубликовали, - у него есть A и B как братья и сестры с подразумеваемой моделью представления родителя/(корневого), верно? thx –

+1

@HowardPautz Исправить; Я предполагаю, что A и B являются братьями и сестрами и что у них есть родитель. (Который может быть корнем). Если они не являются непосредственными братьями и сестрами, необходимо будет провести более промежуточную проводку, в конечном итоге для этой стратегии работать, их общий предок должен настроить линию связи. – Retsam

Смежные вопросы