如何使用Web组件标记绑定嵌套的knockout组件?

时间:2016-04-26 18:06:57

标签: knockout.js knockout-3.0

我真的想使用嵌套的web-component样式标记,但我似乎永远无法让它工作。由于注释here (in the answer)

,我的工作正常
  

问题是由于在使用" web组件"时将params传递到组件中的方式。语法。

我真的不明白他们在说什么,OP正在处理数组。据我所知,它创造了计算出的可观察物。但是,嵌套组件的构造函数中的params总是$raw而且没有。

<parent-component>
  <content>
    <!--works-->
    <div data-bind="component: { name: 'child-component', params: { id: $parent.id } }"></div>

    <!-- does not work -->
    <child-component params="id: '{{$parent.id}}'"></child-component>

  </content>
</parent-component>

jsFiddle

为什么我无法嵌套web-component样式淘汰组件并具有约束力?

2 个答案:

答案 0 :(得分:0)

我在这里有一个网络组件示例https://github.com/brianlmerritt/knockout-babel-browserify-gulp

包含组件的典型主要html:

    <div class="row">
        <div class="panel panel-primary">
            <div class="panel-heading">
                <h2>Three Component View Model Binding Test</h2>
            </div>
            <div class="panel-body">
                <!-- THE GOAL OF THE PROJECT IS TO BIND EVERYTHING BEFORE AND AFTER THE FOLLOWING COMPONENT WITH centralViewModel -->
                <!-- ###ko stopBinding: true -->
                <div class="col-md-4">
                    <component-one></component-one>
                </div>
                <div class="col-md-4">
                    <component-two></component-two>
                </div>
                <div class="col-md-4">
                    <component-three></component-three>
                </div>
                <!-- ###/ko -->

                <p>Note: if component one did not load above, then check your browser console for errors</p>
            </div>

典型组件 - 请注意它是用ES2015(新Javascript)编写的

const ko = require('knockout')
        , CentralData = require('../../service-providers/central-data')
        , CentralState = require('../../service-providers/central-state')
        , template = require('./template.html');

    const viewModel = function (data) {

        //Make service providers accessible to data-bind and templates
        this.CentralData = CentralData;
        this.CentralState = CentralState;

        this.componentName = 'Component One';
        this.foo = ko.observable(`${this.componentName} Foo`);
        this.bar = ko.observableArray(this.componentName.split(' '));
        this.barValue = ko.observable("");
        this.bar.push('bar');
        this.addToBar = (stuffForBar) => {
            if(this.barValue().length >= 1) {
                this.bar.push(this.barValue());
                CentralData.pushMoreData({firstName: this.componentName,secondName:this.barValue()});
            }
        };
        this.CentralState.signIn(this.componentName);
        if (CentralData.dataWeRetrieved().length < 10) {
            var dataToPush = {firstName : this.componentName, secondName : 'Foo-Bar'};
            CentralData.pushMoreData(dataToPush);
        }
    };
    console.info('Component One Running');
    module.exports = {
        name: 'component-one',
        viewModel: viewModel,
        template: template
    };

template.html:

    <div>
        <h1 data-bind="text: componentName"></h1>
        <p>Foo is currently: <span data-bind="text: foo"></span></p>
        <p>Bar is an array. It's values currently are:</p>
        <ul data-bind="foreach: bar">
            <li data-bind="text: $data"></li>
        </ul>
        <form data-bind="submit: addToBar">
            <input type="text"
                   name="bar"
                   placeholder="Be witty!"
                   data-bind="attr: {id : componentName}, value : barValue" />
            <button type="submit">Add A Bar</button>
        </form>
        <h2>Central State</h2>
        <p>The following components are currently signed in to Central State Service Provider</p>
        <ul data-bind="foreach: CentralState.signedInComponents()">
            <li data-bind="text: $data"></li>
        </ul>
        <h2>Central Data</h2>
        <p>The following information is available from Central Data Service Provider</p>
        <table class="table table-bordered table-responsive table-hover">
            <tr>
                <th>Component Name</th><th>Second Value</th>
            </tr>
            <!-- ko foreach: CentralData.dataWeRetrieved -->
            <tr>
                <td data-bind="text: firstName"></td><td data-bind="text: secondName"></td>
            </tr>
            <!-- /ko -->
        </table>
        <h3>End of Component One!</h3>
    </div>

app.js具有组件绑定

const ko = require('knockout');

/**
 * The modules that follow are singleton modules that do not appear to conflict with bindings
 *
 */

const CentralData = require('./service-providers/central-data');   // Mock centralised data/model service
const CentralState = require('./service-providers/central-state'); // Mock centralised state service

/**
 * Register knockout web components - these work, but conflict with any central bindings
 */

ko.components.register(
    'component-one',
    require('./components/component-one/component.js')
);

ko.components.register(
    'component-two',
    require('./components/component-two/component.js')
);

ko.components.register(
    'component-three',
    require('./components/component-three/component.js')
);

/**
 * This code comes from http://www.knockmeout.net/2012/05/quick-tip-skip-binding.html
 *
 * Telling Knockout to Skip Binding Part of a Page
 *
 * However, when used around a component, the component does not load/run!
 *
 */

ko.bindingHandlers.stopBinding = {
    init: function() {
        return { controlsDescendantBindings: true };
    }
};

ko.virtualElements.allowedBindings.stopBinding = true;


/**
 * centralViewModel should be loadable for "all of the page not managed by components"
 *
 * That is the goal of the project, which I am failing in badly at the moment
 *
 */

const centralViewModel = {
    bindingWorked : ko.observable('The binding worked. KO view model centralViewModel has a this context and was bound to the html correctly')
};

console.info('app.js applying bindings...');

/**
 * The next line should bind central viewmodel to everything, but conflicts with components!!
 */

ko.applyBindings(centralViewModel,document.body);

// ko.applyBindings(); // Pull in all of the components


/**
Note: to avoid binding issues, we should be able to add these html comments around each component
 <!-- ko stopBinding: true -->
 <component-name>
 <!-- /ko -->
 However - when we do, the components no longer work
 */

答案 1 :(得分:0)

好吧,感谢@Jeroen让我提供了一个更好的例子。

我的问题是我将参数包装在单引号中并使用{{handle bars}}进行绑定。一旦我删除它,它似乎工作正常。

    <!-- does not work -->
    <child-component params="id: '{{$parent.id}}'"></child-component>

    <!-- wow, this does work! -->
    <child-component params="id: $parent.id"></child-component>