SharePoint Framework 1.7 新功能(一)动态数据(Dynamic Data)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shrenk/article/details/84094468

SharePoint Framework 1.7版本发布了,带来了很多新功能,新功能的简介请参见这里

这篇博客介绍其中的新功能:动态数据(Dynamic Data)。

在SPFx1.7版本之前,SPFx不同的组件之间通信会比较麻烦,动态数据的功能就是为了解决SPFx组件之间通信的问题。

动态数据分为两个部分,一个是动态数据源,一个是数据接收者。动态数据源既可以是一个webpart也可以是一个扩展,同样数据接收者也一样,既可以是webpart也可以是一个扩展。这里我们使用两个webpart来展示一下如果发布和接受动态数据,也就是如何在webpart之间传递数据。

首先使用yeoman创建两个webpart,一个名为SourceWebpart作为动态数据源,用于发布数据,另一个名为TargetWebpart,用于接收数据。

创建完毕之后,使用Code打开项目,可以看到新创建的两个webpart。

我在SourceWebpart中画了一个黄色的区域,当鼠标点击黄色区域的时候,会将鼠标的x和y坐标发布出去。TargetWebpart接收坐标数据并显示在webpart上:

首先看一下SourceWebpart如何获取鼠标位置数据。创建一个IPoint接口,包含x和y两个成员。在“SourceWebpartWebPart”类中添加私有成员mousePosition用来保存鼠标位置数据,然后修改render方法,显示黄色区域,以及绑定onclick事件,代码如下:

export interface IPoint { //定义IPoint接口
  x: number;
  y: number;
}

export interface ISourceWebpartWebPartProps {
  description: string;
}

export default class SourceWebpartWebPart extends BaseClientSideWebPart<ISourceWebpartWebPartProps>
{  
  private mousePosition: IPoint;  //mousePosition用来保存鼠标位置数据

  public onMouseClick(e) {   //onMouseClick方法用来获取鼠标位置数据并保存在mousePosition中
    this.mousePosition = { x: e.clientX, y: e.clientY };
  }
  
  public render(): void {
    //显示黄色区域
    this.domElement.innerHTML = `
      <div id="webpartdiv" style="width: 700px; height: 200px; background-color: yellow">
        
      </div>`;
    
    //绑定onclick事件
    this.domElement.onclick=this.onMouseClick.bind(this);
  }

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

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

以上就完成了点击鼠标获取数据的部分,如果需要将数据发布出去,需要改造一下SourceWebpart,首先需要导入两个接口:

import { IDynamicDataCallables, IDynamicDataPropertyDefinition } from '@microsoft/sp-dynamic-data';

然后SourceWebpart继承IDynamicDataCallables接口:

export default class SourceWebpartWebPart extends BaseClientSideWebPart<ISourceWebpartWebPartProps>
                                          implements IDynamicDataCallables

每一个动态数据源都需要实现IDynamicDataCallables接口,这个接口定义如下:

export declare interface IDynamicDataCallables {
    /**
     * 定义数据源返回的数据名称以及类型
     */
    getPropertyDefinitions(): ReadonlyArray<IDynamicDataPropertyDefinition>;
    /**
     * 根据数据的id返回数据的值
     *
     */
    getPropertyValue(propertyId: string): any;
    /**
     * 根据数据的id返回注释信息(可以不实现)
     */
    getAnnotatedPropertyValue?(propertyId: string): IDynamicDataAnnotatedPropertyValue | undefined;
}

它包含两个必须实现的方法:getPropertyDefinitions和getPropertyValue方法。

getPropertyDefinitions用来定义数据源发布的数据类型,因为我们要发布鼠标位置信息,所以这个方法是这样实现的:


