レンダリング関数と JSX の詳細

レンダリング関数と JSX の詳細

1. 基本

Vue では、ほとんどの場合、テンプレートを使用して HTML を作成することを推奨しています。ただし、シナリオによっては、JavaScript の完全なプログラミング能力が本当に必要になる場合があります。この時点では、テンプレートよりもコンパイラに近いレンダリング関数を使用することができます。

レンダリング関数が役立つ簡単な例を見てみましょう。アンカー付きの見出しをいくつか生成したいとします。

<h1>
  <a name="hello-world" href="#hello-world" rel="外部 nofollow" >
    こんにちは世界!
  </a>
</h1>


上記の HTML では、コンポーネント インターフェイスを次のように定義することにしました。

<anchored-heading :level="1">こんにちは世界!</anchored-heading>


level propを通じて動的にheadingを生成することしかできないコンポーネントを書き始めるとき、次のように実装することをすぐに思いつくかもしれません。

<script type="text/x-template" id="アンカー付き見出しテンプレート">
  <h1 v-if="レベル === 1">
    <スロット></スロット>
  </h1>
  <h2 v-else-if="レベル === 2">
    <スロット></スロット>
  </h2>
  <h3 v-else-if="レベル === 3">
    <スロット></スロット>
  </h3>
  <h4 v-else-if="レベル === 4">
    <スロット></スロット>
  </h4>
  <h5 v-else-if="レベル === 5">
    <スロット></スロット>
  </h5>
  <h6 v-else-if="レベル === 6">
    <スロット></スロット>
  </h6>
</スクリプト>


Vue.component('アンカー付き見出し', {
  テンプレート: '#anchored-heading-template',
  小道具: {
    レベル:
      タイプ: 数値、
      必須: true
    }
  }
})


ここでテンプレートを使用することは最善の選択ではありません。コードが長くなるだけでなく、 <slot></slot>,アンカー要素が挿入されるときに再度繰り返す必要があります。

テンプレートはほとんどのコンポーネントでうまく機能しますが、ここでは明らかに適切ではありません。それでは、 render関数を使用して上記の例を書き直してみましょう。

Vue.component('アンカー付き見出し', {
  レンダリング: 関数 (createElement) {
    要素の作成を返す(
      'h' + this.level, // タグ名 this.$slots.default // 子ノード配列)
  },
  小道具: {
    レベル:
      タイプ: 数値、
      必須: true
    }
  }
})

見た目がずっとシンプルになりました!これによりコードが大幅に簡素化されますが、Vue のインスタンスpropertyに精通している必要があります。この例では、 anchored-headingHello world ! など、 v-slot ディレクティブなしで子ノードをコンポーネントに渡すと、これらの子ノードはコンポーネント インスタンスの $slots.default に格納されることを知っておく必要があります。まだ読んでいない場合は、レンダリング関数に進む前にインスタンス プロパティ API について読むことをお勧めします。

2. ノード、ツリー、仮想DOM

レンダリング関数の詳細に入る前に、ブラウザの仕組みについて少し理解しておくことが重要です。次の HTML を例に挙げます。

<div>
  <h1>私のタイトル</h1>
  テキストコンテンツ
  <!-- TODO: タグラインを追加 -->
</div>


ブラウザがこのコードを読み取ると、家族の成長を追跡するために家系図を描くのと同じように、すべてを追跡するための「DOM ノード」のツリーを構築します。

上記の HTML に対応する DOM ノード ツリーを以下に示します。

各要素はノードです。テキストの各段落もノードです。コメントもノードです。ノードはページのセクションです。家系図と同じように、各ノードには子ノードが存在する可能性があります (つまり、各部分に他の部分を含めることができます)。

これらすべてのノードを効率的に更新するのは難しい場合がありますが、幸いなことに手動で行う必要はありません。 Vue にページ上の HTML をどのようにしたいかを伝えるだけで、テンプレートで指定できます。

<h1>{{ ブログタイトル }}</h1>


またはレンダリング関数では:

レンダリング: 関数 (createElement) {
  createElement('h1', this.blogTitle) を返します
}


どちらの場合も、blogTitle が変更されても、Vue は自動的にページを更新し続けます。

1. 仮想DOM

Vue は、実際の DOM がどのように変更されるかを追跡するために仮想 DOM を作成します。次のコード行をよく見てください:

createElement('h1', this.blogTitle) を返します


