将没有 JS 框架的 SPFX TS 转换为 React TS

Transform a SPFX TS without JS framework to a React TS

我用 yo @microsoft/sharepoint 创建了一个 Web 部件来显示项目列表。 该解决方案是在没有 Javascript 框架的情况下创建的。

import { Version } from '@microsoft/sp-core-library';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import {
  IPropertyPaneConfiguration,
  PropertyPaneTextField
} from '@microsoft/sp-property-pane';
import { escape } from '@microsoft/sp-lodash-subset';

import styles from './GetSpListItemsWebPart.module.scss';
import * as strings from 'GetSpListItemsWebPartStrings';

import {
  SPHttpClient,
  SPHttpClientResponse   
} from '@microsoft/sp-http';
import {
  Environment,
  EnvironmentType
} from '@microsoft/sp-core-library';

export interface IGetSpListItemsWebPartProps {
  description: string;
}
export interface ISPLists {
  value: ISPList[];
}

export interface ISPList {
  ID:string;
  Title: string;
  Summary : string;
  NewsCategory: string;
  Created:string;


    AttachmentFiles:{
      Name:string;
      Url:string;
    ServerRelativeUrl: string;
    }



}

export default class GetSpListItemsWebPart extends BaseClientSideWebPart<IGetSpListItemsWebPartProps> {
  private _getListData(): Promise<ISPLists> {
    return this.context.spHttpClient.get(this.context.pageContext.web.absoluteUrl + "/_api/lists/GetByTitle('News')/items?$select=*&$expand=AttachmentFiles",SPHttpClient.configurations.v1)
        .then((response: SPHttpClientResponse) => {
        return response.json();
        });
    }
    private _renderListAsync(): void {

      if (Environment.type == EnvironmentType.SharePoint || 
               Environment.type == EnvironmentType.ClassicSharePoint) {
       this._getListData()
         .then((response) => {
           this._renderList(response.value);
         });
     }
   }



      public titleurl(query:string){
        var path="/Lists/News/DispForm.aspx?ID=";
        var currdir=this.context.pageContext.web.absoluteUrl;
       var result=currdir+path+query;


        return result;

      }

    private _renderList(items: ISPList[]): void {
      let html: string = '<table border=1 width=100% style="border-collapse: collapse;">';
      html += '<th>ID</th><th>Title</th> <th>Summary</th><th>Created</th><th>Attachments</th>';
      items.forEach((item: ISPList) => {
        html += `
        <tr>     
        <td>${item.ID}</td>       
            <td><a href="${this.titleurl(item.ID)}">${item.Title}</a></td>
            <td>${item.Title}</td>
            <td>${item.Created}</td>
            <td>
            <img src="${item.AttachmentFiles[0].ServerRelativeUrl}" width="300px" height="300px" />
            </td>

            </tr>
            `;
      });
      html += '</table>';

      const listContainer: Element = this.domElement.querySelector('#spListContainer');
      listContainer.innerHTML = html;
    }

  public render(): void {
    this.domElement.innerHTML = `
      <div class="${ styles.getSpListItems }">
        <div class="${ styles.container }">
          <div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${ styles.row }">
          <div class="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1">
          <span class="ms-font-xl ms-fontColor-white">Welcome to SharePoint Modern Developmennt</span>
          <p class="ms-font-l ms-fontColor-white">Loading from ${this.context.pageContext.web.title}</p>
          <p class="ms-font-l ms-fontColor-white">Retrive Data from SharePoint List</p>
        </div>
      </div> 
          <div class="ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}">
          <div>NEWS List Items</div>
          <br>
           <div id="spListContainer" />
        </div>
      </div>`;
      this._renderListAsync();
  }

  protected get dataVersion(): Version {
    return Version.parse('1.0');
  }

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('description', {
                  label: strings.DescriptionFieldLabel
                })
              ]
            }
          ]
        }
      ]
    };
  }
}

这部分渲染成功。

然后我创建了一个解决方案哟@microsoft/sharepoint 使用 React 选项。 我被困在如何呈现 HTML 文档上。 以前它用于 this.domElement,但它说 It is not in the class。 我试图创建另一个 class 来呈现似乎不成功。 如何打印结果?

