Skip to main content

前端开发教程

自定义组件

如果无法播放,点此直接下载/打开

一、发布第一个组件

1.启动项目

// 控制台运行
npm run serve

2.创建组件

组件名称必须满足dom命名规则:cc-com

3.App引入组件

4.浏览器访问:http://localhost:8080/

5.发布组件

  • 右键点击组件入口文件,选择发布组件
  • 控制台提示以下信息表示组件发布成功

二、示例:如何创建Start类型组件

自定义组件的loadModel属性可以控制组件的加载时机,设置为start时,组件会在项目启动时加载。

1.效果展示

使用启动类型的组件,隐藏详情页右侧部分

2.代码实现

隐藏联系人右侧活动动态Card部分,loadModel要设置为start模式

<template>
  <div></div>
</template>

<script>
console.log("JS脚本可以写在这里,会自动执行")


export default {
  data() {
    return {
      componentInfo: {
        // 组件唯一标识,全局唯一
        component: "cloudcc-demo-a",
        // 组件名称,在页面编辑器显示的名字
        compName: "cloudcc-demo-a",
        // 组件描述信息
        compDesc: "组件描述信息",
        // 设置组件在应用启动的时候加载
        loadModel:"start"
      },
      isLock: false,
    };
  },
};
</script>
<style lang="scss">
// 此样式名称逻辑:detail+对象前缀ID,可以在后台设置对象管理中查看
.detail001 {
   // 此样式选择器仅作示例,不保证一直可用。
  .main.left.scrollBoxUnique {
    width: 100% !important;
  }
   // 此样式选择器仅作示例,不保证一直可用。
  .layoutSwitchBox {
    display: none !important;
  }
   // 此样式选择器仅作示例,不保证一直可用。
  .right.scrollBoxUnique {
    display: none !important;
  }
}
</style>

为了方便实施进行开发,目前平台在dom上添加了devid属性,用于标记dom元素

三、示例:如何避免样式污染

在开发web项目时,经常遇到的一个问题就是,全局样式污染,vue中是通过在style中添加scoped标签,在编译阶段对style做特殊处理,避免了样式污染问题。

代码实现

<template>
  <div></div>
</template>

<script>
export default {
  data() {
    return {
      componentInfo: {
        // 组件唯一标识,全局唯一
        component: "cloudcc-demo-a",
        // 组件名称,在页面编辑器显示的名字
        compName: "cloudcc-demo-a",
        // 组件描述信息
        compDesc: "组件描述信息",
      },
      isLock: false,
    };
  },
};
</script>
<style lang="scss" scoped>
// 因为设置了scoped此标签下的样式,仅作用于当前组件,不会影响到其他dom

</style>

四、示例:如何使用echarts

平台目前已经集成了echarts5.3.2,可以全量导入,打包后的组件已经排除,发布到平台会自动引用平台库。

1.效果展示

2.代码实现

<template>
  <div id="chartId" :style="{ width: '100%', height: '400px' }"></div>
</template>