createElement具体的に何を返すのでしょうか?実際には実際の DOM 要素ではありません。より正確な名前はcreateNodeDescriptionかもしれません。これは、そこに含まれる情報が、子ノードの説明情報を含め、ページにレンダリングする必要があるノードの種類を Vue に伝えるためです。このようなノードは「仮想ノード」と呼ばれ、多くの場合「VNode」と略されます。 「仮想 DOM」とは、Vue コンポーネント ツリーによって構築される VNode ツリー全体のことです。

3. createElementパラメータ

次に知っておく必要があるのは、 createElement関数のテンプレート内でこれらの関数を使用する方法です。 createElementが受け入れるパラメータは次のとおりです。

// @returns {VNode}
要素を作成します(
  // {文字列 | オブジェクト | 関数}
  // HTML タグ名、コンポーネント オプション オブジェクト、または // 上記のいずれかに解決される非同期関数。必須フィールドです。
  'div',

  // {物体}
  // テンプレート内の属性に対応するデータ オブジェクト。オプション。
  {
    // (詳細は次のセクションを参照)
  },

  // {文字列 | 配列}
  // `createElement()` によって構築された子仮想ノード (VNode)、
  // 文字列を使用して「テキスト仮想ノード」を生成することもできます。オプション。
  [
    「まずはテキストを書いてください」
    createElement('h1', '見出し'),
    要素を作成します(MyComponent, {
      小道具: {
        いくつかのプロパティ: 'foobar'
      }
    })
  ]
)

1. データオブジェクトを詳しく調べる

注意すべき点が 1 つあります。v v-bind:classv-bind:styleテンプレート構文で特別に扱われるのと同様に、VNode データ オブジェクトにも対応する最上位フィールドがあります。このオブジェクトを使用すると、通常のHTML attributeだけでなく、 innerHTML (v-html ディレクティブをオーバーライドする) などのDOM propertyもバインドできます。

{
  // `v-bind:class` と同じ API、
  // 文字列、オブジェクト、または文字列とオブジェクトの配列を受け入れます 'class': {
    foo: 真、
    バー: 偽
  },
  // `v-bind:style` と同じ API、
  // 文字列、オブジェクト、またはオブジェクトの配列を受け入れます style: {
    色: '赤'、
    フォントサイズ: '14px'
  },
  // 通常の HTML 属性
  属性: {
    id: 'foo'
  },
  // コンポーネントプロパティ
  小道具: {
    myProp: 'バー'
  },
  // DOMプロパティ
  domProps: {
    内部HTML: 'baz'
  },
  // イベントリスナーは`on`内にあります。
  // ただし、`v-on:keyup.enter` のような修飾子はサポートされなくなりました。
  // 処理関数で keyCode を手動で確認する必要があります。
  の上: {
    クリック: this.clickHandler
  },
  // コンポーネント内で `vm.$emit` によってトリガーされるイベントではなく、ネイティブ イベントをリッスンするコンポーネントにのみ使用されます。
  ネイティブオン: {
    クリック: this.nativeClickHandler
  },
  // カスタムディレクティブ。 `binding` では `oldValue` を使用できないことに注意してください。
  // 割り当て。Vue によって自動的に同期されるためです。
  ディレクティブ: [
    {
      名前: 'my-custom-directive',
      値: '2'、
      式: '1 + 1'、
      引数: 'foo',
      修飾子:
        バー: 真
      }
    }
  ]、
  // スコープ付きスロットの形式は // { name: props => VNode | Array<VNode> } です
  スコープスロット: {
    デフォルト: props => createElement('span', props.text)
  },
  // コンポーネントが別のコンポーネントのサブコンポーネントである場合、スロットの名前を指定する必要があります slot: 'name-of-slot'、
  // その他の特別なトップレベルプロパティ
  キー: 'myKey',
  参照: 'myRef',
  // レンダリング関数で複数の要素に同じ参照名を適用すると、
  // すると `$refs.myRef` は配列になります。
  参照先: true
}

2. 完全な例

この知識があれば、最初に実装したかったコンポーネントを完成させることができます。

var getChildrenTextContent = 関数 (children) {
  戻り値 children.map(function (node) {
    ノードの子を返す
      ? 子のテキストコンテンツを取得します(node.children)
      : ノード.テキスト
  })。参加する('')
}

