三、在AEM中实现自定义组件

三、在AEM中实现自定义组件

我们在第二章中实现了自定义模板和页面,在文章的最后用到了repo工具从JCR(Java Content Repository)中拉取自定义的模板用来保存在代码中。那么什么是JCR?

在大型CMS项目开发中,经常会对接供应商的私有存储(数据库、文档、其他存储等),在开发过程中大大增加了系统的复杂性和可维护性,所以标准化内容仓库的需求非常迫切。JCR就应运而生。

Content Repository for Java Technology 规范是在 Java Community Process 中作为 JSR-170 开发的,它的目标是满足这些行业的需求。该规范在 javax.jcr 名称空间中提供了统一的 API ,允许以厂商中立的方式访问任何符合规范的仓库实现。

详情参考IBM关于JCR的介绍

创建自定义组件

这一章我们实现一个翻译组件,通过调用有道智云API来进行翻译单词或句子,自己注册账号密码即可,也可以使用其他API,请自行查找使用。

进入WKDN的ui.apps/src/main/content/jcr_root/apps/wknd/components目录下创建translate目录,结构如下
在这里插入图片描述

_cq_dialog目录为对话框目录,双击组件后弹出的对话框,可在页面输入组件内容

clientlib目录为组件所需js和css目录

translate/.content.xml为组件配置信息

translate/translate.html为组件显示内容

创建组件对话框

打开_cq_dialog/.content.xml文件,进行对话框内容编辑

  • jcr:root标签为结构标签也是根标签,content、items、tabs都为结构标签
  • jcr:title为组件名称
  • sling:resourceType为组件类型,AEM提供了丰富的基础组件类型可供使用,可以在这里进行查看
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
    jcr:primaryType="nt:unstructured"
    jcr:title="翻译组件"
    sling:resourceType="cq/gui/components/authoring/dialog">
    <content
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/container">
        <items jcr:primaryType="nt:unstructured">
            <tabs
                jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/coral/foundation/tabs"
                maximized="{Boolean}false">
                <items jcr:primaryType="nt:unstructured">
                    <properties
                        jcr:primaryType="nt:unstructured"
                        jcr:title="Properties"
                        sling:resourceType="granite/ui/components/coral/foundation/container"
                        margin="{Boolean}true">
                        <items jcr:primaryType="nt:unstructured">
                            <columns
                                jcr:primaryType="nt:unstructured"
                                sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
                                margin="{Boolean}true">
                                <items jcr:primaryType="nt:unstructured">
                                    <column
                                        jcr:primaryType="nt:unstructured"
                                        sling:resourceType="granite/ui/components/coral/foundation/container">
                                        <items jcr:primaryType="nt:unstructured">
                                            <appId
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                fieldLabel="有道智云翻译APPID"
                                                fieldDescription="有道智云翻译APPID."
                                                emptyText="请输入有道智云翻译APPID"
                                                name="./appId"
                                                required="{Boolean}true"/>
                                            <appKey
                                                jcr:primaryType="nt:unstructured"
                                                sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                fieldLabel="有道智云翻译APP密钥"
                                                fieldDescription="有道智云翻译APP密钥."
                                                emptyText="请输入有道智云翻译APP密钥"
                                                name="./appKey"
                                                required="{Boolean}true"/>
                                        </items>
                                    </column>
                                </items>
                            </columns>
                        </items>
                    </properties>
                </items>
            </tabs>
        </items>
    </content>
</jcr:root>

创建组件配置

打开translate/.content.xml

  • jcr:title 组件名称
  • jcr:primaryType 配置类型,cq:Component表示组件
  • componentGroup 组件所属组名,在模板和页面中可以通过组名进行快速搜索组件
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root 
    xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
    xmlns:jcr="http://www.jcp.org/jcr/1.0"
    jcr:primaryType="cq:Component"
    jcr:title="翻译组件"
    jcr:description="有道翻译组件"
    componentGroup="Steven Group" />

创建组件所需的js和css

配置前端库

打开clientlib/.content.xml,steven.translate是我们给前端库起的名字,在html文件中会使用到

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
      jcr:primaryType="cq:ClientLibraryFolder"
      allowProxy="true"
      categories="[steven.translate]"/>
创建js

打开clientlib/js/index.js

