组件运行时 JS 文件

组件运行时 JS 文件名为

  • React 体系:“组件名.react.js”
  • Vue 体系:“组件名.vue”

文件采用标准 ES6 语法,编写组件运行时的渲染逻辑及内容。

基础文件内容

在运行时 JS 文件中的 Render 方法实现组件渲染

  • Render 方法中使用 React 语法
  • return 的内容就是显示的内容,属性参考组件官网说明
  • return 中的值变化后触发 Render 方法

React 体系文件内容

组件继承自 BaseComponent 类,引用运行时 CSS 文件,代码如下:

import React, { Fragment } from 'react';
import BaseComponent from 'components/pcx/BaseComponent';
import hoistNonReactStatic from 'hoist-non-react-statics';
import {组件名, 组件名2} from "antd";
import './css/组件名.css';

class 组件名Pro extends BaseComponent {
  render() {
    return <组件名 {...this.props}></组件名>
  }
}

export default hoistNonReactStatic(组件名Pro, 组件名);

Vue 体系文件内容

使用 JSX 语法,代码如下:

<script setup lang="jsx">
import { 组件名 ,组件名2} from "ant-design-vue";
import { useAttrs, useSlots, reactive, watch, inject ,isVNode} from "vue";
import { commonProps, omitProps, useRefData, useUse, useFireEvent, usePage, useVisible, componentRenderWrapper} from "vue_addon/core";

let props = defineProps({
  ...commonProps
})

let emits = defineEmits([]);
let fireEvent = useFireEvent(emits);
let attrs = useAttrs();
let slots = useSlots();

let use = useUse(props);
let refData = useRefData(props);

let 组件名ProRender = () => {
    let {...vSlots} = slots;
    let omittedProps = omitProps(props, commonProps)
    return <组件名 {...attrs} {...omittedProps} vSlots={vSlots}/>
};

</script>
<template>
  <组件名ProRender />
</template>

引用组件

在运行时 JS 文件中,可以引用系统组件、基础组件和第三方组件

引用系统组件

使用”import 组件名 from 组件路径“引用系统组件

例如:引用“输入框”组件,代码如下

// React 桌面端
import Input from "../../../antdpro/components/Input/Input.react";

// Vue 桌面端
import Input from "../../../antdv/components/Input/Input.vue";

// React 移动端
import Field from "../../../vantui/components/Field/Field.react";

// Vue 移动端
import Field from "../../../vant/components/Field/Field.vue";

引用基础组件

引用 antd 的组件,注意引用的不是系统提供的组件,没有绑定数据组件的能力。

例如:引用“输入框”组件,代码如下

import {Input} from "antd";
import {Input} from "ant-design-vue";

引用第三方组件

第三方组件的 node_modules 放到命名空间的 lib 目录下后,即可引用,示例代码如下

import ReactECharts from 'echarts-for-react';
import * as echarts from 'echarts';
import { createComponent } from "echarts-for-vue";

React 体系 API

组件继承自 BaseComponent 类,BaseComponent 类提供以下 API

方法 参数 说明
getRefData 获取绑定数据集或者绑定数据列的数据组件对象
getData 数据集 ID 通过数据集ID,获取数据组件对象
getRefValue 获取绑定数据列的值
setRefValue 设置绑定数据列的值
getLabelRefValue 获取绑定显示列的值
setLabelRefValue 设置绑定显示列的值
getUseProps 获取引用组件的属性对象
fireEvent 事件名称、事件对象、默认行为 派发组件事件
getPage 获取页面对象

获取组件属性

使用 this.props 获取组件的属性,示例代码如下

let { style, theme, externalThemeName, events } = this.props;

获取绑定数据组件对象

当组件定义了 bind:ref 或 bind:items 属性时,可通过 this.getRefData(); 方法,获取绑定数据集或绑定数据列对应的数据组件对象,方法定义如下

方法:
  getRefData()

返回值:
  数据组件对象

例如:“列表”组件的“绑定数据集”属性定义如下

{
    "List": {
        "properties": {
            "bind:items": {
                "type": "dataValue",
                "editor": "dataValueEditor",
                "label": "绑定数据集"
            }
    }
  }
}

在运行时 JS 文件中获取数据集对象,代码如下

class ListPro extends BaseComponent {
    render() {
        //获取绑定的数据集对象
        let data = this.getRefData();
        //调用数据集的 toJson 方法
        dataSource = data.toJson({ ui: true });
        return <List {...this.props}></List>;
    }
}

如果同时定义了 filter 过滤条件属性,代码如下

"filter": {
    "type": "function",
    "args": {
        "record": {
            "label": "行记录",
            "editor": "rowEditor",
            "editor-parameter": {
                "dataPath": "@bind:items"
            }
        }
    },
    "editor-parameter": {
        "isFilter": "false",
        "isForeachFilter": "true"
    },
    "label": "过滤条件"
},

