

Expressで作成したサーバー内のローカルファイルの内容をフロントエンドのVue.jsのテンプレートオブジェクトを生成する際のdataとして与えたいです。

唯の文字列であれば上手くできそうなのですが、目的のファイルはmarkdown形式で多数の改行やバッククォートが含まれています。

そのため、クライアントで動かすjavascript内でテンプレートを展開すると途中に存在するバッククォートで文字列が終了してしまいうまく渡すことができません。

expressのルーティングが以下のようになっています。

[code]

    router.get('/', (req, res, next) => {
        const str = fs.readFileSync(filepath).toString().replace('`', '\`');
        res.render('md', { data: obj });
    });
    
[/code]

また、フロント側のejsは以下のようになっています。

[code]

    <script src='https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.5/marked.js'></script>
    
    <script>
        window.onload = () => {
            new Vue({
                el: '#editor',
                data: {
                    input: `<%= data %>`
                },
                filters: {
                    marked: marked,
                },
            });
        };
    </script>
    </head>
    <body>
    ...
    
[/code]

chrome等のインスペクタで確認すると、<%=
%>で展開しているdataの文字列のバッククォートで文字列が終了してしまい、それ以降の文字が正常に取り込まれていませんでした。

res.localsに値を持たせることでクライアント側のjsで用いることができるのか？とも思いましたがクライアントのjsではundefinedとなってしまいましたため共有はできないようです。

サーバーで生成したdataの中身をVueのオブジェクトに渡す方法はありますか？


CC BY-SA 4.0
2018-10-19T13:37:05.843
49462
2018-10-20T04:27:13.457
19959
question
node.js vue.js
node.js expressでフロントエンドのVue.jsのオブジェクトを生成するスクリプトに変数を渡したい


dataは文字列ということでよいでしょうか。それならば、`JSON.stringify`により文字列をJSON表現にして渡す方法があります。

ルーティング時にはこのようにして、文字列をJSON表現に変換します。

[code]

    res.render('md', { data: JSON.stringify(obj) });
    
[/code]

フロント側のスクリプトでは、JSON表現された文字列をそのまま文字列リテラルとみなして利用します。

[code]

            data: {
                input: <%- data %>
            },
    
[/code]

`JSON.stringify`を用いることで、バッククオートや改行などを含んだ文字列でも適切にエスケープしてJSONで表現された文字列として表してくれます。JSONで表現された文字列はJavaScriptの文字列リテラルとしても妥当ですから（※）、JavaScriptコードとしてフロント側のスクリプトに埋め込むことができます。

※
ただし、古いブラウザでは元の文字列にU+2028またはU+2029が含まれている場合にエラーが発生してしまいます（[参考](https://github.com/tc39/proposal-
json-
superset)）。普通のmarkdownテンプレートならそんなものが混ざることは無いと思いますが、ユーザー入力などをこの方法で扱う場合は事前に除去するなど注意を払う必要があると思います。

* * *

## 追記

上記の方法は文字列中に`</script>`が含まれている場合にJavaScriptコードが終了してしまう問題がありました。それを回避する方法としては、JSON表現の文字列をEJSにHTMLエスケープしてもらってscript要素の属性に入れておいて、それをスクリプト側から取得するという方法があります。

[code]

    res.render('md', { data: obj });
    
[/code]

* * *
[code]

    <script data-input="<%= data %>">
        window.onload = () => {
            new Vue({
                el: '#editor',
                data: {
                    input: document.currentScript.dataset.input
                },
                filters: {
                    marked: marked,
                },
            });
        };
    </script>
    
[/code]

このサンプルではクライアント側の属性は`document.currentScript.dataset.input`で取得しましたが、これはIE11では動かないようなのでもしIE11対応が必要な場合はscript要素にIDをふったりして対応してください。


CC BY-SA 4.0
2018-10-19T13:41:54.287
49463
2018-10-20T04:27:13.457
2018-10-20T04:27:13.457
30079
30079
49462
answer