(() => {
	// 页面加载时调用
    document.addEventListener('DOMContentLoaded', function () {

    });

    trans = function() {
        var query = $('#trans-content').val();
        var component = $('.cmp-translate');
        var appKey = component.attr('appId');
        var key = component.attr('appKey');
        var salt = (new Date).getTime();
        var curtime = Math.round(new Date().getTime()/1000);
        var to = 'zh-CHS';
        var from = 'en';
        var str1 = appKey + truncate(query) + salt + curtime + key;
        // 用户词表ID
        var vocabId =  '';
        var sign = CryptoJS.SHA256(str1).toString(CryptoJS.enc.Hex);
        $.ajax({
            url: 'http://openapi.youdao.com/api',
            type: 'post',
            dataType: 'jsonp',
            data: {
                q: query,
                appKey: appKey,
                salt: salt,
                from: from,
                to: to,
                sign: sign,
                signType: "v3",
                curtime: curtime,
                vocabId: vocabId,
            },
            success: function (data) {
                var translation = data.translation[0]
                $('#result').html('翻译结果:' + translation);
            }
        });
    }

    const truncate = (q)=> {
              var len = q.length;
              if(len<=20) return q;
              return q.substring(0, 10) + len + q.substring(len-10, len);
          }

})();

打开clientlib/js.txt

#base=js
index.js
创建css

打开clientlib/css/index.css

.cmp-translate {
    margin-top: 20px;
}

打开clientlib/css.txt

#base=css
index.css

创建组件显示内容

打开translate/translate.html,使用HTL语法,HTML 模板语言 (HTL) 是适用于 HTML 的首选和推荐的服务器站点模板系统。是一个开源、不依赖于平台的规范,任何人都可以自由实施。 其规范保存在 GitHub 存储库中。详情参考官方文档

  • sly标签为HTL使用的标签
  • ${}可以访问到JCR中的数据,component、properties为HTL中可直接访问的Java对象
  • data-sly-unwrap=" ! w c m m o d e . e d i t " 表示在非编辑模式下不显示此行信息,意思就是如果我们是在编辑模式下查看组件显示内容,会显示 " {!wcmmode.edit}" 表示在非编辑模式下不显示此行信息,意思就是如果我们是在编辑模式下查看组件显示内容,会显示" !wcmmode.edit"表示在非编辑模式下不显示此行信息,意思就是如果我们是在编辑模式下查看组件显示内容,会显示"{component.title}:Click to configure"这句话,否则不显示
  • 在HTML中如果需要引入前端js和css库,使用data-sly-use.clientLib和data-sly-call属性,data-sly-use.clientLib为固定语句,data-sly-cal中可以使用clientLib.all、clientLib.js、clientLib.css
    • clientLib.all全部引入js和css
    • clientLib.js只引入js
    • clientLib.css只引入css
<div class="cq-placeholder cmp-title" data-emptytext="${component.title}:Click to configure" data-sly-unwrap="${!wcmmode.edit}"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/crypto-js.js"></script>

<sly data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}"/>
<sly data-sly-call="${clientLib.all @ categories='steven.translate'}" />
<div class="cmp-translate" appId="${properties.appId}" appKey="${properties.appKey}">
    <input id="trans-content" type="text" placeholder="请输入需要翻译的英文内容" >
    <button onclick="trans()">翻译</button><br>
    <span id="result"></span>
</div>

在页面中使用组件

要想在页面中使用自定义组件,需要现在模板中选中Translate组件,搜索组名Steven Group
在这里插入图片描述

打开第二章中创建的页面steven,使用Translate组件
请添加图片描述
在这里插入图片描述
点击按钮 View as Published查看页面
在这里插入图片描述
输入需要翻译的内容
在这里插入图片描述
在这里插入图片描述
手动创建自定义组件就开发完成了

从其他组件继承

我们给Translate组件新增一个Tab,与properties标签同级,继承Translate组件,并且继承组件不显示Test页

<test jcr:primaryType="nt:unstructured"
      jcr:title="Test"
      sling:resourceType="granite/ui/components/coral/foundation/container"
      margin="{Boolean}true">
    <items jcr:primaryType="nt:unstructured">
        <columns
                 jcr:primaryType="nt:unstructured"
                 sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
                 margin="{Boolean}true">
            <items jcr:primaryType="nt:unstructured">
                <column
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/coral/foundation/container">
                    <items jcr:primaryType="nt:unstructured">
                        <test
                              jcr:primaryType="nt:unstructured"
                              sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                              fieldLabel="test"
                              fieldDescription="test."
                              emptyText="test"
                              name="./test"/>
                    </items>
                </column>
            </items>
        </columns>
    </items>
</test>

在页面中可以看到多了一个Test页
在这里插入图片描述

继承组件

复制代码,删除不需要的代码
在这里插入图片描述

修改对话框中的test节点

<test jcr:primaryType="nt:unstructured"
      sling:hideResource="{Boolean}true">
</test>

修改组件配置信息,使用jcr:resourceSuperType节点指定父组件位置

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root 
    xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
    xmlns:jcr="http://www.jcp.org/jcr/1.0"
    jcr:primaryType="cq:Component"
    jcr:title="translateChild"
    jcr:description="translateChild"
    jcr:resourceSuperType="wknd/components/translate"
    componentGroup="Steven Group" />

实现效果

在这里插入图片描述
这样自定义组件就开发完了,下一章会继续讲解如何使用SlingModel来开发组件

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值