§ Fox3.0前端框架-三十六计(PC篇)

标签(空格分隔): Fox


§ 前言

故名思义,本文是对我们开发过程中的便利工具的使用方法进行了收集和统一说明

§ 第一计:页面打开与关闭

§ 在tab容器中打开页面

方法: fox.custom.openPage 参数说明

参数 类型 说明
vm vue vue对象(this)
to String 目标路由(name/path)
params Object 路由参数
syncData Object 同步对象
onSuccess Function 页面成功打开回调函数
onDestroy Function 页面关闭(销毁)回调函数

例子

    //vm, to, params = {}, syncData
    fox.custom.openPage(this, '/example/page-sub', {}, this.$data)
1
2

§ 在tab容器中打开页面(with result)

方法: fox.custom.openPageWithResult 参数说明

参数 类型 说明
vm vue vue对象(this)
to String 目标路由(name/path)
params Object 路由参数
syncData Object 同步对象
callback Function 页面关闭(销毁)回调函数

回调函数callbak的参数为code和data,这两个参数可以在关闭页面的时候,通过fox.custom.closePageWith方法传递过来

例子

    //vm, to, params = {}, syncData
    fox.custom.openPageWithResult(this, '/example/page-sub', {}, this.$data, (code, data) => {
                if(code == 0) {
                    console.info(`调用成功 result:${JSON.stringify(data)}`)
                }else{
                    console.info(`调用失败 message:${data}`)
                }
            })   
1
2
3
4
5
6
7
8

§ 窗口模式打开页面

方法: fox.custom.appendPage 参数说明

参数 类型 说明
vm vue vue对象(this)
to String 目标路由(name/path)
attrs Object/String 窗口参数
params Object 路由参数
syncData Object 同步对象
onSuccess Function 页面成功打开回调函数
onDestroy Function 页面关闭(销毁)回调函数

参数attrs的字段类型为字符串的,则为窗口标志,如{'title':attrs},如果attrs为Json对象,那么框架不会做二次处理,直接把attrs传递给窗口

例子

    //vm, to, attrs, params = {}, syncData
    fox.custom.appendPage(this, '/example/page-sub', '标题', {}, this.$data)
1
2

§ 窗口模式打开页面(with result)

方法: fox.custom.appendPageWithResult 参数说明

参数 类型 说明
vm vue vue对象(this)
to String 目标路由(name/path)
attrs Object/String 窗口参数
params Object 路由参数
syncData Object 同步对象
callback Function 页面关闭(销毁)回调函数

1.参数attrs的字段类型为字符串的,则为窗口标志,如{'title':attrs},如果attrs为Json对象,那么框架不会做二次处理,直接把attrs传递给窗口 2.回调函数callbak的参数为code和data,这两个参数可以在关闭页面的时候,通过fox.custom.closePageWith方法传递过来

例子

     fox.custom.appendPageWithResult(this, 'example_page-sub', '子交易', {}, this.$data, (code, data) => {
                if(code == 0) {
                    console.info(`调用成功 result:${JSON.stringify(data)}`)
                }else{
                    console.info(`调用失败 message:${data}`)
                }
            })    
1
2
3
4
5
6
7

§ 关闭页面

方法: fox.custom.closePage 参数说明

参数 类型 说明
vm vue 子页面对象(this)

在子页面中调用,关闭vm对应的页面

例子

    //关闭当前页面
    fox.custom.closePage(this)
1
2

§ 关闭页面(with result)

方法: fox.custom.closePageWithResult 参数说明

参数 类型 说明
vm vue 子页面对象(this)
code String/Number 响应码
data Any 响应结果

在子页面中调用,关闭vm对应的页面

例子

    //关闭当前页面
    fox.custom.closePageWithResult(this, code, data)    
1
2

§ 第二计:父子页面数据传递

在页面打开的方法中,我们注意到有一个syncData参数,如下 tab打开

fox.custom.openPage(vm, to, params = {}, syncData)
1

窗口打开

fox.custom.appendPage(vm, to, attrs, params = {}, syncData)
1

syncData对象

承载着父子页面数据传递的责任,父亲页面打开子页面的时候,传入syncData对象。在孩子页面的fox_flow的created hook方法前把syncData对象中的数据,同步到孩子页面的vm.data中,在fox_flow的postSubmit方法前,把$data中的数据同步回syncData,注意的是,只根据syncData对象的key同步数据,而不会额外增加数据。由于数据同步是在fox_flow中同步的,所以子页面必须有fox_flow流程

![父子同步数据.png-79kB][1]

§ 数据同步扩展

父子页面使用syncData数据进行传递的时候,默认只同步key in syncData && key in data中的数据,如下: syncData:

    {
      name:'江成',
      phone:12345678
    }
1
2
3
4

子页面data:

    {
      name:'',
      sex:'',
    }
1
2
3
4

在默认机制中,只有name是双向同步的,而其它的key不同时存在syncData和data对象中,所以不会自动同步。

但是在需求复杂的场景中,不可避免有例外的情况,这时候我们只能手动获取syncData对象进行同步操作了.

方法: fox.custom.getSyncData 参数说明

参数 类型 说明
vm vue vue对象(this)

§ 第三计:组件返回number类型数据/自动trim字符串

在组件中,我们通过v-model获取的组件值,一般情况下都是字符串类型,但是后台往往需要我们返回number类型的数据,如年龄、序号等,怎么能方便的把字符类型的值转换为数值类型呢,可以参考下面是一个小技巧

v-model修饰符: .number - 输入字符串转为有效的数字 .trim - 输入首尾空格过滤

      <fox-text-item  v-verify="'require'" v-model.number="val" placeholder="请输入内容">数字</fox-text-item>
      
      <fox-text-item  v-verify="'require'" v-model.trim="val" placeholder="请输入内容">去空白字符</fox-text-item>
1
2
3

§ 第四计:校验那些事儿

框架使用指令v-verify来设置校验条,具体请看文档“Fox3.0前端框架-校验器”,如下:

    <fox-text-item v-verify="'require'" v-model="val" placeholder="请输入内容">必输</fox-text-item>
1

当然使用指令v-verify,还是比较麻烦的,所以在fox-*-item的组件中,我们可以通过更加简单的方式设置校验条件

框架同样对部分常用的内置校验提供了简化的写法,当然只适用于fox-*-item类组件

§ 必输(required/require)

     <fox-text-item require v-model="val6" placeholder="请输入内容">必输</fox-text-item>
1

§ 邮件(email)

    <fox-text-item require email v-model="val7"  placeholder="请输入内容">邮件</fox-text-item>
1

§ URL(url)

     <fox-text-item require url v-model="val8" placeholder="请输入内容"clearable>URL</fox-text-item>
1

§ 数字(number)

    <fox-text-item require number v-model="val9" type = "number" placeholder="请输入内容">数字</fox-text-item>
1

§ 动态设置校验校验规则

通过fox-page的verify-rule属性可以设置page内容组件的校验条件, 例如: html

 <fox-page :verify-rules="m_rules"> 
1