在运行时 JS 文件中,获取满足过滤条件的数据,代码如下

        let dataObj = this.getRefData().toJson({ ui: true });
        if(this.props.filter){
            dataObj = dataObj.filter(this.props.filter);
        }

获取数据组件对象

当组件设置了某个属性是数据集 ID 时,可通过 this.getData(数据集ID); 方法获取数据组件对象,方法定义如下

方法:
  getData(dataId)

参数:
  dataId:字符串类型,数据集ID

返回值:
  数据组件对象

例如:“自动完成”组件定义搜索数据列,代码如下

{
    "AutoComplete": {
        "properties": {
            "searchRef": {
                "type": "dataRef",
                "label": "搜索数据列",
                "editor": "dataRef",
                "visible-condition":"@mode='search'",
                "required": "true"
            }
        }
    }
}

在运行时 JS 文件中,通过搜索数据列属性,获取搜索数据集并刷新数据,代码如下

class AutoCompletePro extends BaseComponent {

    onSearch(){
        let searchData = this.getData(this.searchDataId);
        searchData.refreshData();
    }

    render() {
        let props = this.props;
        if(this.mode === "search" && props['searchRef'] && props['suggestDataRef']){
            let [searchDataId,,searchDataColumn] = props['searchRef'].split(".");
            this.searchDataId = searchDataId;
            this.searchDataColumn = searchDataColumn;
        }
        let {options,...restProps} = this.props;

        return 
            return <AutoComplete >
                <Input.Search  onSearch={()=>{this.onSearch()}} />
            </AutoComplete>
    }
}

获取绑定数据列的值

当组件定义了 bind:ref 属性时,可通过 this.getRefValue(); 方法获取绑定数据列的值,方法定义如下

方法:
  getRefValue(serialize)

参数:
  serialize:布尔类型,日期类型是否序列化为字符串,默认是 false

返回值:
  值

例如:“滑动输入条”组件定义绑定数据列,代码如下

{
    "Slider": {
        "properties": {
            "bind:ref": {
                "type": "dataRef",
                "label": "绑定数据列",
                "required": "true"
            }
        }
    }
}

在运行时 JS 文件中,获取绑定数据列的值,代码如下

class SliderPro extends BaseComponent {
    handleChange = (value) => {
        this.fireEvent("onChange", value, () => {
            this.setRefValue(value);
        })
    }

    render() {
        let { value, ...others } = this.props;
        value = this.getRefValue();
        return <Slider  {...others} value={value}  onChange={this.handleChange} />
    }
}

设置绑定数据列的值

当组件定义了 bind:ref 属性时,可通过 this.setRefValue(); 设置绑定数据列的值,方法定义如下

方法:
  setRefValue(value) 

参数:
  value:设置的值

例如:“滑动输入条”组件定义绑定数据列,代码如下

{
    "Slider": {
        "properties": {
            "bind:ref": {
                "type": "dataRef",
                "label": "绑定数据列",
                "required": "true"
            }
        }
    }
}

在运行时 JS 文件中,设置绑定数据列的值,代码如下

class SliderPro extends BaseComponent {
    handleChange = (value) => {
        this.fireEvent("onChange", value, () => {
            this.setRefValue(value);
        })
    }

    render() {
        let { value, ...others } = this.props;
        value = this.getRefValue();
        return <Slider  {...others} value={value}  onChange={this.handleChange} />
    }
}

获取绑定显示列的值

当组件定义了 bind:labelRef 属性时,可通过 this.getLabelRefValue(); 获取绑定显示列的值,方法定义如下

方法:
  getLabelRefValue(serialize)

参数:
  serialize:布尔类型,日期类型是否序列化为字符串,默认是false

返回值:
  值

例如:“选择器”组件定义绑定显示列,代码如下

{
    "Select": {
        "properties": {
            "dataGroup": {
                "label": "数据绑定",
                "properties": {
                    "bind:labelRef": {
                        "type": "dataRef",
                        "label": "绑定显示列"
                    }
                }
            }
        }
    }
}

在运行时 JS 文件中,获取绑定显示列的值,代码如下

class SelectPro extends BaseComponent {
    constructor(props, context) {
        super(props, context);
        this.refData = this.getRefData();
        this.state = {
            value: this.getRefValue(),
            labelValue: this.getLabelRefValue()
        }
    }

    handleChange = (value, options) => {
        this.fireEvent("onChange", [value, options], () => {
            this.setRefValue(options?.value)
            this.setLabelRefValue(options?.label)
        })
    }