import * as React from 'react';
import styles from './B.module.scss';
import { IBProps } from './IBProps';
import { escape } from '@microsoft/sp-lodash-subset';

import {
  SPHttpClient,
  SPHttpClientResponse   
} from '@microsoft/sp-http';
import {
  Environment,
  EnvironmentType
} from '@microsoft/sp-core-library';
import * as ReactDOM from 'react-dom';
export interface ISPLists {
  value: ISPList[];
}

export interface ISPList {
  ID:string;
  Title: string;
  Summary : string;
  NewsCategory: string;
  Created:string;


    AttachmentFiles:{
      Name:string;
      Url:string;
    ServerRelativeUrl: string;
    }



}



export default class B extends React.Component<IBProps, {}> {



  public render(): React.ReactElement<IBProps> {



    return (

      <div  className={ styles.b }>      
        <div id="spListContainer"></div>
        <div className={ styles.container }>
          <div className={ styles.row }>
            <div className={ styles.column }>
              <span className={ styles.title }>Welcome to SharePoint!</span>
              <p className={ styles.subTitle }>Customize SharePoint experiences using Web Parts.</p>
              <p className={ styles.description }>{escape(this.props.description)}</p>

            </div>
          </div>
        </div>
      </div>
    );
  }
}

export class shownews extends B{
  constructor(prop){
          super(prop); 

          public _getListData(): Promise<ISPLists> {
            return this.context.spHttpClient.get(this.context.pageContext.web.absoluteUrl + "/_api/lists/GetByTitle('News')/items?$select=*&$expand=AttachmentFiles",SPHttpClient.configurations.v1)
                .then((response: SPHttpClientResponse) => {
                return response.json();
                });
            }
            public _renderListAsync(): void {

              if (Environment.type == EnvironmentType.SharePoint || 
                       Environment.type == EnvironmentType.ClassicSharePoint) {
               this._getListData()
                 .then((response) => {
                   this._renderList(response.value);
                 });
             }
           }



              public titleurl(query:string){
                var path="/Lists/News/DispForm.aspx?ID=";
                var currdir=this.context.pageContext.web.absoluteUrl;
               var result=currdir+path+query;


                return result;

              }

            private _renderList(items: ISPList[]): void {

              let html: string = '<table border=1 width=100% style="border-collapse: collapse;">';
              html += '<th>ID</th><th>Title</th> <th>Summary</th><th>Created</th><th>Attachments</th>';
              items.forEach((item: ISPList) => {
                html += `
                <tr>     
                <td>${item.ID}</td>       
                    <td><a href="${this.titleurl(item.ID)}">${item.Title}</a></td>
                    <td>${item.Title}</td>
                    <td>${item.Created}</td>
                    <td>
                    <img src="${item.AttachmentFiles[0].ServerRelativeUrl}" width="300px" height="300px" />
                    </td>

                    </tr>
                    `;
              });
              html += '</table>';


              const listContainer = React.createElement('h1',{},html);
              ReactDOM.render(listContainer, document.getElementById('spListContainer'));
               this._renderListAsync();

            }

  }

}

我很抱歉如果有很多关于SPFX、REACT JS CRUD 操作的教程。 但是,我克隆它,尝试 npm install 或 npm i -g,none 的存储库对我有用。

2020-01-28

import * as React from 'react';
import styles from './A.module.scss';
import { IAProps } from './IAProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { PageContext } from "@microsoft/sp-page-context";
import { HttpClient, IHttpClientOptions, HttpClientResponse, SPHttpClient, ISPHttpClientOptions, SPHttpClientResponse } from '@microsoft/sp-http';

import {
  Environment,
  EnvironmentType
} from '@microsoft/sp-core-library';


export interface ISPLists {
  value: ISPList[];
};

export interface ISPList {
  ID:string;
  Title: string;
  Summary : string;
  NewsCategory: string;
  Created:string;
    AttachmentFiles:{
      Name:string;
      Url:string;
    ServerRelativeUrl: string;
    };

}