js

    data(){ 
       return { 
          m_rules:{
            'val12':['require'], 'val13':['require','email'] 
            } 
        } 
    }
1
2
3
4
5
6
7

通过代码设置,可以动态设置组件的校验的规则

§ 重置校验错误信息

fox_clearValidate 代码

    this.fox_clearValidate()
1

§ 通过API动态添加或删除校验规则

fox.custom.setValidate(node, verifyRule, message)
1

参数说明

参数 类型 说明
node ref 组件引用
verifyRlue Array 校验规则
message String 错误提示

如果verifyRule为undefined或空数组,代表删除改组件上的校验规则

例子: html

     <fox-group v-if="true" title="API设置"  column="2">
                 <template v-for="(item, index) in list2">
                   <fox-select-item :key="`item2_id_${index}`" @change="onChange(index, $event)" :source="m_types" v-model="item.type">是否必输</fox-select-item>
                   <fox-text-item :key="`item2_name_${index}`" ref="inputRef" :require = "item.type == '01'" v-model="item.name" placeholder="请输入内容">名称</fox-text-item>
                 </template>
               </fox-group>
1
2
3
4
5
6

js

    onChange(index, type) {
        console.info(`change index:${index}, type:${type}`)
        this.list2[index].type = type
        let rule
        if(type == '01') {
            rule = ['require']
        }
        fox.custom.setValidate(this.$refs.inputRef[index], rule)
    },
1
2
3
4
5
6
7
8
9

§ 指定校验提示的显示位置

默认情况下组件的校验提示会显示在组件的边上(下面),但是在登录页面等特殊页面,我们往往需要让提示显示在特定位置。为了实现该功能,我们需要执行下面两个步骤:

§ 步骤一

在组件上通过属性verify-message-place指定显示错误组件容器的id

§ 步骤二

定义显示组件,必须设置ID属性,且ID和verify-message-place指定的ID保持一致

例子:

     <fox-group v-if="true" title="指定消息显示位置"  column="3">
                 <fox-text-item verify-message-place="my_error_tip" v-verify="['require', 'who']" v-model="val18" placeholder="请输入内容">必输</fox-text-item>
                 <fox-text-item verify-message-place="my_error_tip" v-verify="['require', 'remote-who']" v-model="val19"  placeholder="请输入内容">邮件</fox-text-item>
                 <fox-input-row>
                    <div id="my_error_tip" class="my-error-tip"></div>
                 </fox-input-row>
               </fox-group>
1
2
3
4
5
6
7

§ 在流程fox_flow中设置校验条件

setCheckConditions 设置UI界面检查条件,如下

            /**
             * 设置检查条件
             * @param context
             */
            setCheckConditions(context){
                //触发check函数调用(必须执行context.resolve或context.reject)
                context.resolve()
            },
1
2
3
4
5
6
7
8

通过context.resolve(condtions)设置UI检查条件,并触发检查操作,conditions默认为空,也就是检查整个page的校验条件

§ 设置inclue条件,只检查某些组件

下面代码指定只检查v-model绑定的expression为val10,val11的组件

     /**
      * 设置检查条件
      * @param context
      */
      setCheckConditions(context){
           //触发check函数调用(必须执行context.resolve或context.reject)
            context.resolve({'include':['val10','val11']})
      },
1
2
3
4
5
6
7
8

§ 设置inclueGroup条件,只检查指定组下的组件(白名单)

下面代码指定只检查group name为firstGroup下面的组件

     /**
      * 设置检查条件
      * @param context
      */
      setCheckConditions(context){
           //触发check函数调用(必须执行context.resolve或context.reject)
            context.resolve({'includeGroup':['firstGroup']})
      },      
1
2
3
4
5
6
7
8

§ 设置exclue条件,排除检查某些组件

下面代码指定检查页面的时候,排除v-model绑定的expression为val10,val11的组件

    /**
       * 设置检查条件
       * @param context
       */
    setCheckConditions(context){
      //触发check函数调用(必须执行context.resolve或context.reject)
       context.resolve({'exclude':['val10','val11']})
    },
1
2
3
4
5
6
7
8

§ 设置exclueGroup条件,排除检查指定组下的组件

下面代码指定检查页面的时候,排除group name为secondGroup下面的组件

    /**
       * 设置检查条件
       * @param context
       */
    setCheckConditions(context){
      //触发check函数调用(必须执行context.resolve或context.reject)
       context.resolve({'exclude':['secondGroup']})
    },    
1
2
3
4
5
6
7
8

§ 设置ignoreHidden条件,是否忽略检查隐藏组件,默认为true

下面代码指定检查页面的时候,排除group name为secondGroup下面的组件

下面代码指定检查页面的时,是否忽略隐藏组件

    /**
       * 设置检查条件
       * @param context
       */
    setCheckConditions(context){
      //触发check函数调用(必须执行context.resolve或context.reject)
       context.resolve({'ignoreHidden':false})
    },   
1
2
3
4
5
6
7
8

§ 第五计:大Boss的专属-领域

在奇幻小说中,大boss或后期的主角往往会拥有领域这一大杀器,领域就是boss们临时创建的一方小天地,在这个专属的小天地中,boss可以有限度的改变天地法制,从而达到控场的目的。Fox框架中的领域(Domain)同样也是一个控场的大杀器。可以通过它对整个page的控制。 其中的的一个应用场景就在复核流程中

§ 获取domain

     //获取root domain
     let domain = getRootDomain(this)
1
2

API 函数getRootDomain参数

参数 类型 说明
vm Vue Object 当前vue对象

§ 设置整个page的控件为只读状态,但豁免指定v-model expression的控件

     //设置过滤model,如name,sze等
     domain.setOption("filter-models", filterModels)
     //设置全局只读
     domain.setOption("readonly", true)
1
2
3
4

API 函数setOption参数

参数 类型 说明
key String key
value Any value

§ 根据v-model expression设置page中控件的info、warn提示

§ setWarn

    let tip = '输入不一致'
    let tipIcon = ''
    //设置warn提示
    domain.setWarn(models, tip, tipIcon)
1
2
3
4

API

参数 类型 说明
modelNames Array 需要添加tip的控件对应的v-model
tip String 提示信息
tipIcon String 提示图标

§ setInfo

    let tip = '数据有更新'
    let tipIcon = ''
    //设置info提示
    domain.setInfo(models, tip, tipIcon)
1
2
3
4

API

参数 类型 说明
modelNames Array 需要添加tip的控件对应的v-model
tip String 提示信息
tipIcon String 提示图标

§ 为整个指定v-model expression的控件添加校验器

    //获取原来数据
    let originalData = fox.bus.get("sys_global", "originalData")
    //nodeVal, modelName, relateName, node
    domain.setCheck(filterModels,(val, name, relate, index, node)=>{
        console.info('value='+val+", name="+name+", relate="+relate+", index="+index)
        //获取原来的value
        let originalVal = fox.custom.getValue(originalData, relate)
        //获取当前的value
        let curVal = fox.custom.getValue(this.$data,relate)
        //判断两个value是否一致
        if(fox.isEqual(originalVal, curVal)){
            return undefined
        }else{
            return "输入不一致"
        }
    },tip, tipIcon)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

