-->

How do I access child elements within riot.js

2020-07-06 06:59发布

问题:

If I have a custom riot tag with a p in it like this:

<custom>
  <p>This is a text</p>
</custom>

How do I access the <p> element from within the <custom> tag?

Update: I've received a whole bunch answers that are of ways to select it from the DOM. What I want is a way to select the inner p tag from within the component library riot.js itself. I'm looking for a more riotjs specific answer. For example with polymer you use this.$.content.getDistributedNodes().

回答1:

Riot only provides 4 properties to access data from the current tag you're in:

  • this.opts
  • this.parent
  • this.root
  • this.tags

See the API docs

edit

Besides this you can directly access named elements:

<my-tag>
  <p name="foo">Hi, I'm foo</p>
  <script>
    console.log(this.foo);
  </script>
</my-tag>

see the docs

/edit

There's no direct reference to any of the elements you defined in your custom-tag; the rest comes down to just pure old JS (which you might favour or not).

Like others stated, you can access elements using dom methods. However, in some cases you need to wait until the DOM is actually loaded. For instance:

<my-tag>
  <p>yada</p>
  <script>
    console.log(this.root.querySelector('p'))
  </script>
</my-tag>

won't work, because the DOM is not ready yet. Instead wrap the selector in a 'mount' event listener like this:

<my-tag>
  <p>yada</p>
  <script>
    this.on('mount', function() {
      console.log(this.root.querySelector('p'))
    })
  </script>
</my-tag>


回答2:

If you add an id or name attribute to your inner tag, you can access it via self.

// with 'id'
<custom><p id="pTest">Test</p></custom>

// with 'name'
<custom><p name="pTest">Test</p></custom>

in js part:

self = this

self.pTest
>>  <p id=pTest>Test</p>

Tested in Riot v2.0.10



回答3:

See Tag instance.

We can access to children.

customTagAndLoops = this.children

Also to DOM via root.

iAmDom = this.root
childNodes = this.root.childNodes
p = this.root.querySelector('p')

UPDATE - Feb 14, 2015

children property is obsoleted in Riot.js v2.0.9. The only way to access child elements is using root.



回答4:

Riotjs in latest versions has Yielding nested HTML feature. See the API docs

In your case you can easily do that in this way:

In tag definition:

<custom>
 <!-- tag markup-->
 <div id="place for custom html">
   <yield/>
 </div>
</custom>

In your app:

<custom>
  <p>This is a text</p>
</custom>

Rendered html:

<custom>
  <div id="place for custom html">
    <p>This is a text</p>
  </div>
</custom>

From the docs

The <yield> tag also provides a slot mechanism that allows you to inject html contents on specific slots in the template



回答5:

In riot 3.4.2 you can add a ref attribute to the inner element that you want ej:

<custom>
  <p ref="myP">This is a text</p>
</custom>
...

// in js
this.refs.myP


回答6:

Have you tried:

nodes = document.getElementsByTagName('custom');
for (var i = 0; i< nodes.length; ++i) {
    paragraphs = nodes[i].getElementsByTagName('p');
    alert(paragraphs[0].innerText);
}

getElementsByTagName returns an HTML Collection which you can further query: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection

Here's a quick and dirty fiddle: http://jsfiddle.net/markm/m8n3huLn/



回答7:

querySelector seems to work with custom tags:

document.querySelector('custom p').innerHTML= 'Test complete';
<p>This is a test</p>
<custom>
  <p>This is a test</p>
</custom>
<p>This is a test</p>



回答8:

The RiotJs Cheatsheet suggests using yield, if I have understood your dilemma correctly.

Main tag declaration:

<element-i-will-call>

  <span>I am a title</span>

  <element-child-as-container>
    <yield to='header'>Hello User</yield>
    <yield to='conent'>You are here</yield>
  </element-child-as-container>

</element-i-will-call>

Child tag declaration:

<element-child-as-container>

  <h2>
    <yield from='header'/>
  </h2>

  <div>
    <yield from='conent'/>
  </div>

</element-child-as-container>

Main implementation:

<html>
<head>
    ...
</head>
<body>
    <element-i-will-call />
</body>
</html


回答9:

https://riot.js.org/api/#-yielding-nested-html

if you have this in your html:

<custom>
  <p>This is a text</p>
</custom>

Then in your tag file you can use <yield/>

<custom>
    <yield/>
</custom>

This will now make the <p> render on the page