質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.19%

Vue.jsでのレンダリングが遅い

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 9,079

math346613

score 24

 Vue.jsとElement UIを使ってフロントエンドを開発しています

Vue.jsとElement UIを使っているのですがページにアクセスした際に
Vue.jsとElement UIの機能が反映されるまでに少し時間差があります

<el-tag>Hoge</el-tag>

の場合はHogeという文字が現れてからタグの装飾がされる、、ような感じです

またv-cloakを指定しても

<el-tag>Hoge</el-tag>自体が周りより遅れて描写されます

これはVue.jsが描写している時間とも言えますが他のサイトであまり見るようなことはありません

これらの原因は何でしょうか?

初心者なのでお手柔らかにお願いします

 環境

Google Chrome 67.0.3396.99
Vue.js 2.5.7 
npm 5.6.0
Laravel 5.6.24
CentOS 6.8

ソースコード例

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Hello</title>
  <meta name="csrf-token" content="{{ csrf_token() }}">
  <link rel="stylesheet" href="{{ asset('css/app.css') }}"/>
  <script type="text/javascript">
       window.Laravel = window.Laravel || {};
       window.Laravel.csrfToken = "{{csrf_token()}}";
  </script>
</head>
<body>
<div id="app">
  <nav class="navbar navbar-expand-md navbar-light bg-success navbar-laravel">
    <div class="container">
      <a class="navbar-brand text-white font-weight-bold" href="{{ url('/') }}">
              {{ config('app.name', 'Laravel') }}
      </a>
      <button class="navbar-toggler" type="button" data-toggle="collapse"
           data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <!-- Left Side Of Navbar -->
        <ul class="navbar-nav mr-auto">
        </ul>
      <!-- Right Side Of Navbar -->
        <ul class="navbar-nav ml-auto">
        <!-- Authentication Links -->
        @guest
          <li><a class="nav-link text-white" href="{{ route('login') }}">{{ __('Login') }}</a></li>
          <li><a class="nav-link text-white" href="{{ route('register') }}">{{ __('Register') }}</a></li>
        @else
          <li class="nav-item dropdown">
            <a id="navbarDropdown" class="nav-link dropdown-toggle text-white" href="#"
                role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
              {{ Auth::user()->name }} <span class="caret"></span>
            </a>

            <div class="dropdown-menu" aria-labelledby="navbarDropdown">
              <a class="dropdown-item text-success" href="{{ route('logout') }}"
                  onclick="event.preventDefault();document.getElementById('logout-form').submit();">
                {{ __('Logout') }}
              </a>
              <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
              @csrf
              </form>
              <a class="dropdown-item text-success" href="{{ url('/user/register') }}">
                {{ __('詳細設定') }}
              </a>
            </div>
          </li>
        @endguest
        </ul>
      </div>
    </div>
  </nav>
  <main class="my-5">
    <el-tag>HogeHoge</el-tag>
  </main>
</div>
@include('common.footer')
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');

window.Vue = require('vue');
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import locale from 'element-ui/lib/locale/lang/ja'

Vue.use(ElementUI, { locale })

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */


const app = new Vue({
    el: '#app',
});

jsやjQueryでも同様の現象が起こりますが
これはそもそもWEBページで読み込み後にjsで描画するのならば起こる現象なのでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • oikashinoa

    2018/07/31 23:04

    js/app.jsとかも可能なら上げたほうが良いですよ。回答者で再現できるように出来るだけソースは"可能な限り"上げるべきです。(見せちゃまずいところは隠して下さいね)…本件詳しくないのと出張で試す事も出来ないので、他の方も頼ってください。あとheroku使っているのでしょうか?その辺も書いたほうが良いかも。

    キャンセル

  • math346613

    2018/08/02 05:50

    拙い質問にアドバイスありがとうございます 以後気を付けたいと思います

    キャンセル

  • math346613

    2018/08/02 05:50

    ローカル開発環境で試しております

    キャンセル

回答 3

+1

解決方法 v-cloakを使う

v-cloakはデータバインディング完了までこのディレクティブがつけられた要素の描画は遅れさせ
初期表示時の画面のちらつきを抑える効果がある

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Hello</title>
  <meta name="csrf-token" content="{{ csrf_token() }}">
  <link rel="stylesheet" href="{{ asset('css/app.css') }}"/>
  <script type="text/javascript">
       window.Laravel = window.Laravel || {};
       window.Laravel.csrfToken = "{{csrf_token()}}";
  </script>