<script>
import * as echarts from "echarts";
export default {
  data() {
    return {
      componentInfo: {
        // 组件唯一标识,全局唯一
        component: "cloudcc-demo-a",
        // 组件名称,在页面编辑器显示的名字
        compName: "cloudcc-demo-a",
        // 组件描述信息
        compDesc: "组件描述信息",
      },
      isLock: false,
    };
  },
  mounted() {
    this.myChart = echarts.init(document.getElementById("chartId"));
    // 绘制图表
    this.myChart.setOption({
      color: ["#80FFA5", "#00DDFF", "#37A2FF", "#FF0087", "#FFBF00"],
      title: {
        text: "Gradient Stacked Area Chart",
      },
      tooltip: {
        trigger: "axis",
        axisPointer: {
          type: "cross",
          label: {
            backgroundColor: "#6a7985",
          },
        },
      },
      legend: {
        data: ["Line 1", "Line 2", "Line 3", "Line 4", "Line 5"],
      },
      toolbox: {
        feature: {
          saveAsImage: {},
        },
      },
      grid: {
        left: "3%",
        right: "4%",
        bottom: "3%",
        containLabel: true,
      },
      xAxis: [
        {
          type: "category",
          boundaryGap: false,
          data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
        },
      ],
      yAxis: [
        {
          type: "value",
        },
      ],
      series: [
        {
          name: "Line 1",
          type: "line",
          stack: "Total",
          smooth: true,
          lineStyle: {
            width: 0,
          },
          showSymbol: false,
          areaStyle: {
            opacity: 0.8,
            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
              {
                offset: 0,
                color: "rgb(128, 255, 165)",
              },
              {
                offset: 1,
                color: "rgb(1, 191, 236)",
              },
            ]),
          },
          emphasis: {
            focus: "series",
          },
          data: [140, 232, 101, 264, 90, 340, 250],
        },
        {
          name: "Line 2",
          type: "line",
          stack: "Total",
          smooth: true,
          lineStyle: {
            width: 0,
          },
          showSymbol: false,
          areaStyle: {
            opacity: 0.8,
            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
              {
                offset: 0,
                color: "rgb(0, 221, 255)",
              },
              {
                offset: 1,
                color: "rgb(77, 119, 255)",
              },
            ]),
          },
          emphasis: {
            focus: "series",
          },
          data: [120, 282, 111, 234, 220, 340, 310],
        },
        {
          name: "Line 3",
          type: "line",
          stack: "Total",
          smooth: true,
          lineStyle: {
            width: 0,
          },
          showSymbol: false,
          areaStyle: {
            opacity: 0.8,
            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
              {
                offset: 0,
                color: "rgb(55, 162, 255)",
              },
              {
                offset: 1,
                color: "rgb(116, 21, 219)",
              },
            ]),
          },
          emphasis: {
            focus: "series",
          },
          data: [320, 132, 201, 334, 190, 130, 220],
        },
        {
          name: "Line 4",
          type: "line",
          stack: "Total",
          smooth: true,
          lineStyle: {
            width: 0,
          },
          showSymbol: false,
          areaStyle: {
            opacity: 0.8,
            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
              {
                offset: 0,
                color: "rgb(255, 0, 135)",
              },
              {
                offset: 1,
                color: "rgb(135, 0, 157)",
              },
            ]),
          },
          emphasis: {
            focus: "series",
          },
          data: [220, 402, 231, 134, 190, 230, 120],
        },
        {
          name: "Line 5",
          type: "line",
          stack: "Total",
          smooth: true,
          lineStyle: {
            width: 0,
          },
          showSymbol: false,
          label: {
            show: true,
            position: "top",
          },
          areaStyle: {
            opacity: 0.8,
            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
              {
                offset: 0,
                color: "rgb(255, 191, 0)",
              },
              {
                offset: 1,
                color: "rgb(224, 62, 76)",
              },
            ]),
          },
          emphasis: {
            focus: "series",
          },
          data: [220, 302, 181, 234, 210, 290, 150],
        },
      ],
    });
  },
};
</script>
<style lang="scss" scoped>
.cc-container {
  text-align: center;
  padding: 8px;
  background: goldenrod;
}
</style>

五、示例:如何请求自定义类(接口)

自定义组件请求自定义类,已经封装到CCDK中,请不要自己拼接访问地址

代码实现

<template>
  <div class="cc-container" @click="getInfo">Hello World</div>
</template>

<script>
export default {
  data() {
    return {
      componentInfo: {
        // 组件唯一标识,全局唯一
        component: "cloudcc-demo-a",
        // 组件名称,在页面编辑器显示的名字
        compName: "cloudcc-demo-a",
        // 组件描述信息
        compDesc: "组件描述信息",
      },
      isLock: false,
    };
  },
  methods: {
    getInfo() {
      let className = "AccountClass";
      let methodName = "selectAccount";
      let params = [
        {
          argType: "java.lang.String",
          argValue: "hello",
        },
        {
          argType: "java.lang.String",
          argValue: "world",
        },
      ];
         window.$CCDK.CCCommon.post(className, methodName, params)
        .then((res) => {
          console.log(res);
        })
        .catch((error) => {
          console.log(error);
        });
    },
  },
};
</script>
<style lang="scss" scoped>
.cc-container {
  text-align: center;
  padding: 8px;
  background: goldenrod;
}
</style>

六、示例:如何引入第三方库

某些场景下,可能需要引入第三方库,平台提供了统一的JS注入方法CCDK,可以直接使用

1.例:如何引入jquery

  • 在静态资源中上传资源
  • 在export default上使用$CCDK.CCLoad.loadJs加载js
  • loadModel模式设置为start
<template>
  <div></div>
</template>