Vue.component('アンカー付き見出し', {
  レンダリング: 関数 (createElement) {
    // ケバブケースIDを作成する
    var 見出しId = getChildrenTextContent(this.$slots.default)
      .toLowerCase()
      .replace(/\W+/g, '-')
      .replace(/(^-|-$)/g, '')

    要素の作成を返す(
      'h' + このレベル、
      [
        要素を作成します('a', {
          属性: {
            名前: 見出しID、
            href: '#' + 見出しID
          }
        }, this.$slots.default)
      ]
    )
  },
  小道具: {
    レベル:
      タイプ: 数値、
      必須: true
    }
  }
})

3. 制約

VNode は一意である必要があります

コンポーネント ツリー内のすべての VNode は一意である必要があります。つまり、次のレンダリング関数は不正です。

レンダリング: 関数 (createElement) {
  var myParagraphVNode = createElement('p', 'hi')
  createElement('div', [ を返します。
    // エラー - VNode が重複しています
    myParagraphVNode、myParagraphVNode
  ])
}

要素/コンポーネントを何度も繰り返す必要がある場合は、ファクトリ関数を使用してそれを実行できます。たとえば、次のレンダリング関数は、20 個の同一の段落を完全に合法的な方法でレンダリングします。

レンダリング: 関数 (createElement) {
  createElement('div', を返します。
    Array.apply(null, { 長さ: 20 }).map(関数 () {
      createElement('p', 'hi') を返します
    })
  )
}

4. JavaScriptを使用してテンプレート関数を置き換える

1. v-if と v-for

ネイティブ JavaScript で簡単に実行できる限り、Vue のレンダリング関数は独自の代替手段を提供しません。たとえば、テンプレートで使用されるv-ifv-forです。

<ul v-if="アイテムの長さ">
  <li v-for="item in items">{{ item.name }}</li>
</ul>
<p v-else>アイテムが見つかりません。</p>


これらはすべて、 JavaScriptの if/ elseと map を使用してレンダリング関数内で書き換えることができます。

プロパティ: ['アイテム'],
レンダリング: 関数 (createElement) {
  if (this.items.length) {
    createElement('ul', this.items.map(function (item) { を返します。
      createElement('li', item.name) を返します。
    }))
  } それ以外 {
    return createElement('p', 'アイテムが見つかりません。')
  }
}

2. Vモデル

レンダリング関数にはv-modelに直接対応するものはありません。対応するロジックを自分で実装する必要があります。

プロパティ: ['値'],
レンダリング: 関数 (createElement) {
  var 自己 = これ
  createElement('input', を返す)
    domProps: {
      値: 自己.値
    },
    の上: {
      入力: 関数 (イベント) {
        self.$emit('input', イベントターゲット値)
      }
    }
  })
}


これは低レベル化に伴う代償ですが、v-model よりもインタラクションの詳細をより細かく制御できます。

3. イベントとキー修飾子

.passive.capture.onceなどのイベント修飾子の場合、Vue は、 on に使用できる対応するプレフィックスを提供します。

修飾子プレフィックス
。受け身
。捕獲
。一度
.capture.once または
.一度キャプチャ
~!

例えば:

の上: {
  '!click': this.doThisInCapturingMode、
  '~keyup': this.doThisOnce、
  '~!マウスオーバー': this.doThisOnceInCapturingMode
}


他のすべての修飾子の場合、イベント ハンドラー内からイベント メソッドを使用できるため、プライベート プレフィックスは必要ありません。

修飾子処理関数における同等の操作
。停止イベント.stopPropagation()
。防ぐイベント.preventDefault()
。自己(event.target !== event.currentTarget) の場合、戻り値
ボタン:
.enter、.13
if (event.keyCode !== 13) return (他のキー修飾子の場合、13 は別のキーコードに変更できます)
修飾キー:
.ctrl、.alt、.shift、.meta
if (!event.ctrlKey) return (ctrlKey を altKey、shiftKey、または metaKey に変更)

すべての修飾子を使用した例を次に示します。

の上: {
  keyup: 関数 (イベント) {
    // イベントをトリガーする要素がイベントがバインドされている要素でない場合は、 // 戻ります if (event.target !== event.currentTarget) 戻ります
    // Enter キーが押されなかった場合、または // Shift キーが同時に押されなかった場合 // 戻ります if (!event.shiftKey || event.keyCode !== 13) 戻ります
    // イベントのバブリングを停止する event.stopPropagation()
    // 要素のデフォルトのキーアップイベントを防止します。event.preventDefault()
    // ...
  }
}

4. スロット

静的スロットの内容にはthis.$slots介してアクセスできます。各スロットは VNode の配列です。