export default class A extends React.Component<IAProps, {}> {


  public test:any=[];
  public data:any=[];

  public geturl(query:string){
    var path="/Lists/News/DispForm.aspx?ID=";
    var currdir=this.props.pagecontext.web.absoluteUrl;
   var result=currdir+path+query;

    return result;

  }
  private getListData(){
    const opt: ISPHttpClientOptions = { headers: { 'Content-Type': 'application/json;odata=verbose' } };

    return this.props.SPHttpClient.get(this.props.pagecontext.web.absoluteUrl + "/_api/lists/GetByTitle('News')/items?$select=*&$expand=AttachmentFiles",SPHttpClient.configurations.v1,opt)
        .then((response: SPHttpClientResponse) => {
          response.json().then((json: any) => {


            for(let i=0;i<json.value.length;i++){
              this.data.push(<div><tr>
            <td>${json.ID}</td>
            <td><a href="${this.geturl(json.ID)}">${json.Title}</a></td>
            <td></td>
            <td>${json.Created}</td>
            <td><img src="${json.AttachmentFiles.ServerRelativeUrl}" width="300px" height="300px" /></td>
            </tr></div>);

              }
            });
          });
    }








     /*
  private renderList(item: ISPList[]): void {
         item.forEach((item: ISPList) => {
                       this.data.push(`<tr>
            <td>${item.ID}</td>
            <td><a href="${this.geturl(item.ID)}">${item.Title}</a></td>
            <td></td>
            <td>${item.Created}</td>
            <td><img src="${item.AttachmentFiles.ServerRelativeUrl}" width="300px" height="300px" /></td>
            </tr>`
                       );


                           })
                           console.log(this.data);


    };

    */
/*
    private push() {
      this.test.push(1);
      this.test.push(2);
      this.test.push(3);
      console.log(this.test);
    }
    */






  public render(): React.ReactElement<IAProps>{
    this.getListData();
    console.log(this.data);


     return (


      <div id="splist">


              TEST
        <table className={styles.container}>

          <tr>
        <th>ID</th><th>Title</th> <th>Summary</th><th>Created</th><th>Attachments</th>
        </tr>
        <tr>     
    <td></td>       
            <td><a href="${this.titleurl(item.ID)}">TITLE</a></td>
            <td></td>
            <td>Created</td>
            <td>
                 </td>

            </tr>

       {this.data} 

1234
        </table>
         </div>
    );
  }
}

2020-01-28 18:15