<script>
// 加载jquery
window.$CCDK.CCLoad.loadJs(
  "https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.js"
);
export default {
  data() {
    return {
      componentInfo: {
        // 组件唯一标识,全局唯一
        component: "cloudcc-demo-a",
        // 组件名称,在页面编辑器显示的名字
        compName: "cloudcc-demo-a",
        // 组件描述信息
        compDesc: "组件描述信息",
        // 设置组件在应用启动的时候加载
        loadModel: "start",
      },
      isLock: false,
    };
  },
};
</script>

2.效果展示

七、示例:如何引入图片

某些场景下,组件中可能需要引入静态展示的图片,那么可以使用静态资源实现

1.上传图片至静态资源

  • 进入开发者控制台--》静态资源菜单--》点击新建--》保存后在列表中可查看
  • 点击列表中地址列的复制按钮,复制静态资源链接成功

2.在组件中使用静态资源图片

<template>
  <div>
    <img
      style="width: height: 800px"
      src="https://res.lightning.cloudcc.cn/staticResource/org08f84e9c0566eaf0c/202309/16945042351857583.png"
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      componentInfo: {
        // 组件唯一标识,全局唯一
        component: "cloudcc-demo-a",
        // 组件名称,在页面编辑器显示的名字
        compName: "cloudcc-demo-a",
        // 组件描述信息
        compDesc: "组件描述信息",
        // 设置组件在应用启动的时候加载
        loadModel: "start",
      },
      isLock: false,
    };
  },
};
</script>

八、示例:如何上报日志

为方便开发人员排查线上问题,平台提供了CCLog,可以通过此功能,上报异常信息到监控平台

1.组件中上报Info日志

<template>
  <div>
    <el-button @click="reportInfo">上报Info日志</el-button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      componentInfo: {
        // 组件唯一标识,全局唯一
        component: "cloudcc-demo-a",
        // 组件名称,在页面编辑器显示的名字
        compName: "cloudcc-demo-a",
        // 组件描述信息
        compDesc: "组件描述信息",
        // 设置组件在应用启动的时候加载
        loadModel: "start",
      },
      isLock: false,
    };
  },
  methods: {
    reportInfo() {
      let logInfo = {
        infoType: "debug",
        serviceName: "my app",
        infoMessage: "描述信息",
      };
      window.$CCDK.CCLog.reportInfoLog(logInfo);
    },
  },
};
</script>

2.组件中上报Error日志

<template>
  <div>
    <el-button @click="reportError">上报Error日志</el-button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      componentInfo: {
        // 组件唯一标识,全局唯一
        component: "cloudcc-demo-a",
        // 组件名称,在页面编辑器显示的名字
        compName: "cloudcc-demo-a",
        // 组件描述信息
        compDesc: "组件描述信息",
        // 设置组件在应用启动的时候加载
        loadModel: "start",
      },
      isLock: false,
    };
  },
  methods: {
    reportError() {
      let logInfo = {
        serviceName: "my app",
        errorMessage: "描述信息",
        printStackTraceInfo: "printStackTraceInfo描述信息",
      };
      window.$CCDK.CCLog.reportErrorLog(logInfo);
    },
  },
};
</script>

3.查看上报的日志

  • 登录cloudcc系统——》点击右上角人头像——》点击开发者平台
  • 进入对应的日志菜单即可查看

九、进阶:架构模型

自定义组件实现的基础是Web Components通过此功能实现跨框架组件开发,发布和使用。

文件编译服务

  • 在编译组件时,组件本身是编译的入口文件,而不是模板项目中的 main.jsmain.js 是模板项目运行时的入口文件,可以调整。因此,在组件中使用第三方资源时,需要将资源引入到组件内部,或注入到全局。

十、进阶:组件销毁逻辑

因为自定义组件的特殊渲染逻辑,所以有必要控制组件的销毁时机,如果不进行销毁,在长时间使用后,内存会持续增加,最终导致OOM,目前组件默认销毁时间20分钟

1.组件销毁逻辑

组件会在进入后台(用户不可见的状态)开始倒计时,时间为0时,组件销毁

2.设置组件的销毁时间

配置安全信息 中的高级配置,destroyTimeout可以设置组件的销毁时间,打包的所有组件将统一使用这个配置。单位是毫秒。

  "devConsoleConfig": {
    "destroyTimeout": 1200000
  },

十一、进阶:扩展组件属性

通过扩展组件属性,可以实现组件功能的灵活配置,从而提高组件的可复用性。用户可以通过修改组件的属性,来改变组件的功能,而无需修改组件的源码。

