How to communicate between Web Components (native UI)?

前端 未结 4 1482
陌清茗
陌清茗 2020-12-11 02:34

I\'m trying to use native web components for one of my UI project and for this project, I\'m not using any frameworks or libraries like Polymer etc. I would like to know is

4条回答
  •  青春惊慌失措
    2020-12-11 03:18

    +1 for both other answers, Events are the best because then Components are loosly coupled

    Note that in the detail of a Custom Event you can send anything you want.

    Event driven function execution:

    So I use (psuedo code):

    Elements that define a Solitaire/Freecell game:

    -> game Element
      -> pile Element
        -> slot Element
          -> card element
      -> pile Element
        -> slot Element
          -> empty
    

    When a card (dragged by the user) needs to be moved to another pile,

    it sends an Event (bubbling up the DOM to the game element)

        //triggered by .dragend Event
        card.say(___FINDSLOT___, {
                                    id, 
                                    reply: slot => card.move(slot)
                                });    
    

    Note: reply is a function definition

    Because all piles where told to listen for ___FINDSLOT___ Events at the game element ...

       pile.on(game, ___FINDSLOT___, evt => {
                                          let foundslot = pile.free(evt.detail.id);
                                          if (foundslot.length) evt.detail.reply(foundslot[0]);
                                        });
    
    

    Only the one pile matching the evt.detail.id responds:

    !!! by executing the function card sent in evt.detail.reply

    And getting technical: The function executes in pile scope!

    (the above code is pseudo code!)

    Why?!

    Might seem complex;
    The important part is that the pile element is NOT coupled to the .move() method in the card element.

    The only coupling is the name of the Event: ___FINDSLOT___ !!!

    That means card is always in control, and the same Event(Name) can be used for:

    • Where can a card go to?
    • What is the best location?
    • Which card in the river pile makes a Full-House?
    • ...

    In my E-lements code pile isn't coupled to evt.detail.id either,

    CustomEvents only send functions



    .say() and .on() are my custom methods (on every element) for dispatchEvent and addEventListener

    I now have a handfull of E-lements that can be used to create any card game

    No need for any libraries, write your own 'Message Bus'

    My element.on() method is only a few lines of code wrapped around the addEventListener function, so they can easily be removed:

        $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( ) is a oneliner:

        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));
        },
    

提交回复
热议问题