上述代码涉及了很多API,下面一个个给出解析

§ 方法domain.setCheck

参数 类型 说明
modelNames Array 需要添加检查器的控件对应的v-model
check Function 检查函数
tip String 提示信息
tipIcon String 提示icon

§ check检查函数

参数 类型 说明
nodeVal Array 需要添加检查器的控件对应的v-model
modelName Sting v-model对于的expression名称
relateName String 真实数据对于的key
node VNode 触发检查事件的控件

一般情况下,relateName和modelName是一致的,但是在某些情况下,relateName和modelName就不同下,如下

    <fox-table-column prop="address" label="地址">
         <template v-slot:default="scope">
             <fox-text-item v-model="scope.row.address" fox-model="tableData.address" fox-desc="个人信息.地址"></fox-text-item>
         </template>
    </fox-table-column>
1
2
3
4
5

A.上述是一个典型的table中使用控件的例子,template里面的内容是循环产生的,而我们无法通过该组件上v-model的expression获取vm.$data的数据,这种情况下指定实际需要检查的可以了(fox-model、fox-desc),上述例子通过特定的标签fox-model指定组件实际绑定的data中的key,通过fox-desc设置了组件的描述信息(用于配置界面)

B.如何通过v-model的expression对于的key获取data中的value呢? v-model的expression一般情况有几个种格式, 一层:name、sex 多层:person.name、param.info.name 可以通过fox.custom.getValue方法获取对应的value

1. fox.custom.getValue(data, 'name')
2. fox.custom.getValue(data, 'param.info.name')
1
2

§ 清理校验提示

§ 方法clearCheckTip

清理check校验器产生的警告提示

参数 类型 说明
checkModels Array/undefined 检查器的控件对应的v-model

如果checkModels为未定义,代表清理整个page的警告提示

例子

    // 情况校验提示
    onClearCheckTip() {
        const domain = fox.custom.getRootDomain(this)
        // 指定范围
        // domain.clearCheckTip(['checkedVal', 'extVal', 'val', 'combineValue'])
        // 全局范围
        domain.clearCheckTip()
    },
1
2
3
4
5
6
7
8

§ 手动触发check函数

check(checkModels)

参数 类型 说明
checkModels Array/undefined 检查器的控件对应的v-model

如果checkModels为未定义,代表触发page的校验

例子

        const domain = fox.custom.getRootDomain(this)
        // 指定范围
        // domain.check(['checkedVal', 'extVal', 'val', 'combineValue'])
        // 全局范围
        domain.check()
1
2
3
4
5

§ 第六计:表格数据格式化

从后台获取的表格数据,往往只是value,而不是显示的text,因此我们需要通过映射关系,把value翻译为text。下面的例子通过table column提供的formatter函数来实现上述需求

###例子

返回数据

    [{
          date: "2016-05-02",
          name: `王小虎`,
          sex:"01",
          address: "上海市普陀区金沙江路 1518 弄"
      },
      {
            date: "2016-05-02",
            name: `王小小`,
            sex:"02",
            address: "上海市普陀区金沙江路 1518 弄"
     }],
1
2
3
4
5
6
7
8
9
10
11
12

数据中的sex为value,我需要转换为性别(男/女)

映射文件 src/assets/mapping/sex.json

    {
      "01":"男",
      "02":"女"
    }
1
2
3
4

vue实现

步骤一.引入映射文件

import SexMapping from '@/assets/mapping/sex.json'
1

步骤二.实现formatter方法

     //格式化
     formatter(row,column){
          let val = row[column.property]
          let text = SexMapping[val] || val
          return text
      }
1
2
3
4
5
6

步骤三. table colum设置属性formatter

     <fox-table-item  id="fx_table_01" :content="tableData" page-index="1" :page-sizes="[5, 10, 20, 30]"
                                    :page-size="5" :show-header="true" :show-tool="true" ignore-empty-column="true">
                        <fox-table-column fixed prop="date" label="日期" width="180"></fox-table-column>
                        <fox-table-column prop="name" label="姓名" width="180"></fox-table-column>
                        <fox-table-column prop="address" label="地址"></fox-table-column>
                        <fox-table-column prop="sex" label="性别" :formatter="formatter"></fox-table-column>
                    </fox-table-item>
1
2
3
4
5
6
7

具体实现可以查看例子 src/example/table-item

§ 第七计:动态过滤选择框的选项

在项目实施过程中,某些选择框的选项列表根据前置条件进行改变。最简单的解决方案是通过改变source属性来实现,但是某些特殊的情况下,数据源是不变的,而是需要我们从当前的数据源中筛选出符合条件的值,例如,一个城市的选择框,前提条件分别为一线城市、名字带州的城市、所有城市,在这种情况下数据源是不变的,但是可以通过过滤器筛选出符合条件的选项。如下

§ html

      <fox-select-item placeholder="请选择" :source="m_policy" v-model="policy">城市类型</fox-select-item>
                    <fox-select-item source="@city.json" v-model="value17" :filter="m_filter">城市列表</fox-select-item>

1
2
3

§ js

通过监听城市类型变化,而改变城市列表选项的过滤器

     policy(newVal){
                    this.value17=""
                    if(newVal == '01'){
                        this.m_filter = (item)=>{
                            let list = ['北京', '上海', '广州', '深圳']
                            if(list.indexOf(item.text)!=-1){
                                return true
                            }
                            return false
                        }
                    }else if(newVal == '02'){
                        this.m_filter = (item)=>{
                            return item.text.indexOf('州')!=-1
                        }
                    }else{
                        this.m_filter = undefined
                    }
                },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

§ 第八计:常用公共方法

§ fox提供的工具类方法

§ 对象克隆

方法 extend(是否深度拷贝,dest,src1,src2,src3...)

§ 参数
属性 类型 说明
deep Boolean 是否深度拷贝
dest Object 克隆目标对象
src Object 源对象
§ 例子
    let target = {}
    let src = {
       name:'江成'
    }
    fox.extend(true, target, src)    
1
2
3
4
5

§ foxUI 提供的工具类方法

§ 前置条件(导入foxUI库)

    import {foxUI} from '@/assets/libs/fox-libs'
1

§ 获取可用工作空间width、height

    foxUI.getClientHeigth()
    foxUI.getClientWidth()
1
2

§ 获取元素的let、top、width、height

    foxUI.offsetTop(elm)    //top坐标
    foxUI.offsetLeft(elm)   //leftzuo b
    foxUI.offsetWidth(elm)  //width
    foxUI.offsetHeight(elm) //height
1
2
3
4

§ 空字符串判断

方法 isEmptyString

§ 金额格式化

方法 moneyFormat(value, decimalLength, autoPadding)

§ 参数
属性 类型 说明
value Number 待格式化value
decimalLength Number 小数点长度,默认0
autoPadding Boolean 是否自动填充小数位

§ 金额反格式化

方法 unMoneyFormat(value)
1
§ 参数
属性 类型 说明
value Number 待反格式化value