    render() {
        let { options, popupMatchSelectWidth = false, ...other } = this.props;
        let value = this.state.value;
        let label = this.state.labelValue;
        if (this.props.labelRefDataId) {
            let obj = {};
            (value != null && value !== '') && (obj.value = value);
            (label != null && label !== '') && (obj.label = label);
            if (Object.keys(obj).length > 0) {
                other.value = obj;
            }
        } else {
            (value != null && value !== '') && (other.value = value);
        }
        return <Select {...other} onChange={this.handleChange} onSelect={this.handleSelect}
        />;
    }
}

设置绑定显示列的值

当组件定义了 bind:labelRef 属性时,可通过 this.setLabelRefValue(); 设置绑定显示列的值

方法:
  setLabelRefValue(value)

参数:
  value:设置的值

例如:“选择器”组件定义绑定显示列,代码如下

{
    "Select": {
        "properties": {
            "dataGroup": {
                "label": "数据绑定",
                "properties": {
                    "bind:labelRef": {
                        "type": "dataRef",
                        "label": "绑定显示列"
                    }
                }
            }
        }
    }
}

在运行时 JS 文件中,设置绑定显示列的值,代码如下

class SelectPro extends BaseComponent {
    constructor(props, context) {
        super(props, context);
        this.refData = this.getRefData();
        this.state = {
            value: this.getRefValue(),
            labelValue: this.getLabelRefValue()
        }
    }

    handleChange = (value, options) => {
        this.fireEvent("onChange", [value, options], () => {
            this.setRefValue(options?.value)
            this.setLabelRefValue(options?.label)
        })
    }

    render() {
        let { options, popupMatchSelectWidth = false, ...other } = this.props;
        let value = this.state.value;
        let label = this.state.labelValue;
        if (this.props.labelRefDataId) {
            let obj = {};
            (value != null && value !== '') && (obj.value = value);
            (label != null && label !== '') && (obj.label = label);
            if (Object.keys(obj).length > 0) {
                other.value = obj;
            }
        } else {
            (value != null && value !== '') && (other.value = value);
        }
        return <Select {...other} onChange={this.handleChange} onSelect={this.handleSelect}
        />;
    }
}

获取引用组件的属性对象

当组件元信息引用了其他组件时,可通过 this.getUseProps(); 获取引用组件的属性对象,方法定义如下

方法:
  getUseProps(componentName, key, defaultValue) 

参数:
  componentName:字符串类型,组件名 
  key:字符串类型,在元信息文件中 uses 时定义的 key
  defaultValue:对象类型,默认值

返回值:
  对象类型,引用组件的属性对象

例如:“气泡确认框”组件元信息文件引用“文字提示”组件,设置 key 为 tooltip,代码如下

{
    "Popconfirm":{
        "uses": {
            "tooltip": {
                "label": "提示配置",
                "key": "tooltip",
                "componentName": "antdpro:Tooltip",
                "editor-parameter": {
                    "ignore-properties": [
                        "title"
                    ]
                }
            }
        }
    }
}

在运行时 JS 文件中获取引用组件 tooltip 的属性对象,代码如下

this.getUseProps("Tooltip","tooltip")

派发组件事件

在组件元信息文件中定义的事件,在运行时 JS 文件中调用 fireEvent 方法派发事件,方法定义如下

方法:
  fireEvent(eventName, event, defaultAction)

参数:
  eventName:字符串类型,事件名
  event:Event对象,事件对象
  defaultAction:函数类型,默认行为

例如:“分段控制器”组件定义了 onChange 事件,代码如下

{
    "Segmented": {
        "events": {
            "onChange": {
                "label": "选项变化",
                "data": [
                    {
                        "label": "选项值",
                        "name": "value"
                    }
                ]
            }
        }
    }
}

在运行时 JS 文件中,派发 onChange 事件,代码如下

class SegmentedPro extends BaseComponent {
    handleChange = (value) => {
        this.fireEvent("onChange", value, () => {
            this.setRefValue(value);
        });
    }

    render() {
        return <Segmented {...this.props} onChange={this.handleChange} />
    }
}

创建事件对象

在派发事件前,通过 CustomEvent 创建事件对象,用于定义事件参数,方法定义如下

方法:
  CustomEvent(eventName, eventParams)

参数:
  eventName:字符串类型,事件名
  eventParams:事件参数,格式如下
    {
      cancelable: true,//是否允许使用代码 event.preventDefault() 阻止默认行为
      detail: {//作为 event.detail 参数
        option: option
      }
    }

返回值:
  事件对象

例如:“图表”组件定义了 onBeforeSetOption 事件,用于开发者修改 option,代码如下

{
    "Echarts": {
        "events": {
            "onBeforeSetOption": {
                "label": "显示前",
                "data": [
                    "event"
                ],
                "option": {
                }
            }
        }
    }
}

在运行时 JS 文件中,提供开发者修改 option 的时机,代码如下

  • 创建事件对象,将 option 作为事件参数
  • 开发者在页面的组件事件中,通过 event.detail.option 获取并修改
  • 在 fireEvent 的默认行为中,将开发者设置的 option 写回组件内部