  public getPropertyDefinitions(): ReadonlyArray<IDynamicDataPropertyDefinition> {
    return [
      {
        id: 'x',
        title: 'Mouse-X'
      },
      {
        id: 'y',
        title: 'Mouse-y'
      }
    ];
  } 

定义了两个数据,x表示x坐标,id就是propertyId,这个id会在接下来的getPropertyValue方法中用到,title用来被其他webpart识别。

getPropertyValue方法的实现:

public getPropertyValue(propertyId: string): number {
    switch (propertyId) {
      case 'x':
        return this.mousePosition.x;
      case 'y':
        return this.mousePosition.y;
    }

    throw new Error('Bad property id');
  }

定义好数据之后,需要做两件事,一个是将这个webpart注册为一个数据源,另一个就是对外发布数据。,它们都是用上下文中的dynamicDataSourceManage对象。

将webpart注册为数据源是在onInit()方法中实现的:

protected onInit(): Promise<void> {
    //将webpart注册为动态数据源
    this.context.dynamicDataSourceManager.initializeSource(this);

    return Promise.resolve();
  }

而发布数据是在onMouseClick方法中实现的,当点击鼠标的时候,就会发布数据。onMouseClick方法修改如下:

public onMouseClick(e) {  //onMouseClick方法用来获取鼠标位置数据并保存在mousePosition中
    this.mousePosition = { x: e.clientX, y: e.clientY };
    this.context.dynamicDataSourceManager.notifyPropertyChanged('x');
    this.context.dynamicDataSourceManager.notifyPropertyChanged('y');
  }

到这里SourceWebpart的部分就结束了,完整代码如下:

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

import styles from './SourceWebpartWebPart.module.scss';
import * as strings from 'SourceWebpartWebPartStrings';

import { IDynamicDataCallables, IDynamicDataPropertyDefinition } from '@microsoft/sp-dynamic-data';

export interface IPoint { //定义IPoint接口
  x: number;
  y: number;
}

export interface ISourceWebpartWebPartProps {
  description: string;
}

export default class SourceWebpartWebPart extends BaseClientSideWebPart<ISourceWebpartWebPartProps>
                                          implements IDynamicDataCallables
{  
  private mousePosition: IPoint;  //mousePosition用来保存鼠标位置数据

  protected onInit(): Promise<void> {
    //将webpart注册为动态数据源
    this.context.dynamicDataSourceManager.initializeSource(this);

    return Promise.resolve();
  }

  public onMouseClick(e) {  //onMouseClick方法用来获取鼠标位置数据并保存在mousePosition中
    this.mousePosition = { x: e.clientX, y: e.clientY };
    this.context.dynamicDataSourceManager.notifyPropertyChanged('x');
    this.context.dynamicDataSourceManager.notifyPropertyChanged('y');
  }

  public getPropertyDefinitions(): ReadonlyArray<IDynamicDataPropertyDefinition> {
    return [
      {
        id: 'x',
        title: 'Mouse-X'
      },
      {
        id: 'y',
        title: 'Mouse-y'
      }
    ];
  } 

  public getPropertyValue(propertyId: string): number {
    switch (propertyId) {
      case 'x':
        return this.mousePosition.x;
      case 'y':
        return this.mousePosition.y;
    }

    throw new Error('Bad property id');
  }
  
  public render(): void {
    //显示黄色区域
    this.domElement.innerHTML = `
      <div id="webpartdiv" style="width: 700px; height: 200px; background-color: yellow">
        
      </div>`;

    //绑定onclick事件
    this.domElement.onclick=this.onMouseClick.bind(this);
  }

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

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

然后我们修改TargetWebpart来使用SourceWebpart发布的数据。

首先导入DynamicProperty对象,然后再webpart属性中添加动态属性:

import { DynamicProperty } from '@microsoft/sp-component-base';

export interface ITargetWebpartWebPartProps {
  description: string;
  x: DynamicProperty<number>;
  y: DynamicProperty<number>;
}

然后修改render方法,读取并显示动态数据:

public render(): void {
    
    const x: number | undefined = this.properties.x.tryGetValue();
    const y: number | undefined = this.properties.y.tryGetValue();
    console.log(x);
    this.domElement.innerHTML = `
      <div class="${ styles.targetWebpart }">
        <div class="${ styles.container }">
          <div class="${ styles.row }">
            <div class="${ styles.column }">
              <span class="${ styles.title }">TargetWebpart</span>
              <p class="${ styles.subTitle }">显示鼠标x和y坐标</p>
                <div>Mouse X: ${ x == undefined ? '0' : x }</div>
                <div>Mouse Y: ${ y == undefined ? '0' : y }</div>
            </div>
          </div>
        </div>
      </div>`;
  }

然后添加一个propertiesMetadata方法,来指定动态数据的类型:

protected get propertiesMetadata(): IWebPartPropertiesMetadata {
    return {
      'x': {
        dynamicPropertyType: 'number'
      },
      'y': {
        dynamicPropertyType: 'number'
      }
    };
  }

最后修改getPropertyPaneConfiguration方法,连接数据源:

protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          groups: [
            {
              groupFields: [
                PropertyPaneDynamicFieldSet({
                  label: 'Select data source',
                  fields: [
                    PropertyPaneDynamicField('x', {
                      label: 'Position x'
                    })
                  ]
                }),
                PropertyPaneDynamicFieldSet({
                  label: 'Select data source',
                  fields: [
                    PropertyPaneDynamicField('y', {
                      label: 'Position y'
                    })
                  ]
                })
              ]
            }
          ]
        }
      ]
    };
  }