§ 大数字计算

§
foxUI.multiply
1
§
foxUI.divide
1
§
foxUI.add
1
§
foxUI.subtract
1

§ 例子

    // 相乘
    let n = foxUI.multiply(336662, 3)
    console.info(`multiply:${n}`)
    // 相除(最后一位为小数点)
    n = foxUI.divide(36223, 3, 2)
    console.info(`divide:${n}`)
    // 相加
    n = foxUI.add(3533, 15)
    console.info(`add:${n}`)
    // 相减
    n = foxUI.subtract(122223, 22321312)
    console.info(`subtract:${n}`)
1
2
3
4
5
6
7
8
9
10
11
12

§ 第九计:表格列宽根据列标题和内容自动调整

在定义fox-table-column的时候,如果没设置width属性,那么表格列宽会根据列标题和内容自动调整。当然这个功能也是有限制的,列的内容必须为纯文本。 另外我们还是通过表格的的最小列宽和最大列宽来限制自动调整的范围

table属性

参数 类型 说明
max-column-width Number 最大列宽
min-column-width Function 最小列宽

例子:

     <fox-table-item ref="tableFirst" border id="fx_table_01" :content="tableData" page-index="1" :page-sizes="[5, 10, 20, 30]"
                                    :page-size="5" :show-header="true" :show-tool="false" :ignore-empty-column="false"
                                    @row-click="rowClick" @current-change="currentChange" @selection-change="selectionChange"
                                    highlight-current-row :max-column-width="300" :min-column-width="90">
                        <fox-table-column type="selection" :selectable="allowSelect" ></fox-table-column>
                        <fox-table-column prop="date" label="日期"></fox-table-column>
                        <fox-table-column prop="name" label="姓名"></fox-table-column>
                        <fox-table-column prop="address" label="地址"></fox-table-column>
                        <fox-table-column prop="sex" label="性别" :formatter="formatter"></fox-table-column>
                    </fox-table-item>
1
2
3
4
5
6
7
8
9
10

§ 第十计:fox-group的column属性根据自动调整

当fox-group的宽度变化的时候,fox-x-item会缩小和拉伸以便进行自适应,如果组件的宽度缩小至最小宽度后minItemWidth: 250后,fox-group会动态调整cloumn,以便fox-x-item能够保持足够的宽度

配置方法如下

    src/main.js 配置minItemWidth,如下:
    //安装Fox UI
    Vue.use(foxUI, {
        //head bar height
        headBarHeight:(74+50), //(标题栏高度+面包屑标签高度)
        //foot bar height
        footBarHeight:0,
        //默认label宽度
        labelWidth:'138px',
        //输入item的最小宽度
        minItemWidth: 250,
        //label显示最大字数
        labelMaxCharCount:16
    })
1
2
3
4
5
6
7
8
9
10
11
12
13
14

§ 第十一计:巧用混入(Mixin),提供page的公共属性和公共方法

在具体应用,特别是大型应用中。往往每个vue page中有着同样的属性和方法,为了项目的简洁和维护性,我需要把这些公性的东西提取出来,混入机制无疑是一个合理的选择

例子:

