Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/463.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在Web组件(本机UI)之间通信?_Javascript_Html_Web Component_Custom Element_Native Web Component - Fatal编程技术网

Javascript 如何在Web组件(本机UI)之间通信?

Javascript 如何在Web组件(本机UI)之间通信?,javascript,html,web-component,custom-element,native-web-component,Javascript,Html,Web Component,Custom Element,Native Web Component,我尝试在我的一个UI项目中使用原生web组件,而在这个项目中,我没有使用任何框架或库,如Polymer等。我想知道是否有任何最佳方式或其他方式可以在两个web组件之间进行通信,就像我们在angularjs/angular中所做的那样(如消息总线概念) 目前在UI web组件中,我使用dispatchevent发布数据和接收数据,我使用addeventlistener。 例如,有两个web组件,ChatForm和ChatHistory // chatform webcomponent on sub

我尝试在我的一个UI项目中使用原生web组件,而在这个项目中,我没有使用任何框架或库,如Polymer等。我想知道是否有任何最佳方式或其他方式可以在两个web组件之间进行通信,就像我们在angularjs/angular中所做的那样(如消息总线概念)

目前在UI web组件中,我使用dispatchevent发布数据和接收数据,我使用addeventlistener。 例如,有两个web组件,ChatForm和ChatHistory

// chatform webcomponent on submit text, publish chattext data 
this.dispatchEvent(new CustomEvent('chatText', {detail: chattext}));

// chathistory webcomponent, receive chattext data and append it to chat list
this.chatFormEle.addEventListener('chatText', (v) => {console.log(v.detail);});

请让我知道还有什么其他方法可以达到这个目的。任何好的库,如postaljs等,都可以轻松地与本机UI web组件集成。

如果要处理松散耦合的自定义元素,自定义事件是最好的解决方案

相反,如果一个自定义元素通过其引用知道另一个,则它可以调用其自定义属性或方法

//in chatForm element
chatHistory.attachedForm = this
chatHistory.addMessage( message )
chatHistory.api.addMessage( message )
chatHistory.setAttributes( 'chat', 'active' )
chatHistory.dataset.username = `$(this.name)`
在上面的最后一个示例中,通信是通过通过
api
属性公开的dedecated对象完成的

根据自定义元素的链接方式,还可以混合使用事件(一种方式)和方法(另一种方式)

最后,在一些消息是基本的情况下,您可以通过HTML属性来传递(字符串)数据:

//in chatForm element
chatHistory.attachedForm = this
chatHistory.addMessage( message )
chatHistory.api.addMessage( message )
chatHistory.setAttributes( 'chat', 'active' )
chatHistory.dataset.username = `$(this.name)`

如果您将Web组件看作是内置组件,如
,那么您可以回答自己的问题。这些组件彼此不通信

一旦你开始允许组件之间直接对话,那么你就没有真正的组件了。你有一个绑在一起的系统,没有组件B你就不能使用组件a。这绑得太紧了

相反,在拥有这两个组件的父代码中,您添加了允许您从组件A接收事件、在组件B中调用函数
设置参数的代码,反之亦然

尽管如此,对于内置组件,此规则有两个例外:

  • 标记:它使用
    for
    属性获取另一个组件的ID,如果设置且有效,则当您单击

  • 标记:它查找作为子元素的表单元素,以收集发布表单所需的数据

  • 但这两个问题仍然没有任何联系。
    被告知
    焦点
    事件的接收者,并且仅当ID设置且有效时,才会将其传递给第一个表单元素,或者将其作为子元素传递给第一个表单元素。而
    元素并不关心存在哪些子元素,也不关心有多少子元素,它只是通过其所有子元素查找构成元素的元素并获取它们的
    属性

    但一般来说,您应该避免让一个同级组件直接与另一个同级组件对话。上述两个例子中的交叉通信方法可能是唯一的例外

    相反,父代码应该侦听事件并调用函数或设置属性

    是的,您可以将该功能包装在一个新的父组件中,但请避免太多的痛苦,避免使用意大利面代码


    一般来说,我从不允许兄弟姐妹元素彼此交谈,他们与父母交谈的唯一方式是通过事件。父母可以通过属性、属性和函数直接与子女交谈。但是在所有其他情况下都应该避免这种情况。

    +1对于其他两种答案,事件都是最好的,因为它们的组成部分都是松散的 耦合


    另见:


    请注意,在自定义事件的
    详细信息中,您可以发送任何想要的内容

    事件驱动的函数执行: 所以我使用(psuedo代码):

    定义单人纸牌/免费手机游戏的元素:

    -> game Element
      -> pile Element
        -> slot Element
          -> card element
      -> pile Element
        -> slot Element
          -> empty
    
    当卡片(由用户拖动)需要移动到另一堆时

    它发送一个事件(将DOM冒泡到游戏元素)

    注意:
    回复
    是一个函数定义

    因为所有的都在游戏元素的
    \uuuuuuuu FINDSLOT\uuuuuuuuuuuuuuuuu
    事件中排列

       pile.on(game, ___FINDSLOT___, evt => {
                                          let foundslot = pile.free(evt.detail.id);
                                          if (foundslot.length) evt.detail.reply(foundslot[0]);
                                        });
    
    
    只有与
    evt.detail.id
    匹配的一堆响应:

    !!!执行
    evt.detail.reply中发送的功能
    card

    获取技术:该函数在
    范围内执行

    (上面的代码是伪代码!)

    为什么? 可能看起来很复杂
    重要的部分是
    元素与
    元素中的
    .move()
    方法不耦合

    仅耦合是事件的名称:
    \uuuuuu FINDSLOT\uuuuuu

    这意味着
    始终处于控制状态,同一事件(名称)
    可用于:

    • 一张卡片可以寄到哪里
    • 最好的位置是什么
    • 河里的哪一张牌堆得满满的
    在我的电子元件中,代码
    pile
    也没有耦合到
    evt.detail.id

    CustomEvents仅发送功能



    .say()
    .on()
    是我对
    dispatchEvent
    addEventListener
    的自定义方法(在每个元素上)

    我现在有一手电子元素,可以用来创建任何纸牌游戏

    不需要任何库,编写自己的“消息总线”

    我的
    element.on()
    方法只是围绕
    addEventListener
    函数的几行代码,因此可以轻松删除它们:

        $Element_addEventListener(
            name,
            func,
            options = {}
        ) {
            let BigBrotherFunc = evt => {                     // wrap every Listener function
                if (evt.detail && evt.detail.reply) {
                    el.warn(`can catch ALL replies '${evt.type}' here`, evt);
                }
                func(evt);
            }
            el.addEventListener(name, BigBrotherFunc, options);
            return [name, () => el.removeEventListener(name, BigBrotherFunc)];
        },
        on(
            //!! no parameter defintions, because function uses ...arguments
        ) {
            let args = [...arguments];                                  // get arguments array
            let target = el;                                            // default target is current element
            if (args[0] instanceof HTMLElement) target = args.shift();  // if first element is another element, take it out the args array
            args[0] = ___eventName(args[0]) || args[0];                 // proces eventNR
            $Element_ListenersArray.push(target.$Element_addEventListener(...args));
        },
    
    .say()
    是一个单行程序:

        say(
            eventNR,
            detail,             //todo some default something here ??
            options = {
                detail,
                bubbles: 1,    // event bubbles UP the DOM
                composed: 1,   // !!! required so Event bubbles through the shadowDOM boundaries
            }
        ) {
            el.dispatchEvent(new CustomEvent(___eventName(eventNR) || eventNR, options));
        },
    
    工作考试