将自定义JavaScript模型映射到具有observable的Knockout模型

时间:2017-12-20 15:36:38

标签: javascript knockout.js

我从服务器收到一个模型,它是一个(导航)菜单。 所以它有1个根项,带有一系列菜单项。根项目也有标题。 menuitems数组是一个项目数组,包含一个title和一个linkItems数组(具有controller,action,css等属性的对象)。

我的knockout viewmodel中有相同的模型,但是所有的数组和属性都是可观察的数组/字符串/整数。

现在我这样做了

import React, {Component} from 'react' import PropTypes from 'prop-types' import {Link} from 'react-router' import {Table, Column} from '../../Layout/components/Table' import ReactDOM from 'react-dom' // import ExternalPortal from '../../Sites/components/ExternalPortal' export const TableName = 'ProjectDashboard' class MyWindowPortal extends Component { static propTypes = { children: PropTypes.node, closeWindowPortal: PropTypes.func } constructor (props) { super(props) this.containerEl = document.createElement('div') // STEP 1: create an empty div this.externalWindow = null } componentDidMount () { // STEP 3: open a new browser window and store a reference to it this.externalWindow = window.open('', '', 'width=600,height=400') // STEP 4: append the container <div> (that has props.children appended to it) to the body of the new window this.externalWindow.document.body.appendChild(this.containerEl) this.externalWindow.document.title = 'A React portal window' // copyStyles(document, this.externalWindow.document) // update the state in the parent component if the user closes the // new window this.externalWindow.addEventListener('beforeunload', () => { this.props.closeWindowPortal() }) } componentWillUnmount () { // This will fire when this.state.showWindowPortal in the parent component becomes false // So we tidy up by just closing the window this.externalWindow.close() } render () { // STEP 2: append props.children to the container <div> that isn't mounted anywhere yet return ReactDOM.createPortal(this.props.children, this.containerEl) } } export default class ProjectTable extends Component { constructor (props) { super(props) this.state={showWindowPortal:false} this.toggleWindowPortal = this.toggleWindowPortal.bind(this) this.closeWindowPortal = this.closeWindowPortal.bind(this) } static propTypes = { data: PropTypes.object.isRequired, loginId: PropTypes.string.isRequired } componentDidMount () { window.addEventListener('beforeunload', () => { this.closeWindowPortal() }) } toggleWindowPortal () { this.setState({showWindowPortal: !this.state.showWindowPortal}) } closeWindowPortal () { this.setState({showWindowPortal: false}) } render () { return ( <div> <div> <p>This div is just for testing click here to see the portal</p> { this.state.showWindowPortal && ( <MyWindowPortal closeWindowPortal={this.closeWindowPortal}> <button onClick={() => this.closeWindowPortal()} > Close </button> </MyWindowPortal> ) } <button onClick={this.toggleWindowPortal}> {this.state.showWindowPortal ? 'Close the' : 'Open a'} Portal </button> </div> </div> ) } } 我有一个带有可观察数组的菜单,但下面的所有项目都是&#39;或者&#39;降低&#39;在树上是正常的&#39;对象而不是可观察的对象。

我见过vm.menuitems(menuitemsfromserver)方法,但我无法理解它。 模型是相同的,唯一的区别是一个由可观察(-arrays)和另一个纯javascript对象组成。

1 个答案:

答案 0 :(得分:1)

有一个特别针对该案例制作的插件:http://knockoutjs.com/documentation/plugins-mapping.html

从其文档:

// Every time data is received from the server:
ko.mapping.fromJS(data, viewModel);
  

对象的所有属性都将转换为可观察对象。如果更新将更改该值,则它将更新observable。

     

将数组转换为可观察数组。如果更新会更改项目数,则会执行相应的添加/删除操作。它还会尝试保持顺序与原始JavaScript数组相同。

在您的情况下,代码看起来像:

ko.mapping.fromJS(menuitemsfromserver, vm.menuitems)

它将迭代所有属性和 menuitemsfromserver 的所有数组,并将它们转换为可观察对象。

最近没有积极维护插件,如下所示:https://github.com/SteveSanderson/knockout.mapping,但为了这个目的,它仍然是一个有用的代码。