レンダリング: 関数 (createElement) {
  // `<div><スロット></スロット></div>`
  createElement('div', this.$slots.default) を返します
}


this.$scopedSlotsを通じてスコープ スロットにアクセスすることもできます。各スコープ スロットは、VNode の数を返す関数です。

プロパティ: ['メッセージ'],
レンダリング: 関数 (createElement) {
  // `<div><スロット:text="メッセージ"></スロット></div>`
  createElement('div', [ を返します。
    this.$scopedSlots.default({
      テキスト: this.message
    })
  ])
}

レンダリング関数を使用してスコープ スロットを子コンポーネントに渡す場合は、VNode データ オブジェクトのscopedSlotsフィールドを使用できます。

レンダリング: 関数 (createElement) {
  // `<div><child v-slot="props"><span>{{ props.text }}</span></child></div>`
  createElement('div', [ を返します。
    要素を作成します('child', {
      // データオブジェクトに `scopedSlots` を渡す
      // 形式は { name: props => VNode | Array<VNode> } です
      スコープスロット: {
        デフォルト: 関数 (props) {
          createElement('span', props.text) を返します。
        }
      }
    })
  ])
}

5. JSX

render関数をたくさん書く場合、次のようなコードを書くのは面倒だと感じるかもしれません。

要素を作成します(
  'アンカー見出し'、{
    小道具: {
      レベル: 1
    }
  }, [
    createElement('span', 'こんにちは')、
    ' 世界!'
  ]
)

特に、対応するテンプレートが非常に単純な場合:

<アンカー見出し:level="1">
  こんにちは世界!
</アンカー見出し>

そのため、Vue で JSX 構文を使用するための Babel プラグインがあり、これによりテンプレートに近い構文に戻ることができます。

'./AnchoredHeading.vue' から AnchoredHeading をインポートします。

新しいVue({
  el: '#demo',
  レンダリング: 関数 (h) {
    戻る (
      <アンカー見出しレベル={1}>
        こんにちは世界!
      </アンカーされた見出し>
    )
  }
})

h をcreateElementのエイリアスとして使用することは、Vue エコシステムでは一般的な慣例であり、実際には JSX で必須です。 Vue Babelプラグインのバージョン 3.4.0 以降では、JSX を持つES2015構文 (関数や矢印関数ではない) で宣言されたすべてのメソッドとゲッターにconst h = this.$createElement自動的に挿入されるため、(h) パラメータを削除できます。プラグインの以前のバージョンでは、現在のスコープで h が使用できない場合、アプリケーションはエラーをスローします。

6. 機能コンポーネント

先ほど作成したアンカー タイトル コンポーネントは比較的単純です。状態を管理せず、渡された状態をリッスンせず、ライフサイクル メソッドもありません。実際には、これはいくつかのプロパティを受け入れる単なる関数です。このようなシナリオでは、コンポーネントを機能的としてマークできます。これは、コンポーネントがステートレス (リアクティブ データなし) であり、インスタンスがない (this コンテキストがない) ことを意味します。機能コンポーネントは次のようになります。

Vue.component('my-component', {
  機能的: 真、
  // Propsはオプションです props: {
    // ...
  },
  // インスタンスの不足を補うために // コンテキストレンダリングとして2番目の引数を提供します: function (createElement, context) {
    // ...
  }
})


注: 2.3.0 より前のバージョンでは、関数コンポーネントが props を受け取る場合、 props オプションが必要でした。バージョン 2.3.0 以降では、props オプションを省略することができ、コンポーネントのすべての属性は自動的に暗黙的に props として解決されます。

機能コンポーネントを使用する場合、それらはステートレスかつインスタンスレスであるため、参照は HTMLElement になります。

バージョン 2.5.0 以降では、単一ファイル コンポーネントを使用する場合、テンプレート ベースの機能コンポーネントは次のように宣言できます。

<テンプレート機能>
</テンプレート>


コンポーネントに必要なものはすべて、次のフィールドを持つオブジェクトであるcontextパラメータとして渡されます。

  • props:すべてのpropsを提供するオブジェクト
  • children: VNode の子ノードの配列
  • slots:すべてのスロットを含むオブジェクトを返す関数
  • scopedSlots : (2.6.0+) 渡されたスコープ スロットを公開するオブジェクト。通常のスロットも関数として公開します。
  • data:コンポーネントに渡されるデータ オブジェクト全体。createElement の 2 番目のパラメータとしてコンポーネントに渡されます。
  • parent : 親コンポーネントへの参照
  • listeners : (2.3.0+) このコンポーネントの親コンポーネントによって登録されたすべてのイベント リスナーを含むオブジェクト。これは data.on のエイリアスです。
  • injections : (2.3.0+) inject オプションが使用される場合、このオブジェクトには注入する必要があるプロパティが含まれます。

