5
1

More than 3 years have passed since last update.

Riot.js Advent Calendar 2019 の15日目が空いていたので埋めます。(ちょっと過ぎちゃったケド)

はじめに

@black-trooper さんのRiot v4 で子コンポーネントのメソッドを実行するの通り、v3の時は子コンポーネントのメソッドを実行したりということはよくやっていたんですが、v4から簡単には出来なくなっています。

riot-observableでも良いのですが、もうちょっと気軽に呼びたかったので少し調べてみました。
observable自体は便利なので、興味がある方は@black-trooper さん記事を参考に!

コンポーネントを使う

riot.componentの戻り値はコンポーネントに関する情報を持っているのでここから操作できます。

child.riot
<my-child>
  <p>{ state.message } World!!</p>

  <script>
    export default {
      state: {
        message: ""
      },

      onMounted(props, state) {
        this.greeting(props.message);
      },

      greeting(msg) {
        this.state.message = msg;
        this.update();
      }
    }
  </script>
</my-child>
app.riot
<app>
  <div id="child"></div>
  <input type="button" value="Goodbye" onclick="{ call_greeting }">
  <input type="button" value="Hola" onclick="{ call_greeting }">
  <input type="button" value="Adios" onclick="{ direct_greeting }">

  <script>
    import { component } from 'riot'
    import Child from './child.riot'

    let child;
    export default {
      onMounted(props, state) {
        // 子コンポーネントをマウント
        child = component(Child)(document.getElementById('child'), {
          message: 'Hello'
        });

        // 子コンポーネントのstateを取得
        console.log(child.state.message); // Hello
      },

      // 子コンポーネントのメソッドを呼び出し
      call_greeting(e) {
        child.greeting(e.target.value);
      },

      // 子コンポーネントのstateを直接変更
      direct_greeting(e) {
        child.state.message = e.target.value;
        child.update();
      }
    }
  </script>
</app>
index.js
import { component } from 'riot'
import App from './app.riot'

component(App)(document.getElementById('root'));

riotファイルの中でコンポーネント使いたくないんだけど?

ですよね。
それにはv4でなぜ取得できないのか調べる必要があります。

mountのソースを確認。

      mount(element, state, parentScope) {
                     :
        element[DOM_COMPONENT_INSTANCE_PROPERTY] = this; // add eventually the 'is' attribute

エレメントのプロパティには入れていますが、キーがSymbolとなっています。

DOM_COMPONENT_INSTANCE_PROPERTY = Symbol('riot-component')

邪道版 子コンポーネントを操作

Symbolで持っているということさえわかれば十分。

app.riot
<app>
  <my-child message="Hello"></my-child>
  <input type="button" value="Goodbye" onclick="{ call_greeting }">
  <input type="button" value="Hola" onclick="{ call_greeting }">
  <input type="button" value="Adios" onclick="{ direct_greeting }">

  <script>
    let child;

    export default {
      onMounted(props, state) {
        const elm = this.$("my-child");
        // 子コンポーネントの情報を取得
        child = elm[Object.getOwnPropertySymbols(elm).find(symbol => symbol.toString() === "Symbol(riot-component)")];
      },

      // 子コンポーネントのメソッドを呼び出し
      call_greeting(e) {
        child.greeting(e.target.value);
      },

      // 子コンポーネントのstateを直接変更
      direct_greeting(e) {
        child.state.message = e.target.value;
        child.update();
      }
    }
  </script>
</app>
index.js
import { component, register } from 'riot'
import App from './app.riot'
import Child from './child.riot'

register('my-child', Child);
component(App)(document.getElementById('root'));

無事呼べました!

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1