步骤一,新增mixin对象,目录src/utils/custom/page-mixin.js

    // page 混入
    export let PageMixin = {
        // 注入
        inject: {
    
        },
        // 数据
        data() {
            return{
                publicName: '', // debug
            }
        },
        // 方法
        methods: {
            // debug
            sayHello() {
                console.info(`hello world ${this.publicName}`)
            },
        },
        // 计算方法
        computed: {
    
        },
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

步骤二,引用并装载mixin对象,如下

    import { PageMixin } from '@/utils/custom/page-mixin'
    
    xport default {
        name: 'example_group',
        // 混入
        mixins: [PageMixin],
    }
1
2
3
4
5
6
7

§ 第十二计:按钮权限控制

权限的控制方案

§ 步骤一

给予页面每个按钮设置一个唯一编号或者权限类型编号 例如(src/page/example/group) 唯一编号:

    <fox-button auth="003"  type="primary" @click="onSubmit">提交</fox-button>

1
2

权限类型:

    <fox-button auth="write"  type="primary" @click="onSubmit">提交</fox-button>
    
    <fox-button auth="read"  type="primary" @click="onCancel">取消</fox-button>
1
2
3

§ 步骤二

打开页面的时候设置该页面的权限范围,在父亲页面打开子页面的时候,子页面也同时继承父亲页面的权限范围

打开页面设置权限范围例子(page/common/frame/components/my-tags.vue):

     openPage(item, root, type) {
                // 激活index
                this.selected = item.path || item.name
                let route = {
                    path: item.path,
                    name: item.name,
                    params: item.params || {},
                    root: root,
                    success: item.success,
                    destroy: item.destroy,
                }
                // 权限范围
                const authScope = Symbol.for('authScope')
                // 设置权限范围
                route.params[authScope] = item.index
                if (type == 'to') {
                // 打开页面
                    this.$router.to(route)
                } else {
                // 打开页面
                    this.$router.open(route)
                }
                // 保存tag状态
                this.saveTagState()
            },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

继承父亲页面权限例子(utils/custom/page-helper.js)

      // 权限范围
        const authScope = Symbol.for('authScope')
        // 获取访问(继承父亲页面的权限范围)
        let scope = vm.$route && vm.$route.params && vm.$route.params[authScope]
        if(scope) {
            // 设置权限范围
            route.params.authScope = scope
        }
1
2
3
4
5
6
7
8

§ 步骤三

在登录后或者每个页面打开的时候,加入指定范围的权限列表

例子(utils/commons/controller/flows/normal-flow.js):

     /**
         * Vue对象创建,数据加载后,更改数据不会触发updated函数
         */
        created(session) {
            // 通过setTimeout模拟异步请求(实际情况下,不需要setTimeout,而是直接请求后端获取权限)
            setTimeout(() => {
                // 权限范围
                const authScope = Symbol.for('authScope')
                // 获取范围
                const scope = this.$route && this.$route.params && this.$route.params[authScope]
                // scope存在,并且该scope的权限不存在的情况
                if(scope && !foxUI.judge.hasAuths(scope)) {
                    foxUI.judge.addAuths(scope, ['006', '007', '008'])
                }
            }, 2000)
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

§ 第十三计:组件扩展规范

本节中的组件扩展范围是指对fox-*-item类组件进行二次封装,如下面所示:

例子A:

    <template>
      <fox-text-item @focus="onFocus" @blur="onBlur"  v-model="val" v-bind="$attrs" v-on="$listeners">
         <slot></slot>
      </fox-text-item>
    </template>
1
2
3
4
5

例子B

    <template>
      <fox-item>
        <fox-text-item @focus="onFocus" @blur="onBlur"  v-model="val" v-bind="$attrs" v-on="$listeners">
        </fox-text-item>
      </fox-item>
    </template>
1
2
3
4
5
6

§ 二次封装的规范如下:

§ 实现provide

    provide: {
        // custom component top level
        customRoot: true,
        // custom component scope
        customScope: true,
    },
1
2
3
4
5
6

§ 实现v-model

自定义组件必须实现v-model,而且对应的属性名必须为vlaue

如下:

      // 属性
        props: {
            // 值
            value: {
                required: false,
            },
        },
        // model
        model: {
            prop: 'value',
            event: 'change',
        },
1
2
3
4
5
6
7
8
9
10
11
12

§ 实现focus、blur、setValue的事件抛出

    <template>
      <fox-text-item @focus="onFocus" @blur="onBlur" @setValue="onSetValue" v-model="val" v-bind="$attrs" v-on="$listeners">
         <slot></slot>
      </fox-text-item>
    </template>

 

    // 方法
        methods: {
            onFocus(evt) {
                this.$emit('focus', evt)
            },
            onBlur(evt) {
                this.$emit('blur', evt)
            },
            onSetValue(evt) {
                this.$emit('setValue', evt)
            },
        },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

§ 使用v-verify指令的方式添加校验

对应自定义组件,要求使用指令的方式添加校验,而不是通过属性的方式,如下

      <fox-x-text-item v-verify="'require'" v-model="val14">
       必输
     </fox-x-text-item>
1
2
3

§ 完整例子

    <template>
      <fox-text-item @focus="onFocus" @blur="onBlur"  v-model="val" v-bind="$attrs" v-on="$listeners">
         <slot></slot>
      </fox-text-item>
    </template>
    
    <script>
    export default {
        name: 'fox-x-text-item',
        provide: {
            // custom component top level
            customRoot: true,
            // custom component scope
            customScope: true,
        },
        // 属性
        props: {
            // 值
            value: {
                required: false,
            },
        },
        // model
        model: {
            prop: 'value',
            event: 'change',
        },
        // 数据
        data() {
            return {
                val: this.value,
            }
        },
        // watch
        watch: {
            val(newVal, oldVal) {
                this.$emit('change', newVal)
            },
        },
        // 方法
        methods: {
            onFocus(evt) {
                this.$emit('focus', evt)
            },
            onBlur(evt) {
                this.$emit('blur', evt)
            },
        },
    }
    </script>
    
    <style scoped>
    
    </style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

§ 第十四计:日期工具类

Fox框架提供了对日期操作的工具类,我们可以使用日期工具类配合fox-date日期范围组件的过滤器来限制选中范围

§ 获取当天的0时0分0秒

fox.custom.getCurrentDay()
1

§ 获取当月的1日0时0分0秒

fox.custom.getCurrentMonth()
1

§ 判断日期是否在范围内(日)

fox.custom.inScope4Day(date, startDate, span)
1
§ 参数
属性 类型 说明
date Date 需要判断的日期
startDate Date 开始日期
span Number 跨度

span=1 当前开始日期之后一天的范围 span=-1 当前开始日期之前一天的访问

§ 判断日期是否在范围内(月)

fox.custom.inScope4Month(date, startDate, span)
1
§ 参数
属性 类型 说明
date Date 需要判断的日期
startDate Date 开始日期
span Number 跨度

span=1 当前开始日期之后一个月的范围 span=-1 当前开始日期之前一个月的访问

§ 完整例子

    // 获取当前月的日期(0时, 0分)
    let curDate = fox.custom.getCurrentDay()
    console.info(`start date:${curDate.toLocaleDateString()}`)
    
    // 获取当前月的日期(1日,0时, 0分)
    let curMonth = fox.custom.getCurrentMonth()
    console.info(`start month:${curMonth.toLocaleDateString()}`)
    console.info(`year:${curMonth.getFullYear()}, month:${curMonth.getMonth()}, day:${curMonth.getDay()}, hour:${curMonth.getHours()}, minutes:${curMonth.getMinutes()}, second:${curMonth.getSeconds()}`)
    
    // 判断日期是否在一个月范围内
    let date = new Date()
    let flag = fox.custom.inScope4Month(date, curMonth, 1)
    console.info(`日期是否在当前月范围:${flag}`)
    
    // 判断日期是否在7天范围内
    flag = fox.custom.inScope4Day(date, date, 7)
    console.info(`日期是否在7天范围:${flag}`)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

§ 第十五计:表格高度根据页面高度自适应

在查询条件+表格的界面中,如果我们需要表格的高度能自动撑满界面中剩余的空间,那么我们可以设置表格的高度为height="stretch",这样表格的高度就能根据剩余空间进行调整

例子页面:

     <fox-page>
            <!--footer bar必须在fox-content的面-->
            <fox-footer-bar v-if="true" align="right">  <!--align的值有left、center、right 默认为right-->
                <fox-button type="primary" @click="onSubmit">提交</fox-button>
              <fox-button @click="setChecker">设置检查器</fox-button>
                <fox-button @click="onCancel">取消</fox-button>
            </fox-footer-bar>
            <fox-content>
                <fox-group v-if="true" title="查询条件" column="3">
                  <fox-date-item
                      value-format="yyyy-MM-dd HH:mm:ss"
                      :end-date-offset = "1"
                      type="daterange"
                      range-separator=""
                      start-placeholder="开始日期"
                      end-placeholder="结束日期">日期</fox-date-item>
                  <fox-text-item>姓名</fox-text-item>
                  <fox-text-item>地址</fox-text-item>
                  <fox-number-item>电话</fox-number-item>
                </fox-group>
                <fox-group title="编辑表格">
                  <fox-x-tip-area v-model="tableData"></fox-x-tip-area>
                    <fox-table-item :content="tableData" page-index="1" :page-sizes="[5, 10, 20, 30]"
                                    :page-size="5" :show-header="true" height="stretch">
                        <fox-table-column prop="date" label="日期" width="180"></fox-table-column>
                        <fox-table-column prop="name" label="姓名" width="180"></fox-table-column>
                        <fox-table-column prop="address" label="地址">
                            <template v-slot:default="scope">
                                <fox-text-item v-model="scope.row.address" fox-model="tableData.address" fox-desc="个人信息.地址"></fox-text-item>
                            </template>
                        </fox-table-column>
                        <fox-table-column prop="phone" label="电话">
                            <template v-slot:default="scope">
                                <fox-text-item type="number" v-model="scope.row.phone" fox-model="tableData.phone" fox-desc="个人信息.电话"></fox-text-item>
                            </template>
                        </fox-table-column>
                    </fox-table-item>
                </fox-group>
            </fox-content>
        </fox-page>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

§ 第十七计:金额组件

金额组件使用类型:

§ 默认:

     <fox-money-item v-model="input">默认</fox-money-item>
1

§ 限制小数位

    <fox-money-item v-model="input2" decimal-length="2" unit="元">小数2</fox-money-item>
1

§ 自动填充小数位

    <fox-money-item v-model="input3" decimal-length="2" auto-adding="true" unit="元">自动填充</fox-money-item>
1

§ 不允许输入负数

    <fox-money-item v-model="input4" unit="元" min="0">非负数</fox-money-item>
1

§ 设置输入最小和最大值限制

    <fox-money-item v-model="input5" unit="元" min="5" max="100" required>最大最小值</fox-money-item>
1

§ 设置整数部分和小数部分的长度

    <fox-money-item v-model="input6" fox-model-invisible="true" unit="元" integer-length="5" decimal-length="3">53</fox-money-item>
1

§ 设置金额组件的转换率、转换精度和单位

组件中输入1,v-mode对应的值为1000.00

     <fox-money-item v-model="input7" unit="万元" rates="1000" decimal-length="4">单位万</fox-money-item>
1

§ 设置金额组件的转换率(小于1)、转换精度和单位

组件中输入100,v-mode对应的值为1

     <fox-money-item v-model="input8" unit="%" rates="0.01" precision="2">百分比</fox-money-item>
1

§ 第十八计:tab容器中的非激活tab页中组件校验错误显示解决方案

在tab容器中,需要校验的组件在非激活tab页中,如何让其显示出来?需要尊从下面规范

§ html结构规范

每个tab下面必须有一个fox-group

    <fox-tabs>
       <fox-tab-pane name="first">
          <fox-group name="group_first"></fox-group>
       </fox-tab-pane>
    </fox-tabs>
1
2
3
4
5

例子:

    <fox-tabs v-model="m_activeTabName" type="card">
                     <fox-tab-pane label="用户管理" name="first">
                       <fox-group  name="group_first">
                         <fox-text-item v-verify="'require'" v-model="val15" :class="mClass">用户管理</fox-text-item>
                       </fox-group>
                     </fox-tab-pane>
                     <fox-tab-pane label="配置管理" name="second">
                       <fox-group name="group_second">
                         <fox-select-item require :source="m_types" v-model="val16">用户管理</fox-select-item>
                       </fox-group>
                     </fox-tab-pane>
                     <fox-tab-pane label="角色管理" name="third">
                       <fox-group name="group_third">
                         <fox-text-item require v-model="val17">角色管理</fox-text-item>
                       </fox-group>
                     </fox-tab-pane>
    </fox-tabs>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

§ tab容器必须设置v-model

     <fox-tabs v-model="m_activeTabName" type="card">
     </fox-tabs>
1
2

§ tab页和group的命名规范

fox-group上必须设置name,其规范为group_tab页名称 例如 fox-tab-panel的名称为“first”(不能带下划xian),那么fox-group的名称就必须为group_first或者group_frist_xxx

§ 在显示错误校验的方法中调用fox.custom.showMeTheError

§ fox.custom.showMeTheError

§ 参数
属性 类型 说明
vm VM对象 vue对象引用
tabNameKey String tab容器对应的v-model属性名
checkResult Object checkResult 校验结果

例子(cancelSubmit节点中处理校验不通过情况)

    // 在没有tab容器的情况下,不需要添加下面代码
                    if(error && error.elementList) {
                        /**
                       * 切换对应校验错误的tab页
                       * @param vm
                       * @param tab容器对应的v-model属性名
                       * @param checkResult 校验结果
                       */
                        fox.custom.showMeTheError(this, 'm_activeTabName', res)
                    }
1
2
3
4
5
6
7
8
9
10
注意:在页面没有tab容器的情况下,就不要调用该方法了

§ 第十九计:大页面拆分方案

我们在开发过程中,我们偶尔会遇到大页面的开发,如一个页面中有几百个字段的情况,把完整的代码写在一个文件中会导致可读性差的问题。这样我们需要一个把大页面拆分为多个小文件的方案。具体例子(组合组件):example/parts/index.vue

§ 拆分原则

大页面的拆分原则是按照业务功能模块来拆分,保证每部分具有一定的独立性,尽量少的关联关系。如每个tab页或每个step作为一个单元

§ 目录结构

那么页面的拆分结构如何呢?我们以一个例子页面来说明

拆分前
├── parts                      
│   ├── index.vue               

拆分后
├── parts                      
│   ├── index.vue  
│   ├── subs
│   │   ├── sub-a.vue            
│   │   ├── sub-b-vue 
1
2
3
4
5
6
7
8
9
10

从上面拆分前后的比较来看,我们把在一个index.vue的代码,拆分到其子目录subs下面,分为sub-a.vue和sub-b.vue(子文件的命名可根据具体业务功能命名)

§ 页面规范

§ 主页面 index.vue

  • 引用子页面
  • 每个子页面必须设置一个name

§ 子页面 subs/*.vue

  • 子页面的根元素必须为fox-sub-page

§ 页面数据交换

§ 设置子页面数据

domain.setSubData(name, data)
1
§ 参数
属性 类型 说明
name 子页面名称 String
data json 数据

例子

            // 设置数据
            setData(name) {
                // 获取root domain
                const domain = fox.custom.getRootDomain(this)
                if(name == 'first') {
                    domain.setSubData(name, {
                        employedCompany: '胡花钱',
                        position: '高级玩家',
                        phone: '18620171653',
                        email: 'jiangcheng@yusys.com.cn',
                        address: '无忧岛',
                    })
                }else{
                    domain.setSubData(name, {
                        input: 123.45,
                        input2: '6666666',
                        input3: '12.12',
                        input4: '1',
                        input5: '2',
                    })
          
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

§ 获取子页面数据

let subData = domain.getSubData(name)
1
§ 参数
属性 类型 说明
name 子页面名称 String

例子

    // 获取数据
    getData(name) {
        // 获取root domain
        const domain = fox.custom.getRootDomain(this)
        // 获取对应的页面的data
        const data = domain.getSubData(name)
        console.info(`页面${name}数据:${JSON.stringify(data)}`)
    },
1
2
3
4
5
6
7
8

§ 获取子页面的某个属性的值

 let val = domain.getSubDataValue(name, key)
1
§ 参数
属性 类型 说明
name 子页面名称 String
key 属性名 String

例子

    // 获取value
    getValue(name, key) {
        // 获取root domain
        const domain = fox.custom.getRootDomain(this)
        let val = domain.getSubDataValue(name, key)
        console.info(`获取value name:${name}, key:${key}, value:${val}`)
    },
1
2
3
4
5
6
7

§ 设置子页面的某个属性的值

 domain.setSubDataValue(name, key, value)
1
§ 参数
属性 类型 说明
name 子页面名称 String
key 属性名 String
value 属性值 Any

例子

    // 设置value
    setValue(name, key, value) {
        // 获取root domain
        const domain = fox.custom.getRootDomain(this)
        domain.setSubDataValue(name, key, value)
    },
1
2
3
4
5
6

§ 获取所有子页面名称

let names = domain.getAllSubNames()
1

例子

    // 获取子页面名称
    getSubPageNames() {
        // 获取root domain
        const domain = fox.custom.getRootDomain(this)
        let names = domain.getAllSubNames()
        console.info(`sub page names:${JSON.stringify(names)}`)
    },
1
2
3
4
5
6
7

§ 获取所有子页面的数据

let datas = domain.getAllSubData()
1

例子

    // 获取子页面数据
    getSubPageDatas() {
        // 获取root domain
        const domain = fox.custom.getRootDomain(this)
        let datas = domain.getAllSubData()
        for(let key in datas) {
            console.info(`sub page name:${key}, data:${JSON.stringify(datas[key])}`)
        }
    },
1
2
3
4
5
6
7
8
9

§ 获取请求数据(主页面+子页面)

let reqData = fox.custom.getRequestData(this)
1
§ 参数
属性 类型 说明
vm Vue对象 Vue

例子

    // 获取请求数据
    getRequestData() {
        let reqData = fox.custom.getRequestData(this)
        console.info(`request data:${JSON.stringify(reqData)}`)
    },
1
2
3
4
5

§ 设置响应数据(主页面+子页面)

fox.custom.setResponseData(this, rspData)
1
§ 参数
属性 类型 说明
vm Vue对象 Vue
data 响应数据 json

例子

    // 设置响应数据
    setResponseData() {
        let rspData = {
            employedCompany: '古墓派',
            position: '小龙女',
            phone: '18620171653',
            email: 'dragon@yusys.com.cn',
            address: '绝情谷',
            input: 9999.99,
            input2: '99999',
            input3: '99999.99',
            input4: '999',
            input5: '9999',
        }
        fox.custom.setResponseData(this, rspData)
    },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

§ 重置数据(主页面+子页面)

fox.custom.resetData(this)
1
§ 参数
属性 类型 说明
vm Vue对象 Vue

例子

    // 重置数据
    resetData() {
        fox.custom.resetData(this)
    },
1
2
3
4

§ 第二十计:动态页面

平台提供了根据界面配置动态生成界面的支持,根据html页面的结构,我们的页面配置数据也是树状结构的。

├── fox-page                
│   ├── fox-header-bar 
│   ├── fox-footer-bar  
│   │   │   ├── fox-button
│   │   │   ├── fox-button
│   ├── fox-content
│   │   ├── fox-group
│   │   │   ├── fox-text-item
│   │   │   ├── fox-select-item
│   │   │   ├── fox-date-item
1
2
3
4
5
6
7
8
9
10

完整例子请查看: 1.example/dynamic/index.vue 2.example/dynamic-tabs/index.vue

§ 普通节点结构

页面配置的普通节点结构如下

      {
          name: '组件名称',
          key:'唯一key',
          model:'model值',
          directives: //指令集合
          [
             {
                 name: '指令名',
                 value: '指令value(常量/变量/函数)',
                 param: 'value函数的参数' //可选
              },
          ],
          attrs://常量属性
          {
             '属性key': '常量value',
          },
          props://动态属性
          {
             '属性key': '变量value(变量/函数)',
             'method_param_属性key名':'参数常量'//
          },
          on: //事件 
          {
              '事件名': '事件函数',
              'method_param_事件名':'参数常量' //可选
          },
          style:// html element style
          {
             'style key':'style value'
          }
          ref: '', // ref引用
          children: //孩子节点集合
          [
            {'text':'常量'}, //例如<text>innerText</text>
            {  //例如<text>{{innerValue}}</text>
               'variable':'变量(变量/函数)',
               'param':'variable函数的常量参数'//可选
             },
            {...}, //孩子组件配置
          ]
      },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

例如:

html(配置生成)

    <fox-group v-show="true" title="选择框" column="3">
      <fox-select-item v-model="val5" placeholder="请输入内容" :source="m_items" :disabled="false" @blur="onBlur" @visible-change= "onVisibleChange">普通数据源</fox-select-item>
    </fox-group>
1
2
3

配置

    {
         name: 'fox-group',
         directives: [
            {
               name: 'show',
               value: 'true',
            },
         ],
         attrs: {
             title: '选择框',
             column: '3',
         },
         on: {},
         ref: '',
         children: [
            {
               name: 'fox-select-item',
               model: 'val5',
               attrs: {
                    placeholder: '请输入内容',
               },
               props: {
                    source: 'm_items',
                    disabled: 'false',
               },
               on: {
                    blur: 'onBlur',
                    'visible-change': 'onVisibleChange',
               },
               ref: '',
               children: [
                    {
                        text: '普通数据源',
                    },
                ],
           },
        ],
    },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

§ slot节点结构

      {
          name: '组件名称',
          ..... //配置
          children: //孩子节点集合
          [
            {
                 slot: 'slot名称',
                 name: '组件名',
                 ......
            }
          ]
      },
1
2
3
4
5
6
7
8
9
10
11
12

例子

html(配置生成)

    <fox-number-item v-model="val4" placeholder="请输入内容" max="100" min="50" v-verify="'required'">
        <template v-slot:default>插槽</template>
        <template v-slot:append><div class="el-icon-more fox-x-more-btn" @click="moreAction"></div></template>
    </fox-number-item>
1
2
3
4

配置

    {
          name: 'fox-number-item',
          model: 'val4',
          attrs: {
               placeholder: '请输入内容',
               max:'100',
               min:'50',
           },
           props: {},
           on: {},
           ref: '',
           directives: [
               {
                   name: 'verify',
                   value: '"required"',
                },
            ],
            children: [
                {
                    text: '插槽',
                },
                {
                     slot: 'append',
                     name: 'div',
                     attrs: {
                        class: 'el-icon-more fox-x-more-btn',
                     },
                     on: {
                         click: 'moreAction',
                     },
                 },
            ],
    },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

§ 循环slot节点结构

对于v-for的支持 v-for=(item, index) in items

    {
       loop: true, // 循环标志
       items: '循环数组',
       children: [ //循环内容
          {
               slot: 'slot名称',
               slotScope: '循环item',
               key: 'key名称', //在循环中会自动加上index,如key名称_index
               name: '循环组件名',
               ......
          },
        ],
    },
1
2
3
4
5
6
7
8
9
10
11
12
13

例子 html(配置生成)

    <template v-for="(item, index) in myList">
        <fox-select-item :key="`item_type_${index}`" @change="onChange(item, index, $event)" :source="m_types" v-model="item.type">是否必输</fox-select-item>
        <fox-text-item :key="`item_name_${index}`" ref="inputRef" :require = "isRequired(item, index)" v-model="item.name" placeholder="请输入内容">名称</fox-text-item>
        <fox-button :key="`item_ops_${index}`" @click="onOperation(item, index)">{{getBtnText(item, index)}}</fox-button>
    </template>
1
2
3
4
5

配置

    {
        loop: true,
        items: 'myList',
        children: [
            {
               slot: 'default',
               slotScope: 'item',
               key: 'item_type',
               name: 'fox-select-item',
               model: 'item.type',
               attrs: {
                 placeholder: '请输入',
               },
               props: {
                 source: 'm_types',
               },
               on: {
                 change: 'onChange',
               },
               ref: '',
               children: [
                  {
                    text: '是否必输',
                  },
                ],
             },
             {
                 slot: 'default',
                 slotScope: 'item',
                 key: 'item_name',
                 name: 'fox-text-item',
                 model: 'item.name',
                 attrs: {
                    placeholder: '请输入内容',
                 },
                 props: {
                    'required.exec': 'isRequired',
                 },
                 on: {},
                 ref: 'inputRef',
                 children: [
                     {
                        text: '名称',
                     },
                 ],
              },
              {
                  slot: 'default',
                  slotScope: 'item',
                  key: 'item_ops',
                  name: 'fox-button',
                  attrs: {},
                  props: {},
                  on: {
                    click: 'onOperation',
                  },
                  children: [
                     {
                        variable: 'getBtnText',
                     },
                   ],
                },
        ],
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

在循环slot中的方法函数或属性函数,都会默认添加item和index两个参数,如onOperation = onOperation(item, index, event)

§ 节点配置中属性的支持

下面将会给节点配置中的属性支持进行介绍(重点部分),全部支持请查看例子example

§ 组件中“属性=常量”支持

节点中的常量属性需要定义在attrs中

    {
         name: 'fox-date-item',
         attrs: {
            'value-format': 'yyyy-MM-dd HH:mm:ss',
            type: 'daterange',
            'range-separator': '至',
            'start-placeholder': '开始日期',
            'end-placeholder': '结束日期',
        },
     }
1
2
3
4
5
6
7
8
9
10

§ 组件中“属性=变量”支持

节点中的常量属性需要定义在props中,可以是vue对象的data属性、计算属性、方法

变量

    {
        name: 'fox-select-item',
        props: {
            source: 'm_items',
        },
    }
    
    data(){
      return {
        m_items:[]
      }
    }
1
2
3
4
5
6
7
8
9
10
11
12

计算属性

    {
        name: 'fox-select-item',
        props: {
            source: 'mItems',
        },
     }
    
    computed:{
         mItems(){
           return []
         }
    }
1
2
3
4
5
6
7
8
9
10
11
12

函数

    {
        name: 'fox-select-item',
        props: {
            source: 'loadDatasource',
        },
    }

    methods:{
       loadDatasource(){
          return new Promise((resolve)=>{
             resolve([])
          }
       }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

§ 组件中“属性=函数(执行函数返回结果)”支持

如果属性的值,需要立刻执行指定函数返回结果的,则需要加上.exec 函数(执行函数返回结果)

    {
        name: 'fox-select-item',
        props: {
             'required.exec': 'isRequired',
        },
    }

    methods:{
       isRequired(){
          return trur
       }
    }
1
2
3
4
5
6
7
8
9
10
11
12

带参数函数(执行函数返回结果)

    {
        name: 'fox-select-item',
        props: {
           'required.exec': 'isRequired',
           'method_param_required':'01'
        },
    }

    methods:{
       isRequired(type){
          if(type == '01'){
             return true
          }else{
             false
          }
       }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

§ 组件中“sync属性”支持

sync属性,需要加上.sync

    {
        name: 'fox-date-item',
        props: {
            'startDate.sync': 'startDate',
            'endDate.sync': 'endDate',
        },
    }

    data(){
       return {
         startDate:'',
         endDate:''
       }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

§ 节点配置中v-model

通过model指定绑定的值

    {
        name: 'fox-date-item',
        model: 'val'
    }
    
    data(){
       return {
         val:''
       }
    }
1
2
3
4
5
6
7
8
9
10

§ 节点配置中v-show支持

计算属性或data变量支持

    {
        name: 'fox-group',
        directives: [
             {
                 name: 'show',
                 value: 'mShown',
              },
         ],
    }
    
    computed:{
       mShown(){
          return true
       }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

方法支持

    {
        name: 'fox-group',
        directives: [
             {
                 name: 'show',
                 value: 'mShown',
              },
         ],
    }
    
    methods:{
       mShown(){
          return false
       }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

带参数方法支持

    {
        name: 'fox-group',
        directives: [
             {
                 name: 'show',
                 value: 'mShown',
                 param: '01'
              },
         ],
    }
    
    methods:{
       mShown(type){
          if(type == '01'){
             return true
          }
          return false
       }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

§ 节点配置中v-if支持

计算属性或data变量支持

    {
        name: 'fox-group',
        directives: [
             {
                 name: 'if',
                 value: 'mHas',
              },
         ],
    }
    
    computed:{
       mHas(){
          return true
       }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

方法支持

    {
        name: 'fox-group',
        directives: [
             {
                 name: 'if',
                 value: 'mHas',
              },
         ],
    }
    
    methods:{
       mHas(){
          return false
       }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

带参数方法支持

    {
        name: 'fox-group',
        directives: [
             {
                 name: 'if',
                 value: 'mHas',
                 param: '01'
              },
         ],
    }
    
    methods:{
       mHas(type){
          if(type == '01'){
             return true
          }
          return false
       }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

§ 动态页面渲染

页面的配置信息,通过组件fox-dynamic渲染生成

    <template>
      <fox-dynamic :source = "m_source"></fox-dynamic>
    </template>
    
    <script>
      export default {
         // 数据
        data() {
            return {
                m_source:{...} //动态页面配置
            }
        }
      }
    </script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

§ 第二十一计:Hint提示

进入页面中的某些输入框时,我们需要给用户提示,如注意事项、操作规范等,因此我为输入框提供hint提示功能

§ 属性设置

在输入组件上设置hint-text属性,当该组件获取到焦点的时候,就是显示提示内容

 <fox-group title="属性设置" column="4">
                <fox-text-item hint-text="请输入名称" v-model="value">姓名</fox-text-item>
                <fox-select-item hint-text="请确认财富组成" v-model="value2" placeholder="请选择" :source="m_items">理财产品</fox-select-item>
                <fox-date-item hint-text="请输入出生日期" v-model="value3" placeholder="选择日期" required>出生日期</fox-date-item>
            </fox-group>
1
2
3
4
5

§ Domain设置

另外我们提供更加灵活的手段来说设置hint提示,通过在domain中注入hint提示的映射{model:hintText},让对应model name的组件获取hint text

映射的key为model的名称,value为提示文本

§ 步骤一

开启页面的hint提示,通过provide设置

export default {
    // 名称
    name: 'example_hint',
    // 标志页面开启hint支持
    provide() {
        return {
            hintOpen: true
        }
    },
    ....
}
1
2
3
4
5
6
7
8
9
10
11

§ 步骤二

组件必须设置了v-model

<fox-group title="domain设置" column="4">
                <fox-text-item v-model="value4">账号</fox-text-item>
                <fox-select-item v-model="value5" placeholder="请选择" :source="m_items">股票名称</fox-select-item>
                <fox-date-item v-model="value6" placeholder="选择日期" required>注册日期</fox-date-item>
            </fox-group>
1
2
3
4
5

§ 步骤三

domain设置hint提示映射

   /**
             *  界面渲染后,更改数据会触发钩子函数
             * @param session
             * @param context
             */
            mounted(session, context) {
                let domain = getRootDomain(this)
                domain.setOption('hints', {
                    value4: '请输入账号1,请输入账号2,请输入账号3,请输入账号4,请输入账号5',
                    value5: '请选择股票',
                    value6: '请填写注册日期1,请填写注册日期2,请填写注册日期3'
                })
                context.resolve()
            },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
最后更新于: 4/15/2022, 2:41:22 PM