functional : trueを追加した後、アンカー タイトル コンポーネントのレンダリング関数を更新してコンテキスト パラメーターを追加し、 this.$slots.defaultcontext.childrenに更新してから、this.level を context.props.level に更新する必要があります。

関数コンポーネントは単なる関数であるため、レンダリングのオーバーヘッドは大幅に低くなります。

ラッパーコンポーネントとしても非常に便利です。たとえば、次の操作を行う必要がある場合:

  • 複数のコンポーネントから 1 つをプログラムで選択して、自動的にレンダリングします。
  • 子コンポーネントに渡す前に、子、プロパティ、データを操作します。

以下は、渡されたプロパティの値に基づいて、より具体的なコンポーネントをレンダリングできるsmart-listコンポーネントの例です。

var 空のリスト = { /* ... */ }
var テーブルリスト = { /* ... */ }
var OrderedList = { /* ... */ }
var 順序なしリスト = { /* ... */ }

Vue.component('スマートリスト', {
  機能的: 真、
  小道具: {
    アイテム: {
      タイプ: 配列、
      必須: true
    },
    isOrdered: ブール値
  },
  レンダリング: 関数 (createElement, コンテキスト) {
    関数適切なリストコンポーネント(){
      var アイテム = context.props.items

      if (items.length === 0) 空のリストを返す
      if (typeof items[0] === 'object') は TableList を返します
      if (context.props.isOrdered) は OrderedList を返します。

      順序なしリストを返す
    }

    要素の作成を返す(
      適切なリストコンポーネント()、
      コンテキスト.データ、
      コンテキスト.子供
    )
  }
})

1. 属性とイベントを子要素または子コンポーネントに渡す

通常のコンポーネントでは、props として定義されていない属性はコンポーネントのルート要素に自動的に追加され、同じ名前の既存の属性が置き換えられるか、インテリジェントにマージされます。

ただし、機能コンポーネントでは、この動作を明示的に定義する必要があります。

Vue.component('my- functional-button', {
  機能的: 真、
  レンダリング: 関数 (createElement, コンテキスト) {
    // 属性、イベント リスナー、子ノードなどを完全に透過的に送信します。
    createElement('button', context.data, context.children) を返します。
  }
})


context.data をcreateElementの 2 番目の引数として渡すことで、 my-functional-buttonのすべての属性とイベント リスナーを渡します。実際、これは非常に透過的であるため、これらのイベントでは .native 修飾子さえ必要ありません。

テンプレートベースの機能コンポーネントを使用する場合は、属性とリスナーも手動で追加する必要があります。独自のコンテキストにアクセスできるため、 data.attrs を使用して任意のHTML attributeを渡すことができ、 listeners ( data.on のエイリアス) を使用して任意のイベント リスナーを渡すことができます。

<テンプレート機能>
  <ボタン
    クラス="btn btn-primary"
    v-bind="data.attrs"
    v-on="リスナー"
  >
    <スロット/>
  </ボタン>
</テンプレート>

2. slots() と children の比較

なぜslots()children両方が必要なのか疑問に思うかもしれません。 slots().default childrenに似ていませんか?場合によっては、その通りです。しかし、次のような子を持つ関数コンポーネントの場合はどうでしょうか?

<私の機能コンポーネント>
  <p v-スロット:foo>
    初め
  </p>
  <p>2番目</p>
</my-function-component> 関数コンポーネント


このコンポーネントの場合、 children は 2 つの段落タグを提供しますが、 slots().default 2 番目の匿名段落タグのみを渡し、 slots().foo は最初の名前付き段落タグを渡します。 childrenと slots() の両方を備えているため、コンポーネントにスロット メカニズムを認識させるか、children を渡すことによって他のコンポーネントに渡すかを選択できます。

7. テンプレートのコンパイル

Vue テンプレートは実際にはレンダリング関数にコンパイルされることを知っておくと興味深いかもしれません。これは実装の詳細であり、通常は問題になりません。しかし、テンプレートの機能がどのようにコンパイルされるかを確認したい場合は、非常に興味深いと思うかもしれません。以下は、Vue.compile を使用してテンプレート文字列をオンザフライでコンパイルする簡単な例です。