</head>
<body>
<div id="app">
  <nav class="navbar navbar-expand-md navbar-light bg-success navbar-laravel">
    <div class="container">
      <a class="navbar-brand text-white font-weight-bold" href="{{ url('/') }}">
              {{ config('app.name', 'Laravel') }}
      </a>
      <button class="navbar-toggler" type="button" data-toggle="collapse"
           data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <!-- Left Side Of Navbar -->
        <ul class="navbar-nav mr-auto">
        </ul>
      <!-- Right Side Of Navbar -->
        <ul class="navbar-nav ml-auto">
        <!-- Authentication Links -->
        @guest
          <li><a class="nav-link text-white" href="{{ route('login') }}">{{ __('Login') }}</a></li>
          <li><a class="nav-link text-white" href="{{ route('register') }}">{{ __('Register') }}</a></li>
        @else
          <li class="nav-item dropdown">
            <a id="navbarDropdown" class="nav-link dropdown-toggle text-white" href="#"
                role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
              {{ Auth::user()->name }} <span class="caret"></span>
            </a>

            <div class="dropdown-menu" aria-labelledby="navbarDropdown">
              <a class="dropdown-item text-success" href="{{ route('logout') }}"
                  onclick="event.preventDefault();document.getElementById('logout-form').submit();">
                {{ __('Logout') }}
              </a>
              <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
              @csrf
              </form>
              <a class="dropdown-item text-success" href="{{ url('/user/register') }}">
                {{ __('詳細設定') }}
              </a>
            </div>
          </li>
        @endguest
        </ul>
      </div>
    </div>
  </nav>
  <main class="my-5">
    <el-tag>HogeHoge</el-tag>
  </main>
</div>
@include('common.footer')
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>

のid="app"部分を

<div id="app" v-cloak

</div>

とすることでjsの処理をすべて終えてから画面に表示させる

疑問1,なぜ描画が遅れるのか?

jsを使った初期描画ではこの動作がデフォルトとなる、これに対して多くの場合ローディング画面を表示するなどして対応している

疑問2,asset('/js/app.js')を<head></head>内に記述する方法はなぜこの場合において有効ではないのか?

第一に<head></head>内に記述する方法では先にapp.jsを読み込むためにそもそもページロードが遅くなる,第二にapp.jsに操作したい要素を記述しておいてもapp.jsを先に読み込んでしまうとその要素が見つからないのでapp.jsの記述は無効となる なので多くの場合bodyタグの直前に記述される

疑問3,v-showを使って描画中はローディング画面を魅せる方法はなぜこの場合無効であったか?

(この場合については的確に分かっていないので推測で書くことにする)
v-showを使うにはVue.jsの読み込みが必要だがそれがbodyタグの直前に存在するのでどうしても
body内を描画→app.jsの読み込み→v-showの利用となり、一瞬body内の要素がちらつくことになる(と推測)

結論としては

app.jsを含めた画面描画をする場合で他に方法を試してダメな場合は全体にv-cloakとする

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

0

<script src="{{ asset('js/app.js') }}"></script>


この部分でvueのロードや準備をすると読みました(質問に追加していただいたふたつ目のソースがコレですよね?)

この位置に書かれているのは理由ありますか?
もっと早い段階に移動させてはいかがですか?(例えば window.Laravelなんとか の処理の前後)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/02 21:18

    おめでとうございます。可能なら、新たに解答欄に最終コードを書いていただけると私の勉強にもなるので嬉しいです。

    キャンセル

  • 2018/08/02 22:31

    了解しました、今回いろいろと調べてきた中で自分が分かったことをまとめておきましたので一読ください
    お互い頑張りましょう!!

    キャンセル

  • 2018/08/02 22:31

    本当にありがとうございました。

    キャンセル

0

解決方法 v-cloakを使う

v-cloakはデータバインディング完了までこのディレクティブがつけられた要素の描画は遅れさせ
初期表示時の画面のちらつきを抑える効果がある

これを

<div id="app" v-cloak></div>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.19%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる