Reactjs 如何正确使用typescript中的工厂方法
好吧,这是一个很难回答的问题,让我们看看我是否能正确地解释我自己 在Sharepoint中,ListItem默认具有以下属性:id、标题、createdby、createddate、modifiedby、modifieddate 但是您可以创建包含更多列的自定义列表,但它们继承自基本列表,因此任何新列都将添加到以前的列中 我的想法是使用typescript在Sharepoint Framework中创建一个通用解决方案,并能够使用Office UI Fabric Details列表组件从任何列表中读取和呈现: 所以我从模型开始: 列表项Reactjs 如何正确使用typescript中的工厂方法,reactjs,typescript,design-patterns,sharepoint,Reactjs,Typescript,Design Patterns,Sharepoint,好吧,这是一个很难回答的问题,让我们看看我是否能正确地解释我自己 在Sharepoint中,ListItem默认具有以下属性:id、标题、createdby、createddate、modifiedby、modifieddate 但是您可以创建包含更多列的自定义列表,但它们继承自基本列表,因此任何新列都将添加到以前的列中 我的想法是使用typescript在Sharepoint Framework中创建一个通用解决方案,并能够使用Office UI Fabric Details列表组件从任何列表
export class ListItem {
constructor(
public id: string,
public title: string,
public modified: Date,
public created: Date,
public modifiedby: string,
public createdby: string,
) { }
}
DirectoryListItem.ts
import {ListItem} from './ListItem';
export class DirectoryListItem extends ListItem {
constructor(
public id: string,
public title: string,
public modified: Date,
public created: Date,
public modifiedby: string,
public createdby: string,
public firstName: string,
public lastName: string,
public mobileNumber: string,
public internalNumber: string,
) {
super(id, title, modified, created, modifiedby, createdby);
}
}
AnnouListItem.ts
import {ListItem} from './ListItem';
export class AnnouncementListItem extends ListItem {
constructor(
public id: string,
public title: string,
public modified: Date,
public created: Date,
public modifiedby: string,
public createdby: string,
public announcementBody: string,
public expiryDate: Date
) {
super(id, title, modified, created, modifiedby, createdby);
}
}
等等
然后,我创建了一个只包含一个方法的ListItemFactory,您可以看到它返回一个ListItem数组
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
import { IWebPartContext } from '@microsoft/sp-webpart-base';
import {ListItem} from './models/ListItem';
export class ListItemFactory{
public _getItems(requester: SPHttpClient, siteUrl: string, listName: string): ListItem[] {
let items: ListItem[];
requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`,
SPHttpClient.configurations.v1,
{
headers: {
'Accept': 'application/json;odata=nometadata',
'odata-version': ''
}
})
.then((response: SPHttpClientResponse): Promise<{ value: ListItem[] }> => {
return response.json();
})
.then((response: { value: ListItem[] }): void => {
items= response.value;
});
return items;
}
}
从'@microsoft/sp http'导入{SPHttpClient,SPHttpClientResponse};
从'@microsoft/sp webpart base'导入{IWebPartContext};
从“./models/ListItem”导入{ListItem};
导出类ListItemFactory{
public _getItems(请求者:SPHttpClient,siteUrl:string,listName:string):ListItem[]{
let items:ListItem[];
requester.get(`${siteUrl}/\u-api/web/lists/getbytitle(`${listName}'))/items?$select=Title,Id`,
SPHttpClient.configurations.v1,
{
标题:{
“接受”:“application/json;odata=nometadata”,
“odata版本”:”
}
})
.然后((回复:SPHttpClientResponse):Promise=>{
返回response.json();
})
.then((响应:{value:ListItem[]}):void=>{
项目=响应值;
});
退货项目;
}
}
其他工厂看起来也很相似:
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
import {ListItemFactory} from './ListItemFactory';
import {ListItem} from './models/ListItem';
import {DirectoryListItem} from './models/DirectoryListItem';
export class DirectoryListItemFactory extends ListItemFactory {
public _getItems(requester: SPHttpClient, siteUrl: string, listName: string): DirectoryListItem[] {
let items: DirectoryListItem[];
requester.get(`${siteUrl}/_api/web/lists/getbytitle('${listName}')/items?$select=Title,Id`,
SPHttpClient.configurations.v1,
{
headers: {
'Accept': 'application/json;odata=nometadata',
'odata-version': ''
}
})
.then((response: SPHttpClientResponse): Promise<{ value: DirectoryListItem[] }> => {
return response.json();
})
.then((response: { value: DirectoryListItem[] }): void => {
items= response.value;
});
return items;
}
}
从'@microsoft/sp http'导入{SPHttpClient,SPHttpClientResponse};
从“/ListItemFactory”导入{ListItemFactory};
从“./models/ListItem”导入{ListItem};
从“./models/DirectoryListItem”导入{DirectoryListItem};
导出类DirectoryListItemFactory扩展ListItemFactory{
public _getItems(请求者:SPHttpClient,siteUrl:string,listName:string):DirectoryListItem[]{
let items:DirectoryListItem[];
requester.get(`${siteUrl}/\u-api/web/lists/getbytitle(`${listName}'))/items?$select=Title,Id`,
SPHttpClient.configurations.v1,
{
标题:{
“接受”:“application/json;odata=nometadata”,
“odata版本”:”
}
})
.然后((回复:SPHttpClientResponse):Promise=>{
返回response.json();
})
.then((响应:{value:DirectoryListItem[]}):void=>{
项目=响应值;
});
退货项目;
}
}
唯一的区别是,它不返回ListItem,而是返回DirectoryListItem数组
在那之前,一切对我来说都很清楚,然后我有了我的组件,它将作为参数之一接收,列表名
请密切注意readItems方法和render方法,我的问题集中在这里
import * as React from 'react';
import styles from './FactoryMethod.module.scss';
import { IFactoryMethodProps } from './IFactoryMethodProps';
import { IFactoryMethodCrudState } from './IFactoryMethodCrudState';
import { ListItem } from './models/ListItem';
import { escape } from '@microsoft/sp-lodash-subset';
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
import { ListItemFactory} from './ListItemFactory';
import { AnnouncementListItemFactory} from './AnnouncementListItemFactory';
import { DirectoryListItemFactory} from './DirectoryListItemFactory';
import { NewsListItemFactory} from './NewsListItemFactory';
import { TextField } from 'office-ui-fabric-react/lib/TextField';
import {
DetailsList,
DetailsListLayoutMode,
Selection
} from 'office-ui-fabric-react/lib/DetailsList';
import { MarqueeSelection } from 'office-ui-fabric-react/lib/MarqueeSelection';
import { autobind } from 'office-ui-fabric-react/lib/Utilities';
let _items: any[];
let _columns = [
{
key: 'column1',
name: 'Name',
fieldName: 'name',
minWidth: 100,
maxWidth: 200,
isResizable: true
},
{
key: 'column2',
name: 'Value',
fieldName: 'value',
minWidth: 100,
maxWidth: 200,
isResizable: true
},
];
export default class FactoryMethod extends React.Component<any, any> {
private listItemEntityTypeName: string = undefined;
private _selection: Selection;
constructor(props: IFactoryMethodProps, state: IFactoryMethodCrudState) {
super(props);
/* this.state = {
status: this.listNotConfigured(this.props) ? 'Please configure list in Web Part properties' : 'Ready',
items: []
}; */
this._selection = new Selection({
onSelectionChanged: () => this.setState({ selectionDetails: this._getSelectionDetails() })
});
this.state = {
status: this.listNotConfigured(this.props) ? 'Please configure list in Web Part properties' : 'Ready',
items: _items,
selectionDetails: this._getSelectionDetails()
};
}
public componentWillReceiveProps(nextProps: IFactoryMethodProps): void {
this.listItemEntityTypeName = undefined;
this.setState({
status: this.listNotConfigured(nextProps) ? 'Please configure list in Web Part properties' : 'Ready',
items: []
});
}
public render(): React.ReactElement<IFactoryMethodProps> {
let { items, selectionDetails } = this.state;
return (
<div>
<div>{ selectionDetails }</div>
<TextField
label='Filter by name:'
onChanged={ this._onChanged }
/>
<MarqueeSelection selection={ this._selection }>
<DetailsList
items={ items }
columns={ _columns }
setKey='set'
layoutMode={ DetailsListLayoutMode.fixedColumns }
selection={ this._selection }
selectionPreservedOnEmptyClick={ true }
onItemInvoked={ this._onItemInvoked }
compact={ true }
/>
</MarqueeSelection>
</div>
);
}
private readItems(): void {
this.setState({
status: 'Loading all items...',
items: []
});
//Here its where we actually use the pattern to make our coding easier.
switch(this.props.listName)
{
case "List":
let factory = new ListItemFactory();
let listItems = factory._getItems(this.props.spHttpClient, this.props.siteUrl, this.props.listName);
this.setState({
status: `Successfully loaded ${listItems.length} items`,
items: listItems
});
break;
case "Announcements":
let announcementFactory = new AnnouncementListItemFactory();
let announcementlistItems = announcementFactory._getItems(this.props.spHttpClient, this.props.siteUrl, this.props.listName);
this.setState({
status: `Successfully loaded ${listItems.length} items`,
items: announcementlistItems
});
break;
case "News":
let newsFactory = new NewsListItemFactory();
let newsListItems = newsFactory._getItems(this.props.spHttpClient, this.props.siteUrl, this.props.listName);
this.setState({
status: `Successfully loaded ${listItems.length} items`,
items: newsListItems
});
break;
case "Directory":
let directoryFactory = new DirectoryListItemFactory();
let directoryListItems = directoryFactory._getItems(this.props.spHttpClient, this.props.siteUrl, this.props.listName);
this.setState({
status: `Successfully loaded ${listItems.length} items`,
items: directoryListItems
});
break;
default :
break;
}
}
private _getSelectionDetails(): string {
let selectionCount = this._selection.getSelectedCount();
switch (selectionCount) {
case 0:
return 'No items selected';
case 1:
return '1 item selected: ' + (this._selection.getSelection()[0] as any).name;
default:
return `${selectionCount} items selected`;
}
}
private listNotConfigured(props: IFactoryMethodProps): boolean {
return props.listName === undefined ||
props.listName === null ||
props.listName.length === 0;
}
@autobind
private _onChanged(text: any): void {
this.setState({ items: text ? _items.filter(i => i.name.toLowerCase().indexOf(text) > -1) : _items });
}
private _onItemInvoked(item: any): void {
alert(`Item invoked: ${item.name}`);
}
}
import*as React from'React';
从“./FactoryMethod.module.scss”导入样式;
从“/IFactoryMethodOps”导入{IFactoryMethodOps};
从“/IFactoryMethodCrudState”导入{IFactoryMethodCrudState};
从“./models/ListItem”导入{ListItem};
从'@microsoft/sp lodash subset'导入{escape};
从“@microsoft/sp http”导入{SPHttpClient,SPHttpClientResponse};
从“/ListItemFactory”导入{ListItemFactory};
从“/AnnouncementListItemFactory”导入{AnnouncementListItemFactory};
从“./DirectoryListItemFactory”导入{DirectoryListItemFactory};
从“./NewsListItemFactory”导入{NewsListItemFactory};
从“office ui fabric react/lib/TextField”导入{TextField};
进口{
详细列表,
DetailsListLayoutMode,
挑选
}来自“office ui fabric react/lib/DetailsList”;
从“office ui fabric react/lib/MarqueeSelection”导入{MarqueeSelection};
从“office ui fabric react/lib/Utilities”导入{autobind};
let_项目:任何[];
设_列=[
{
键:“column1”,
姓名:'姓名',
fieldName:'名称',
最小宽度:100,
最大宽度:200,
isResizable:对
},
{
键:“column2”,
名称:“值”,
字段名:“值”,
最小宽度:100,
最大宽度:200,
isResizable:对
},
];
导出默认类FactoryMethod扩展React.Component{
私有listItemEntityTypeName:string=未定义;
私人选择:选择;
构造函数(道具:IFactoryMethodOps,状态:IFactoryMethodCrudState){
超级(道具);
/*此.state={
状态:this.listNotConfigured(this.props)“‘请在Web部件属性中配置列表’:‘就绪’,
项目:[]
}; */
此。_选择=新选择({
onSelectionChanged:()=>this.setState({selectionDetails:this.\u getSelectionDetails()})
});
此.state={
状态:this.listNotConfigured(this.props)“‘请在Web部件属性中配置列表’:‘就绪’,
项目:_项目,
selectionDetails:这是。\ u getSelectionDetails()
};
}
公共组件将接收道具(nextrops:ifactorymethodrops):无效{
this.listItemEntityTypeName=未定义;
这是我的国家({
状态:this.listNotConfigured(nextrops)“‘请在Web部件属性中配置列表’:‘就绪’,
项目:[]
});
}
public render():React.ReactElement{
让{items,selectionDetails}=this.state;
返回(
{selectionDetails