Backbone.js テンプレートを分離する

引き続き、BackBone.js の件です。

ドットインストールでは、テンプレートは html に記述した<script type="text/template">~~~</script>を参照していました。
Vue.js のように、テンプレートは js を読み込む html から分離させたいです。

やってみました。

目次

参考

ディレクトリ構成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|   package-lock.json
| package.json
| webpack.config.js
|
+---dist
| index.html
|
+---node_modules
\---src
| index.js
|---collection
| memos.js
|
+---model
| memo.js
|
\---view
memo-template.html
memo_view.js

呼び出す html

backbone.js で作成したらアプリケーションを呼び出すdist/index.htmlは、次のようにしておきます。

dist/index.html
1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head>
<title>webpack-Backbone</title>
</head>
<body>
<h1>Memo</h1>
<div id="memo"></div>
<script src="app.js"></script>
</body>
</html>

webpack でバンドル、テンプレートは分離するので、シンプルですね。

とりあえず埋め込み

まずはとりあえず、Backbone.View にテンプレートを埋め込めば、.vueファイルよろしく管理できると考えました。

src/view/memo_view.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const _ = require("underscore");
const $ = require("jquery");
const Backbone = require("backbone");

const MemoView = Backbone.View.extend({
template: _.template("<p>テンプレート <%= id %>:<%= text %></p>"),
render: function () {
const template = this.template(this.model.toJSON());
this.$el.html(template);
return this;
},
});

module.exports = MemoView;

こちらのビューを使って、以下のsrc/index.jsで呼び出しします。

src/index.js
1
2
3
4
5
6
7
8
const $ = require("jquery");
const Memo = require("./model/memo");
const MemoView = require("./view/memo_view");

const memo = new Memo({ id: 1, text: "text1" });
const memoView = new MemoView({ model: memo });

$("#memo").html(memoView.render().el);

用意できたら、API サーバーと webpaack-dev-server を両方起動して、ブラウザでアクセスします。

次のように表示されます。

index.html の<div id="memo"></div>の部分に、テンプレートが反映されています。

クラスの中で記述したくないので、分離する

View の中に書くことでアプリケーションを読みだす html とは分離できました。
しかし、クラスの中に直接記述すると見通しは良くないと感じます。
テンプレートの部分だけクラスの外に分離してみます。

src/view/memo_view.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const _ = require("underscore");
const $ = require("jquery");
const Backbone = require("backbone");

const temp = `
<p>テンプレート <%= id %>:<%= text %></p>
`;

const MemoView = Backbone.View.extend({
template: _.template(temp),
render: function () {
const template = this.template(this.model.toJSON());
this.$el.html(template);
return this;
},
});

module.exports = MemoView;

外部に出せたので見通し自体は良くなりました。
しかし、ただの文字列として書いているので、エディタのサポートがないので少し面倒とも感じます。

テンプレートを別のファイルに分離する

調べると非同期で読み込むように ajax で取得するものなどありました。
どうせ webpack を使うので、テンプレートもバンドルできるように試みました。

以下コマンドでhtml-loaderをインストールします。
npm install --save-dev html-loader

インストールできたら、webpack.config.jsを以下のように編集します。

webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
module.exports = {
mode: "development",
// エントリーポイントの.jsファイル
entry: `./src/index.js`,
// ファイルの出力設定
output: {
// 出力ファイルのディレクトリ名
path: `${__dirname}/dist`,
// 出力ファイル名
filename: "app.js",
},
module: {
rules: [
//html-loaderを導入
{
test: /\.html$/i,
loader: "html-loader",
},
],
},
//webpack-dev-server設定
devServer: {
contentBase: "dist",
//open: true,
proxy: {
"/api": {
target: "http://localhost:3000",
},
},
},
devtool: "inline-source-map",
};

webpack.config.jsを編集できたら、view/memo-template.htmlを作成します。

src/view/memo-template.html
1
<p>テンプレート <%= id %>:<%= text %></p>

分離したテンプレートview/memo-template.htmlsrc/view/memo_view.jsを読み込みます。
const template = require("./memo-template.html");の部分です。

編集したsrc/view/memo_view.jsが以下のようになります。

src/view/memo_view.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const _ = require("underscore");
const $ = require("jquery");
const Backbone = require("backbone");

//テンプレート読み込み
const template = require("./memo-template.html");

const MemoView = Backbone.View.extend({
template: _.template(template),
render: function () {
const template = this.template(this.model.toJSON());
this.$el.html(template);
return this;
},
});

module.exports = MemoView;

用意できたら、API サーバーと webpaack-dev-server を両方起動して、ブラウザでアクセスします。

次のように表示されます。

テンプレートを完全に別の html ファイルに分離できたので、エディタのサポートも効くようになります。


backbone.js でテンプレートの分離をしてみました。
html-loaderを使うことできれいに分離できました。

ではでは。