let beforeSetOptionEvent = new CustomEvent("onBeforeSetOption", {
    cancelable: true,
    detail: {
        option: option
    }
});
this.fireEvent("onBeforeSetOption", beforeSetOptionEvent, () => {
    option = beforeSetOptionEvent.detail.option;
});

获取页面对象

获取页面对象,从而获取配置上下文对象 configContext,调用 request 方法,方法定义如下

方法:
  getPage()

返回值
  页面对象

例如:“签名”组件中调用页面对象的 request 方法获取个人签名,代码如下

this.getPage().request({
    method: "GET",
    url,
    header: {
    },
    datatype: "json",
    success: (result = {}) => {
        if (result && result.data) {
            resolve(result && result.data.signature || null);
        } else {
            reject()
            throw new Error(msg);
        }
    },
    error: (result = {}) => {
        reject(result)
        throw new Error(msg);
    },
    complete: (result = {}) => {
    }
});

例如:“图表”组件获取页面对象中的配置上下文对象 configContext,代码如下

if (this.getPage().getCurrentTheme()) {//没有设置主题,根据门户皮肤,自动设置使用深色模式或浅色模式
    let colorTextBase = this.getPage().getCurrentTheme().token?.colorTextBase;
    let colorBgBase = this.getPage().getCurrentTheme().token?.colorBgBase;
    if (colorTextBase && !this.isDarkColor(colorTextBase) && colorBgBase && this.isDarkColor(colorBgBase)) {
        themeName = "dark";
    }
}

Vue 体系 API

组件通过引入 vue_addon/core 文件来获取 React 体系中对应的 Api。

import { useRefData, useUse, useFireEvent, usePage, } from "vue_addon/core";
方法 参数 说明
useRefData 获取绑定数据集或者绑定数据列的数据组件对象
useData 数据集 ID 通过数据集ID,获取数据组件对象
useUse 获取引用组件的属性对象
useFireEvent 事件名称、事件对象、默认行为 派发组件事件
usePage 获取页面对象

通过 useRefData 或 useData 方法获取的数据组件对象,提供下面4个方法

方法 参数 说明
getRefValue 获取绑定数据列的值
setRefValue 设置绑定数据列的值
getLabelRefValue 获取绑定显示列的值
setLabelRefValue 设置绑定显示列的值

获取组件属性

组件的属性定义在组件元信息文件中,属性分成两部分,一部分在 JS 中使用,使用后可传给组件,另一部分直接传给组件

  • 通过 defineProps 方法获取指定的组件属性,在 JS 文件中使用
  • 通过 useAttrs 方法获取其他属性,在 render 方法中直接传给组件
  • 对于在 defineProps 方法中加入的通用属性 commonProps,使用 omitProps 方法排除 commonProps 后,在 render 方法中传给组件使用。之所以需要排除是因为 Vue 对于多余的属性会输出警告
  • 通用属性 commonProps 有两个作用,一是将系统数据绑定属性拆分成3个属性,便于在 JS 文件中使用;二是一些通用属性无需定义。了解 commonProps 中的属性,参考 /tools/uix-web/vue_addon/core/utils.js 文件
    • bind:ref 拆分为 refDataId、refColumnName、refRow
    • bind:labelRef 拆分为 labelRefDataId、labelRefColumnName、labelRefRow
    • bind:items 无需定义,直接使用 items
    • bind:options 无需定义,直接使用 options,另外还提供了一个 optionsRefDataId 属性
    • optionsLabel 无需定义,直接使用 optionsLabel
    • optionsValue 无需定义,直接使用 optionsValue
//获取指定的属性和通用属性
let props = defineProps({
  text: {type: String},
  icon: {type: [Object, String]},
  iconPosition: {type: String},
  displayMode: {type: String},
  opLabel: {type: String},
  opIcon: {type: String},
  iconStyle: {type: Object},
  href: {type: String},
  ...commonProps
})
//获取其它属性
let attrs = useAttrs();
//获取指定属性中一部分属性
let {text, icon, iconPosition, displayMode, iconStyle, href, ...other} = props;
//从这一部分属性中排除通用属性
let omittedProps = omitProps(other, commonProps)
//将其它属性和排除后的属性传给组件
return <Button {...attrs} {...omittedProps}>{icon}</Button>

使用 defineProps 方法获取组件的属性

方法:
  defineProps({
    xxx: {type: xxx, default: xxx},
    ...commonProps})

参数:
  JSON 对象,key 是组件的属性名,value 是 JSON 对象,里面指定了组件属性的类型 type 和默认值 default。加入 commonProps 后,系统内置属性:bind:items、bind:ref、bind:options 无需定义

返回值:
  指定的属性和通用的属性

例如:在 Echarts 组件元信息文件中定义了 option、dataConfig、theme、bind:items、filter、events 等属性,使用 defineProps 方法获取组件的属性,加入了 commonProps,因此无需定义 bind:items,直接使用 items 即可,代码如下

import { commonProps, usePage, useRefData, useFireEvent } from "vue_addon/core";

let props = defineProps({
    option: { type: String },
    dataConfig: { type: String },
    theme: { type: String },
    filter: { type: Function },
    events: { type: String },
    ...commonProps
})

let { option, dataConfig, ...other } = props;

获取绑定数据组件对象

当组件有定义了 bind:ref 或 bind:items 属性时,可通过 useRefData(); 方法获取绑定数据集或者绑定数据列的数据组件对象,方法定义如下

方法:
  useRefData(props)

参数:
  props:组件的属性,通过 defineProps 方法获取的组件的属性

返回值:
  数据组件对象

例如:“列表”组件的“绑定数据集”属性定义如下

{
    "List": {
        "properties": {
            "bind:items": {
                "type": "dataValue",
                "editor": "dataValueEditor",
                "label": "绑定数据集"
            }
        }
    }
}

在运行时 JS 文件中获取数据集对象,代码如下

<script setup lang="jsx">
import { Fragment, cloneVNode, useAttrs, useSlots, withDirectives } from "vue";
import { useRefData, omitProps, useFireEvent, commonProps, useUse, usePage } from "vue_addon/core";

let props = defineProps({
  ...commonProps,
});

let refData = useRefData(props);

let ListProRender = () => {
  let { pureLoop, dataSource, loadMoreType, showEmpty, ...others } = props;
  let _slots = { ...slots };
  if (refData) {
    dataSource = refData.toJson({ ui: true }) || [];

    return (
      <List
        {...attrs}
        {...omittedProps}
        dataSource={dataSource}
        rowKey={rowKey}
        pagination={false}
        vSlots={_slots}
      ></List>
    );
  }
};
</script>
<template>
  <ListProRender />
</template>

如果同时定义了 filter 过滤条件属性,代码如下

"filter": {
    "type": "function",
    "args": {
        "record": {
            "label": "行记录",
            "editor": "rowEditor",
            "editor-parameter": {
                "dataPath": "@bind:items"
            }
        }
    },
    "editor-parameter": {
        "isFilter": "false",
        "isForeachFilter": "true"
    },
    "label": "过滤条件"
},

在运行时 JS 文件中,获取满足过滤条件的数据,代码如下

    let props = defineProps({
        option: { type: String },
        filter: { type: Function },
        dataConfig: { type: String },
        events: { type: String },
        theme: { type: String },
        ...commonProps
    })

    let refData = useRefData(props);
    let processDataSourceFilter = (filter, dataSource) => {
        if (typeof filter == "function") {
            dataSource = dataSource.filter(filter);
        }
        return dataSource;
    }
    let dataObj = refData.toJson({ ui: true });
    dataObj = processDataSourceFilter(props.filter, dataObj);

获取数据组件对象

当组件设置了某个属性是数据集 ID 时,可通过 useData(数据集ID); 方法获取数据组件对象,方法定义如下

方法:
  useData(dataId)
参数:
  dataId:字符串类型,数据集ID

返回值:
  数据组件对象

例如:“自动完成”组件定义搜索数据列,代码如下

{
    "AutoComplete": {
        "properties": {
            "searchRef": {
                "type": "dataRef",
                "label": "搜索数据列",
                "editor": "dataRef",
                "visible-condition":"@mode='search'",
                "required": "true"
            }
        }
    }
}

在运行时 JS 文件中,通过搜索数据列属性,获取搜索数据集并刷新数据,代码如下

<script setup lang="jsx">
import {AutoComplete,Pagination,Button,Input} from 'ant-design-vue';
import {SearchOutlined} from  '@ant-design/icons-vue';
import {Fragment, reactive, useAttrs, useSlots} from "vue";
import {commonProps,omitProps ,useRefData, useUse, useFireEvent,useData} from "vue_addon/core";

/**
 *  支持2种模式
 *
 *  1. 提示输入后搜索模式  search  最要使用场景
 *  2  提示输入后录入模式  input
 *  3. 原本自动完成的模式
 */

let props = defineProps({
  ...commonProps,
  mode: {
    type: String
  },
  searchRef: {
    type: String
  },
})
let searchDataId,searchDataColumn,suggestDataId,suggestDataMatchColumn;
if(props.mode === "search" && props['searchRef'] && props['suggestDataRef']){
  let [_searchDataId,,_searchDataColumn] = props['searchRef'].split(".");
  searchDataId = _searchDataId;
  searchDataColumn = _searchDataColumn;
}

let searchData = useData(searchDataId);

let onSearch = ()=>{
  searchData.refreshData();
}


let AutoCompleteProRender = ()=>{

  let {options,...restProps} = props;
  //根据mode自动决定子节点
  let children,childProps ;
  if(props.mode == "search"){
    childProps = use.getProps("Input",'search');
    let btnProps = use.getProps("Button",'search-btn');
    children = <Input {...childProps} />;
    let omittedProps = omitProps(restProps, commonProps)
    return <><AutoComplete
        {...attrs}
        vSlots={slots}
        {...omittedProps}
        onChange={(value)=>{
          state.searchValue = value;
        }}
        options={options}>
      {children}
    </AutoComplete>
      <Button  type="primary" icon={<SearchOutlined onClick={()=>{onSearch()}}/>}  {...btnProps}></Button>
    </>
  }
}
</script>
<template>
  <AutoCompleteProRender/>
</template>

获取绑定数据列的值

当组件定义了 bind:ref 属性时,可通过 data.getRefValue(); 方法获取绑定数据列的值,data 是通过 useRefData 或 useData 方法获取的数据组件对象,方法定义如下

方法:
  data.getRefValue()

返回值:
  值

例如:“滑动输入条”组件定义绑定数据列,代码如下

{
    "Slider": {
        "properties": {
            "bind:ref": {
                "type": "dataRef",
                "label": "绑定数据列",
                "required": "true"
            }
        }
    }
}

在运行时 JS 文件中,获取绑定数据列的值,代码如下

<script setup lang="jsx">
import {Slider} from 'ant-design-vue';
import {useAttrs, useSlots} from "vue";
import {commonProps, useRefData,omitProps, useUse, useFireEvent} from "vue_addon/core";

let props = defineProps({
  ...commonProps,
})
let emits = defineEmits(['change']);
let fireEvent = useFireEvent(emits);
let refData = useRefData(props);

let handleChange = (value) => {
  fireEvent("change",  value, () => {
    if(props.range){
      value = value.join(",")
    }
    refData?.setRefValue(value);
  })

}

let SliderProRender = ()=>{
  let {  value, range, ...others } = props;
  value = refData?.getRefValue() || value;
  return <Slider {...attrs} {...omittedProps}  range={range} value={value} onChange={handleChange} vSlots={slots}/>
}
</script>
<template>
  <SliderProRender/>
</template>

设置绑定数据列的值

当组件定义了 bind:ref 属性时,可通过 data.setRefValue(); 设置绑定数据列的值,data 是通过 useRefData 或 useData 方法获取的数据组件对象,方法定义如下

方法:
  data.setRefValue(value)

参数:
  value:设置的值

例如:“滑动输入条”组件定义绑定数据列,代码如下

{
    "Slider": {
        "properties": {
            "bind:ref": {
                "type": "dataRef",
                "label": "绑定数据列",
                "required": "true"
            }
        }
    }
}

在运行时 JS 文件中,设置绑定数据列的值,代码如下

<script setup lang="jsx">
import {Slider} from 'ant-design-vue';
import {useAttrs, useSlots} from "vue";
import {commonProps, useRefData,omitProps, useUse, useFireEvent} from "vue_addon/core";

let props = defineProps({
  ...commonProps,
})
let emits = defineEmits(['change']);
let fireEvent = useFireEvent(emits);
let refData = useRefData(props);

let handleChange = (value) => {
  fireEvent("change",  value, () => {
    if(props.range){
      value = value.join(",")
    }
    refData?.setRefValue(value);
  })

}

let SliderProRender = ()=>{
  let {  value, range, ...others } = props;
  value = refData?.getRefValue() || value;
  return <Slider {...attrs} {...omittedProps}  range={range} value={value} onChange={handleChange} vSlots={slots}/>
}
</script>
<template>
  <SliderProRender/>
</template>

获取绑定显示列的值

当组件定义了 bind:labelRef 属性时,可通过 data.getLabelRefValue(); 获取绑定显示列的值,方法定义如下

方法:
  data.getLabelRefValue()

返回值:
  值

例如:“选择器”组件定义绑定显示列,代码如下

{
    "Select": {
        "properties": {
            "dataGroup": {
                "label": "数据绑定",
                "properties": {
                    "bind:labelRef": {
                        "type": "dataRef",
                        "label": "绑定显示列"
                    }
                }
            }
        }
    }
}

在运行时 JS 文件中,获取绑定显示列的值,代码如下

let use = useUse(props);
let refData = useRefData(props);
let optionsData = useData(props.optionsRefDataId);
let state = reactive({
  value: refData.getRefValue(),
  labelValue: refData.getLabelRefValue(),
});

设置绑定显示列的值

当组件定义了 bind:labelRef 属性时,可通过 data.setLabelRefValue(); 设置绑定显示列的值

方法:
  data.setLabelRefValue(value)

参数:
  value:设置的值

例如:“选择器”组件定义绑定显示列,代码如下

{
    "Select": {
        "properties": {
            "dataGroup": {
                "label": "数据绑定",
                "properties": {
                    "bind:labelRef": {
                        "type": "dataRef",
                        "label": "绑定显示列"
                    }
                }
            }
        }
    }
}

在运行时 JS 文件中,设置绑定显示列的值,代码如下

let refData = useRefData(props);
let handleChange = (value, options) => {
  fireEvent("change", [value, options], () => {
    if (props.mode == "multiple" || props.mode == "tags") {
      if (value.length > 0) {
        refData.setRefValue(value.join(","));
        refData.setLabelRefValue(options.map((item) => item.label).join(","));
      } else {
        refData.setRefValue(null);
        refData.setLabelRefValue(null);
      }
    } else {
      refData.setRefValue(options?.value);
      refData.setLabelRefValue(options?.label);
    }
  });
};

获取引用组件的属性对象

当组件元信息引用了其他组件时,可通过 useUse(props).getProps(); 获取引用组件的属性对象,方法定义如下

方法:
  useUse(props).getProps(componentName, key, defaultValue)

参数:
  props:组件的属性,通过 defineProps 方法获取的组件的属性
  componentName:字符串类型,组件名 
  key:字符串类型,在元信息文件中 uses 时定义的 key
  defaultValue:对象类型,默认值

返回值:
  对象类型,引用组件的属性对象

例如:“气泡确认框”组件引用“文字提示”组件,设置 key 为 tooltip,代码如下

{
    "Popconfirm": {
        "uses": {
            "tooltip": {
                "label": "提示配置",
                "key": "tooltip",
                "componentName": "antdv:Tooltip",
                "editor-parameter": {
                    "ignore-properties": [
                        "title"
                    ],
                    "ignore-events": []
                }
            }
        }
    }
}

在运行时 JS 文件中获取引用组件 tooltip 的属性对象,代码如下

<script setup lang="jsx">
import {Popconfirm} from 'ant-design-vue';
import {commonProps,useRefData,useUse,omitProps} from "vue_addon/core";
let use = useUse(props);
let PopconfirmProRender = () => {
  let {cancelButtonProps={},okButtonProps={},...other} = props;
  Object.assign(other, use.getProps("Tooltip", 'tooltip', null));
  let omittedProps = omitProps(other, commonProps)
  return <Popconfirm {...attrs} {...omittedProps}  vSlots={slots} />
}
</script>
<template>
  <PopconfirmProRender/>
</template>

派发组件事件

在组件元信息文件中定义的事件,在运行时 JS 文件中调用 useFireEvent 方法派发事件,方法定义如下

方法:
  let emits = defineEmits([]);
  useFireEvent(emits)(eventName, event, defaultAction);

参数:
  eventName:字符串类型,事件名
  event:Event对象,事件对象
  defaultAction:函数类型,默认行为

例如:“分段控制器”组件定义了 onChange 事件,代码如下

{
    "Segmented": {
        "events": {
            "onChange": {
                "label": "选项变化",
                "data": [
                    {
                        "label": "选项值",
                        "name": "value"
                    }
                ]
            }
        }
    }
}

在运行时 JS 文件中,派发 onChange 事件,代码如下

<script setup lang="jsx">
import { Segmented } from "ant-design-vue";
import { useAttrs, useSlots, reactive, watch } from "vue";
import { commonProps, useRefData, omitProps, useData, useFireEvent } from "vue_addon/core";

let emits = defineEmits(["change"]);
let fireEvent = useFireEvent(emits);
let handleChange = (value) => {
  fireEvent("change", value, () => {
    refData.setRefValue(value);
  });
};
let SegmentedProRender = () => {
  let { ...vSlots } = slots;
  let omittedProps = omitProps(props, commonProps);
  return (
    <Segmented
      {...attrs}
      {...omittedProps}
      vSlots={vSlots}
      onChange={handleChange}
    />
  );
};
</script>
<template>
  <SegmentedProRender />
</template>

创建事件对象

在派发事件前,通过 CustomEvent 创建事件对象,用于定义事件参数,方法定义如下

方法:
  CustomEvent(eventName, eventParams)

参数:
  eventName:字符串类型,事件名
  eventParams:事件参数,格式如下
    {
      cancelable: true,//是否允许使用代码 event.preventDefault() 阻止默认行为
      detail: {//作为 event.detail 参数
        option: option
      }
    }

返回值:
  事件对象

例如:“图表”组件定义了 onBeforeSetOption 事件,用于开发者修改 option,代码如下

{
    "Echarts": {
        "events": {
            "onBeforeSetOption": {
                "label": "显示前",
                "data": [
                    "event"
                ],
                "option": {
                }
            }
        }
    }
}

