Vueコンポーネントテンプレートを動的にロードする

親愛なるハブロフチアン! 最近、私たちのチームで、サーバーレンダリングを含むVue.jsフレームワークの使用を開始しましたが、その後、特にプログラマーとしての多くの問題に遭遇しました。



サイトのレイアウトの変更は、私を通して発生しました。 タイトルを変更するか、ブロックの場所を変更するかに関わらず、htmlコードの一部が投げ出された後、この部分を必要なコンポーネントに挿入し、必要な変数とメソッドを置き換え、webpackを実行し、コードをサーバーにアップロードする必要がありました。



サーバー上で監視モードでwebpackを使用するか、同僚に必要なコマンドのリストを提供することができますが、同僚にとってはやや困難です。

そのため、サーバーからデータを取得して、テンプレートの動的な読み込みを行うことにしました。



例として、このアプローチの単純化されたバージョンを検討してください。



構造は次のとおりです。





コンポーネントでテンプレートのプリロードを使用するには、サーバーからデータが受信されるのを待つ必要がありますが、Promisは完璧です。 その結果、Vueコンポーネントの2つのラッパーを取得しました。



wrapComponent -Vueコンポーネントのグローバル登録用



// ./wrapComponent.js import Vue from 'vue'; import axios from 'axios'; export default function wrapComponenet(name, template, component) { return () => { return new Promise((resolve, reject) => { axios.get(template).then((fetchData) => { const template = fetchData.data; Vue.component(name, { ...component, template, }); resolve(); }); }); }; }
      
      





wrapPageComponent -Vueコンポーネントを返します。



 // ./wrapPageComponent.js import axios from 'axios'; export default function wrapPageComponent(name, template, component) { return () => { return new Promise((resolve, reject) => { axios.get(template).then((fetchData) => { const template = fetchData.data; resolve({ ...component, template, }); }); }); }; }
      
      





以下で使用するコードのほとんどは、サーバーレンダラーvue.js( ssr.vuejs.org )の公式ドキュメントから取得されているため、これについては詳しく説明しません。



 // ./server/index.js // Koa import Koa from 'koa'; import staticFile from 'koa-static'; //   Vue- import createApp from '../serverEntry.js'; // Vue  import { createRenderer } from 'vue-server-renderer'; const PORT = 4000; const server = new Koa(); server.use(staticFile('public')); server.use((ctx) => { //    const app = await createApp(); //  html -  const html = await renderer.renderToString(app); const page = ` <!DOCTYPE html> <html lang="ru"> <head> <title>Vue App</title> <base href="/"> <meta charset="utf-8"> </head> <body> <div id="root">${html}</div> <script src="js/app.js"></script> </body> </html> `); ctx.body = page; }); server.listen(PORT, (err) => { if (err) console.log(err); console.log(`Server started on ${PORT} port`); }); export default server;
      
      





KoaJSはサーバーフレームワークとして使用されますが、他のものを使用することも、まったく使用しないこともできます。



次に、Vueアプリケーションのサーバーエントリポイントについて考えてみましょう。すべてがシンプルで、アプリケーションが生成されるのを待って結果を返します。 将来、このエントリポイントはルーティング、ストレージなどによって拡張されます。



 // ./serverEntry.js import { createApp } from './app'; export default async (context) => { const { app } = await createApp(); return app; };
      
      





クライアントエントリポイントでも同じことが起こります



 // ./client.js import { createApp } from './app'; createApp() .then(({ app }) => { app.$mount('#app'); });
      
      





そして最後に、Vueアプリケーション自体に到達しました。



 // ./app/index.js //  Vue import Vue from 'vue'; import VueAxios from 'vue-axios'; //   import axios from 'axios'; //  Vue import App from './App'; //   import mainMenu from './Components/MainMenu'; import mainContent from './Components/MainContent'; Vue.use(VueAxios, axios); axios.defaults.baseURL = 'http://localhost:4000/'; export async function createApp( context ) { const appComponent = await App(); const app = new Vue({ render: (h) => h(App), }); return new Promise((resolve, reject) => { //      Promise const allComponents = [ mainMenu(), mainContent(), ]; Promise.all(allComponents) .then(() => { resolve({ app, router }); }); }); }
      
      





そして、直接、Vueコンポーネント自体はラッパーにラップされます(トートロジーについてはごめんなさい)。



 // ./app/App.js import wrapPageComponenets from '../wrapPageComponents'; export default wrapAppComponenets('App', '/template/App.html', { name: 'App', });
      
      





 // ./app/Components/MainMenu.js import wrapComponenets from '../../wrapComponents'; export default wrapComponenets('main-menu', '/templates/MainMenu.html', { data() { return { title: 'VueJS App'}; } })
      
      





 // ./app/Components/MainContent.js import wrapComponenets from '../../wrapComponents'; export default wrapComponenets('main-component', '/templates/MainContent.html', { data() { return { name: ' !'}; }, methods: { clickHandle() { alert('   '); } } });
      
      





そして、 パブリック/テンプレート/にあるこれらのコンポーネントに対応するテンプレート



 <!-- ./public/templates/App.html --> <div> <main-menu></main-menu> <main-content></main-content> </div>
      
      





 <!-- ./public/templates/MainMenu.html --> <nav> <ul> <li class="logo">{{title}}</li> </ul> </nav>
      
      





 <!-- ./public/templates/MainContent.html --> <div> <h1 @click="clickHandle()">{{name}}</h1> </div>
      
      





以上です。 これで、すべてのテンプレートがサーバーから読み込まれます。同僚に対して、このテンプレートまたはそのテンプレートで置き換えることができる変数とメソッドのリストを提供できます。私のメソッドへの参加は、新しいメソッドと変数の追加と、htmlテンプレートでの最小限の作業に限定されます。 また、v-show、v-if、v-forディレクティブの使用を説明する方がはるかに簡単であることが判明しました。



ご清聴ありがとうございました!



All Articles