TargetWebpart的完整代码如下:

import { Version } from '@microsoft/sp-core-library';
import {
  BaseClientSideWebPart,
  IPropertyPaneConfiguration,
  PropertyPaneTextField,
  IWebPartPropertiesMetadata,
  IPropertyPaneConditionalGroup,
  DynamicDataSharedDepth,
  PropertyPaneDynamicFieldSet,
  PropertyPaneDynamicField
} from '@microsoft/sp-webpart-base';
import { escape } from '@microsoft/sp-lodash-subset';

import styles from './TargetWebpartWebPart.module.scss';
import * as strings from 'TargetWebpartWebPartStrings';

import { DynamicProperty } from '@microsoft/sp-component-base';

export interface ITargetWebpartWebPartProps {
  description: string;
  x: DynamicProperty<number>;
  y: DynamicProperty<number>;
}

export default class TargetWebpartWebPart extends BaseClientSideWebPart<ITargetWebpartWebPartProps> {

  public render(): void {
    
    const x: number | undefined = this.properties.x.tryGetValue();
    const y: number | undefined = this.properties.y.tryGetValue();
    console.log(x);
    this.domElement.innerHTML = `
      <div class="${ styles.targetWebpart }">
        <div class="${ styles.container }">
          <div class="${ styles.row }">
            <div class="${ styles.column }">
              <span class="${ styles.title }">TargetWebpart</span>
              <p class="${ styles.subTitle }">显示鼠标x和y坐标</p>
                <div>Mouse X: ${ x == undefined ? '0' : x }</div>
                <div>Mouse Y: ${ y == undefined ? '0' : y }</div>
            </div>
          </div>
        </div>
      </div>`;
  }

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

  protected get propertiesMetadata(): IWebPartPropertiesMetadata {
    return {
      'x': {
        dynamicPropertyType: 'number'
      },
      'y': {
        dynamicPropertyType: 'number'
      }
    };
  }

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          groups: [
            {
              groupFields: [
                PropertyPaneDynamicFieldSet({
                  label: 'Select data source',
                  fields: [
                    PropertyPaneDynamicField('x', {
                      label: 'Position x'
                    })
                  ]
                }),
                PropertyPaneDynamicFieldSet({
                  label: 'Select data source',
                  fields: [
                    PropertyPaneDynamicField('y', {
                      label: 'Position y'
                    })
                  ]
                })
              ]
            }
          ]
        }
      ]
    };
  }
}

gulp serve启动本地工作台,添加两个webpart,然后打开TargetWebpart的配置面版(如果打不开需要刷新一下页面),可以看到在配置面板中,可以选择数据源连接。连接数据源之后,鼠标点击黄色区域,TargetWebpart就会显示鼠标的坐标。

完整代码:https://gitee.com/shrenk/spfx-dynamicdata

参考文档:https://docs.microsoft.com/en-us/sharepoint/dev/spfx/dynamic-data

猜你喜欢

转载自blog.csdn.net/shrenk/article/details/84094468