在运行时 JS 文件中,提供开发者修改 option 的时机,代码如下

  • 创建事件对象,将 option 作为事件参数
  • 开发者在页面的组件事件中,通过 event.detail.option 获取并修改
  • 在 fireEvent 的默认行为中,将开发者设置的 option 写回组件内部
import { commonProps, usePage, useRefData, useFireEvent } from "vue_addon/core";
let emits = defineEmits(['beforeSetOption']);
let fireEvent = useFireEvent(emits);
let event = new CustomEvent("onBeforeSetOption", {
    cancelable: true,
    detail: { option: option }
});
fireEvent("beforeSetOption", event, () => {
    option = event.detail.option;
})

获取页面对象

获取页面对象,从而获取配置上下文对象 configContext,调用 request 方法,方法定义如下

方法:
  usePage()

返回值:
  页面对象

例如:“签名”组件中调用页面对象的 request 方法获取个人签名,代码如下

<script setup lang="jsx">

let $page = usePage();

let loadPersonSign = async (event) => {
  if (props.disabled) return;
  let sign = await getPersonSign();
  refData.setRefValue(sign);
};
let _personSign = undefined;
let getPersonSign = async () => {
  if (_personSign !== undefined) {
    return _personSign;
  }
  var personId = await getPersonId();
  var msg = i18n("加载个人签名出错");
  if (personId) {
    var url = "/entry/uaa/Users/" + personId + "?extInfo=true";
    _personSign = await new Promise((resolve, reject) => {
      $page.request({
        method: "GET",
        url,
        header: {},
        datatype: "json",
        success: (result = {}) => {
          if (result && result.data) {
            resolve((result && result.data.signature) || null);
          } else {
            reject();
            throw new Error(msg);
          }
        },
        error: (result = {}) => {
          reject(result);
          throw new Error(msg);
        },
        complete: (result = {}) => {},
      });
    });
  }

  return _personSign;
};
defineExpose({});
</script>
<template>
  <SignatureProRender />
</template>

例如:“图表”组件获取页面对象中的配置上下文对象 configContext,代码如下

if ($page.props.configContext) {//没有设置主题,根据门户皮肤,自动设置使用深色模式或浅色模式
    let colorTextBase = $page.props.configContext?.theme?.token?.colorTextBase;
    let colorBgBase = $page.props.configContext?.theme?.token?.colorBgBase;
    if (colorTextBase && !isDarkColor(colorTextBase) && colorBgBase && isDarkColor(colorBgBase)) {
        themeName = "dark";
    }
}

暴露操作和方法

在运行时 JS 文件中定义的方法,通过 defineExpose 方法向外暴露后,在页面的 JS 文件中方可调用。方法定义如下

方法:
  defineExpose({methodName})

参数:
  methodName:在运行时 JS 文件中定义的方法的方法名

例如:“对话框”组件的运行时 JS 文件中定义了 open 和 close 方法,用于打开和关闭对话框,并向外暴露,代码如下

let open = (config) => {
  state.controlledProps = without(state.controlledProps,"open");
  let src = config?.src;
  let params = config?.params;
  if (src) {
    state.controlledProps =  without(state.controlledProps,"pagePath");
    state.pagePath = src;
  }
  if(params){
    state.controlledProps =  without(state.controlledProps,"params");
    state.params = params;
  }
  let event = new CustomEvent("onOpen", {
    cancelable: true,
    detail: {pagePath: state.pagePath, params: state.params}
  });
  fireEvent("open", event, () => {
    state.pagePath = event.detail.pagePath;
    state.params = event.detail.params;
    state.open = true;
    state.modal = config?.modal || {};
  })
}

let close = (event) => {
  event = event || new CustomEvent("onClose", {
    cancelable: true
  })
  fireEvent("close", event, () => {
    state.open = false;
  });
}

defineExpose({
  open,
  close
})

例如:系统在 /tools/uix-web/vue_addon/core/use/useComp.js 文件的 useVisible 方法中定义了 show 和 hide 两个方法,用于显示和隐藏。“抽屉”组件调用 useVisible 方法获取 show 和 hide 两个方法,并向外暴露,代码如下

let [state, exposeInfo] = useVisible({ props, propName: "open" });
defineExpose(exposeInfo);

获取插槽

在组件设计时定义的插槽,通过 useSlots 方法获取。方法定义如下

方法:
  useSlots()

返回值:
  插槽

例如:“按钮”组件获取插槽,显示插槽,代码如下

import {useAttrs, useSlots, h} from "vue";
let slots = useSlots();
let ButtonProRender = () => {
    return (
        <Button {...attrs} {...omittedProps}>
          {text || slots}
        </Button>
    );
};

results matching ""

    No results matching ""