1.如何自定义属性

  • 以官方Image组件为例
  • 配置“请输入图片地址”的属性
  • 通过propObj和propOption可以创建自定义属性采集器
<template>
  <div>
    <img style="width: height: 800px"/>
  </div>
</template>

<script>
export default {
  data() {
    return {
      componentInfo: {
        // 组件唯一标识,全局唯一
        component: "cloudcc-demo-a",
        // 组件名称,在页面编辑器显示的名字
        compName: "cloudcc-demo-a",
        // 组件描述信息
        compDesc: "组件描述信息",
        // 设置组件在应用启动的时候加载
        loadModel: "start",
      },
      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "请输入图片地址",
          type: "input",
        },
      },
      isLock: false,
    };
  },
};
</script>

2.接收自定义属性

  • 属性自定义好之后,需要使用props接收使用,通过定义的elePropObj来接收
<template>
  <div>
    <img style="width: height: 800px" :src="elePropObj.src" />
  </div>
</template>

<script>
export default {
  props: {
    // 自定义属性
    elePropObj: {
      type: Object,
      default: () => ({}),
    },
  },
  data() {
    return {
      componentInfo: {
        // 组件唯一标识,全局唯一
        component: "cloudcc-demo-a",
        // 组件名称,在页面编辑器显示的名字
        compName: "cloudcc-demo-a",
        // 组件描述信息
        compDesc: "组件描述信息",
        // 设置组件在应用启动的时候加载
        loadModel: "start",
      },
      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "请输入图片地址",
          type: "input",
        },
      },
      isLock: false,
    };
  },
};
</script>

十二、进阶:自定义propOption属性

propOption支持多种数据采集组件,方便用户配置属性。以下属性都需要配置到data中

1.输入框

      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "请输入图片地址",
          type: "input",
        },
      },

2.日期选择器

      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "日期选择器",
          type: "date",
        },
      },

3.时间选择器

      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "时间选择器",
          type: "time",
        },
      },

4.图标

      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "图标",
          type: "icon",
        },
      },

5.颜色选择器

      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "颜色",
          type: "color",
        },
      },

6.下拉框

      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "下拉款",
          type: "option",
          options: [
            {
              value: "fill",
              label: "fill",
            },
            {
              value: "contain",
              label: "contain",
            },
          ],
        },
      },

7.切换器

      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "切换器",
          type: "radioButton",
          options: [
            {
              label: "default",
              value: "default",
            },
            {
              label: "button",
              value: "button",
            },
          ],
        },
      },

8.开关

      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "开关",
          type: "switch",
        },
      },

9.代码编辑框

      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "代码编辑框",
          type: "code",
        },
      },

10.提示信息

      // 扩展属性对象
      propObj: {
        // 自定义属性时,必须写入ID
        id: "",
        src: "",
      },
      // 扩展属性配置
      propOption: {
        src: {
          lable: "提示信息",
          type: "word",
          link: "https://www.baidu.com",
        },
      },

十三、进阶:自定义events事件

通过扩展属性,可以定义一些生命周期的回调方法,以供实现特殊业务逻辑

1.案例

  • 比如在组件Created方法中执行一段逻辑
// 在组件的data属性中添加以下代码,添加的代码必须在isLock: false上面
data() {
    return {
      componentInfo: {
        component: "test-plugin",

        compName: "test-plugin",

        compDesc: "Component description information",
      },
      events: {
        myCreated: `function created(self) {
           // self即this,本组件的vue实例
          }`,
      },
      eventsOption: {
        myCreated: {
          lable: "label.dev.created",
          type: "code",
        },
      },
      isLock: false,
    };
  },
  • 在created()添加以下代码
  created() {
    ......
    let myCreated = eval("(false || " + this.eleEventObj.myCreated + ")");
    myCreated(this);
    ......
  },

2.效果展示

十四、进阶:componentInfo配置说明

1.标准配置:

  componentInfo: {
        // 组件唯一标识,全局唯一。1:英文必须使用小写。2:大于等于2个单词。3:使用"-"分隔
        component: "cloudcc-demo-01",
        // 组件名称,在页面编辑器显示的名字
        compName: "演示使用组件",
        // 组件描述信息
        compDesc: "组件描述信息",
        },

2.高级配置:

  componentInfo: {
        // 加载模式,不写默认lazy
        // lazy:懒加载,加载自定义页面的时候才加载组件,
        // start:启动加载,启动应用的时候会自动加载组件
        loadModel: "lazy",
        },