this.setState({ items:"<td>{item.ID}</td> 
<td>{item.Title}</td> 
<td>{item.Summary}</td> 
<td>{item.Created}</td> 
<td>{item.AttachmentFiles[0].ServerRelativeUrl}</td>" });

这个不行

this.Title.push(<span><td>{item.Title}</td></span>); 
this.Url.push(<span><td>{item.AttachmentFiles[0].ServerRelativeUrl}</td></span>); 

这个有效

this.ID.push(item.ID); /* this.Title.push(<span><td>{item.Title}</td></span>); this.Url.push(<span><td>{item.AttachmentFiles[0].ServerRelativeUrl}</td></span>); */ this.forceUpdate(); 

如果我使用数组并使用 .push 发送包含 HTML 标签的数据 以下屏幕截图显示了问题。

代码

 public renderList(item: ISPList[]): void {

          item.forEach((item: ISPList) => {

          this.data.push(<tr>);
          this.data.push(<td>{item.ID}</td>);
          this.data.push(<td>{item.Title}</td>);
          this.data.push(<td>{item.AttachmentFiles[0].ServerRelativeUrl}</td>);
          this.data.push(</tr>);
//some brackets...

2020-01-28 1956 TR 中的问题 TR 问题:如果我在一行中写入 HTML 标签和数据,标签将自行生成。但是在render方法中,我需要添加一个标签来包裹它,这会使我的输出格式不正确。

//some codes before to get the JSON data
 this.data.push(<tr>
            <td>{item.ID}</td>
            <td>{item.Title}</td>
            <td>{item.AttachmentFiles[0].ServerRelativeUrl}</td></tr>);
//some more codes

public render(): React.ReactElement<IAProps>{


     return (

      <div id="splist">

              TEST
        <table className={styles.container}>

          <tr>
            <th>ID</th>
            <th>Title</th>
          <th>Attachments</th>
          </tr>

         {this.data}

         </table>      
         </div>
    );
  }

首先,您需要根据要渲染的组件(具有道具或状态)来考虑您的解决方案。在您的解决方案的上下文中,您可以创建一个组件让我们说:'GetandRenderListItems.tsx' 并执行所有“_getListData()”操作。您可以在每次挂载组件后使用 'componentDidMount()' 生命周期钩子调用 _getListData() 函数。然后你需要编写 html 模板来呈现检索到的数据(所有你在 '_renderList()' 方法中所做的)看看下面的代码片段以获得一个想法:

     public render(): React.ReactElement<IyourcomponentsProps> {
    return (
     // your dynamic table html and you should not use inline style but define styles in 
       scss file and use them.
    );
  }

然后在您的 'yourwebpart.ts' 文件中,您可以在 render() 方法中渲染此组件:

     public render(): void {
    const element: React.ReactElement<IyourwebpartProps > = React.createElement(
      GetandRenderListItems,
      {
        description: this.properties.description,
       // similarly assign values to  other props
      }
    );

    ReactDom.render(element, this.domElement);
  }

希望这会有所帮助。

编辑

您可以使用 array.map() 例如要使用您的数组呈现 table,您可以编写类似的内容。

    public render () : React.ReactElement<IyourcomponentsProps> {
    return(
        <div className={styles.someStyle} >   
          <table className={styles.container}>
           <tr>
             <th>ID</th><th>Title</th> <th>Summary</th><th>Created</th 
             <th>Attachments</th>
           </tr>

               { yourArray.map(function(item,key){    
                  let url = this.titleurl(item.ID);
                return (<tr className={styles.rowStyle} key={key}>    //you can use key if you want to track index
         <td></td>           <td className={styles.someclass}><a href={url}>{item.Title}</a></td>    

                  </tr> ); 
              })}    

          </table>    
        </div>    


    );
}

我使用 .bind .map 函数来实现它。 为项目添加状态应该是下一个更新。 我在处理数组和打印时遇到了麻烦

整个组件.tsx 文件

import * as React from 'react';
import styles from './A.module.scss';
import { IAProps } from './IAProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { PageContext } from "@microsoft/sp-page-context";
import { HttpClient, IHttpClientOptions, HttpClientResponse, SPHttpClient, ISPHttpClientOptions, SPHttpClientResponse } from '@microsoft/sp-http';
import {
  Environment,
  EnvironmentType
} from '@microsoft/sp-core-library';

export interface ISPLists {
  value: ISPList[];
};

export interface Istate {
  ID:string;
  Title: string;
  isLoad?: boolean;
  Url:string;
    AttachmentFiles:{
      Name:string;
      Url:string;
    ServerRelativeUrl: string;

    };
}


export interface ISPList {
  ID:string;
  Title: string;
  Summary : string;
  NewsCategory: string;
  Created:string;
    AttachmentFiles:{
      Name:string,
      Url:string,
    ServerRelativeUrl: string,
    };

}





/*
MAIN STARTS HERE
 2020-01-28
*/ 
export default class A extends React.Component<IAProps> {

constructor(props){
  super(props);

   this.loadNews();
   this.getListData=this.getListData.bind(this);
   this.geturl=this.geturl.bind(this);
   this.loadNews=this.loadNews.bind(this);
}



//variables to render html tags
private ID:any = [];
private Title:any = [];
private Url:any = [];
private data:any =[];
private tro:any=[]; //<tr>
private trc:any=[]; //</tr>
private tdo:any=[]; //<td>
private tdc:any=[]; //</td>




private loadNews(){
  this.getListData();
  /*
  this.getListData().then((response) => {
    this.renderList(response.value);

  });
  */ // when getlist and redner list are different functions
}



  public geturl(query:string){
    var path="/Lists/News/DispForm.aspx?ID=";
    var currdir=this.props.pagecontext.web.absoluteUrl;
   var result=currdir+path+query;
       return result;
   }

private tags(flag:boolean,first:boolean){
  // if first data add <tr>
  //if last data add </tr>
  //
  if (flag && first){
    document.getElementById("tro").innerHTML = <tr>;
  }else if (flag && !first){
   document.getElementById("trc").innerHTML = </tr>;
  }

}


   private  getListData() {
    const opt: ISPHttpClientOptions = { headers: { 'Content-Type': 'application/json;odata=verbose' } };
    this.props.SPHttpClient.get(this.props.pagecontext.web.absoluteUrl + "/_api/web/lists/getbytitle('News')/items?$select=*,AttachmentFiles&$expand=AttachmentFiles/Title&$orderby=ID desc", SPHttpClient.configurations.v1, opt).then((response: SPHttpClientResponse) => {
      response.json().then((json: any) => {
         for(let i=0;i<json.value.length;i++){
          var url=this.geturl(json.value[i].ID);
            if(i==0){ // add tags <tr> </tr>
              let flag=true; let first=true;
              this.tags(flag,first);


            }else if(i==json.value.length){
              let flag=false; let first=false;
              this.tags(flag,first);

            }
            this.data.push({ID:<td>{json.value[i].ID}</td>,
             Title:<td><a href={url} target="_blank">{json.value[i].Title}</a></td>,
             Url:<td><img src={json.value[i].AttachmentFiles[0].ServerRelativeUrl} width="300px" height="300px" /></td>
              });
             //   debugger;
                              this.ID.push(json.value[i].ID);

                             // this.Title.push(json.value[i].Title);
                              //this.Url.push(json.value[i].AttachmentFiles[0].absoluteUrl);
               this.forceUpdate(); 
              }//close for
        });// close response.json  
      });//close private getListData method

    }


              // json.value[i].Title}
       //json.value[i].AttachmentFiles[0].absoluteUrl}

       /*
      <td><a href="${this.geturl(json.ID)}">${json.value[i].Title}</a></td>
        <td></td>
        <td>${json.value[i].Created}</td>
        <td><img src="${json.AttachmentFiles.ServerRelativeUrl}" width="300px" height="300px" /></td>
         */











  public render(): React.ReactElement<IAProps>{
    console.log(this.data);
       return (
    <div className={styles.a} >
             <div className={styles.container} ></div>

         <span className={ styles.title }>News</span>
         <div className={styles.Table}>  
          <div className={styles.Heading}>  
         <table >
           <tr>  
              <div className={styles.Cell}>Title</div>  
              <div className={styles.Cell}>Created</div>  
              <div className={styles.Cell}>IMGSRC</div> 
           </tr>


            <div className={styles.Cell}>
              <span id="tro"></span>
            {this.data.map((data)=>
             <div> {data.ID}</div>
            )
            }
          </div>
          <div className={styles.Cell}>
            {this.data.map((data)=>
             <div> {data.Title}</div>
                      )
            }
          </div>
          <div className={styles.Cell}>
            {this.data.map((data)=>
             <div> {data.Url}</div>
            )
            }
              <span id="trc"></span>
          </div>








            </table>
                     </div>

                  </div>
                        </div>


    );
  }
}


render方法中.map函数如下

 <div className={styles.Cell}>
            {this.data.map((data)=>
             <div> {data.Url}</div>
            )
            }
              <span id="trc"></span>
          </div>

要访问数组中的数据对象,必须在定义 class.

后在构造函数中声明 .bind
export default class A extends React.Component<IAProps> {

constructor(props){
  super(props);

   this.loadNews();
   this.getListData=this.getListData.bind(this);
   this.geturl=this.geturl.bind(this);
   this.loadNews=this.loadNews.bind(this);
}



//variables to render html tags

private data:any =[];

中途。 这是原型。 一旦我能够提取数据,我就可以设置 CSS

的样式

感谢您的帮助。