<div>
        <ヘッダー>
          <h1>私はテンプレートです!</h1>
        </ヘッダー>
        <p v-if="メッセージ">{{ メッセージ }}</p>
        <p v-else>メッセージはありません。</p>
      </div>


与える:

関数匿名(
){
  with(this){return _c('div',[_m(0),(message)?_c('p',[_v(_s(message))]):_c('p',[_v("メッセージがありません。"))])])}
}


静的レンダリング関数:

_m(0): 関数匿名(
){
  with(this){return _c('header',[_c('h1',[_v("私はテンプレートです!")])])}
}

レンダリング関数と JSX の詳細に関するこの記事はこれで終わりです。レンダリング関数と JSX に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vue3 のレンダリング関数における互換性のない変更の詳細な説明
  • Vueレンダリング関数renderの使い方の詳しい説明
  • Vueレンダリング機能の詳しい説明
  • Vue で jsx 構文を正しく使用する方法
  • React-vscode で jsx 構文を使用する際の問題と解決策
  • JSX を使用してコンポーネント パーサー開発を構築する例
  • JSX を使用してカルーセル コンポーネントを実装する方法 (フロントエンドのコンポーネント化)
  • Vueコンポーネントjsx構文の具体的な使用
  • Vue jsx の使用ガイドと vue.js での jsx 構文の使用方法
  • Vue が JSX 構文をサポートする方法の詳細な説明

<<:  Dockerコンテナ接続実装手順の分析

>>:  MySQL NULLがピットを引き起こした

推薦する

Vue プロジェクトにインターフェース リスニング マスクを追加する方法

1. 事業背景マスク レイヤーを使用してユーザーの異常な操作を遮断する方法は、フロントエンドでよく使...

Win10 での MySQL 8.0 ログインでユーザー 'root'@'localhost' のアクセスが拒否される (パスワード使用: YES) 問題の解決方法

最近、MySQL を学び始めました。インストールはスムーズに進み、インターネット上の既成のチュートリ...

ubuntu18.04 での qt5.12.8 のインストールと環境設定に関する詳細なチュートリアル

環境システム: Ubuntu 18.04ソフトウェア: qt5.12.8 1. インストールパッケー...

mysql はフィールドコンテンツの一部を置き換え、mysql は関数 replace() を置き換えます。

[mysql] replace の使用方法 (フィールドの内容の一部を置き換える) [mysql]...

JavaScriptにおけるこのポインティング問題の詳細な説明

序文信じてください。この記事の 7️⃣ ステップを覚えておけば、JS の this リファレンスを完...

Dockerコンテナを閉じずに終了する方法の詳細な説明

Docker コンテナに入った後、コンテナを終了すると、コンテナは Exited 状態に変わります。...

MySQL での mysqladmin 日常管理コマンドの概要 (必読)

mysqladmin ツールの使用形式は次のとおりです。 mysqladmin [オプション] コ...

Docker で最初のアプリケーションをデプロイする方法

前回の記事では、Docker Desktop をインストールし、Kubernetes を有効にしまし...

ウェブページのメモリ使用量とCPU使用量を削減する方法

一部の Web ページは大きく見えなくても開くのに非常に時間がかかる場合があります。一方、他の We...

ネイティブ JS でスネーク ゲームを書く

この記事では、参考までに、JSでスネークゲームを書くための具体的なコードを紹介します。具体的な内容は...

シンプルなスネークゲームを実現するネイティブjs

この記事では、スネークゲームを実装するためのjsの具体的なコードを参考までに共有します。具体的な内容...

Vue の一般的な問題と解決策の概要 (推奨)

Vue に限定されず、他の種類の SPA プロジェクトにも当てはまる問題がいくつかあります。 1....

Ubuntu 18.04 で apt ソースを Alibaba Cloud ソースに変更する詳細なプロセス

目次序文: Ubuntu 18.04 は apt ソースを Alibaba Cloud ソースに変更...

Linux サーバーに Java Web プロジェクトをデプロイするための完全なチュートリアル

この記事は主にインターネット上の他のチュートリアルを参考にしています。実際に操作した上でのまとめです...

Angularルーティングの基礎の詳細な説明

目次1. ルーティング関連オブジェクト2. ルーティングオブジェクトの場所3. ルーティング構成4....