自定义组件
如果无法播放,点此直接下载/打开
一、发布第一个组件
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日志
- 使用CCDK中的CCLog
<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日志
- 使用CCDK中的CCLog
<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.js。main.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",
},