Hiding vue.js template before it is rendered

2019-03-09 21:55发布

I am trying to hide the vue.js template's contents before it is fully rendered. Consider following template:

<div class="loader"> 
  <table class="hidden">
    <tr v-for="log in logs">
      <td>{{log.timestamp}}</td>
      <td>{{log.event}}</td>
    </tr>
  </table>
</div>

When I render this template on the server, the user sees the contents of the <tr> element before it is rendered. For this reason I use the class hidden to hide it, before it is fully rendered.

Also before it is rendered, I am showing a loader element with some animated progressbar.

Once it is rendered, I would just call element.show() in jQuery and hide the progressbar as well. My question is: is it okay to mix jQuery and vue.js to achieve this?

var vueLogs = new Vue({
  el: "#checkInLogsHolder",
  data: {logs: []}
});
var holder = $("#checkInLogsHolder");

function response(payload) {
  // hiding the loader animation
  holder.find(".loader").remove();
  // showing the rendered table
  holder.find("table").show();
  vueLogs.logs.unshift(payload);
}

Is there some better way to do this?

标签: vue.js
5条回答
Rolldiameter
2楼-- · 2019-03-09 22:05

Vue already has a v-cloak directive built in, you just need to add the relevent css class:

[v-cloak] {
  display: none;
}

And then apply it to your element like so:

<div v-cloak>
  {{message}}
</div>

Here's the JSFiddle: https://jsfiddle.net/2jbe82hq/

If you remove v-cloak in that fiddle you will see the mustached {{message}} before the instance has been mounted.

If you want to display a loader while you retrieve data from your server, then you combine a boolean flag with v-if to show and hide the loader:

var vm = new Vue({
  el: "#app",
  created(){
    this.$http.get('url').then(response => {
      // set loader to false
      this.loading = false;
    });
  },
  data: {
    message: 'Hello Vue!',
    loading: true
  }
});

You can then do:

<div v-if="loading">
   Loading...
</div>
<div v-else>
    {{message}}
</div>

Here's the JSFiddle for that: https://jsfiddle.net/fa70phLz/

It's also possible to use a loading class as well and then use v-bind:class to apply and remove the class based on the flag, which is useful if you want to overlay the entire page with a loader.

<div :class="{'loading': loading}"></div>
查看更多
干净又极端
3楼-- · 2019-03-09 22:11

I'm just adding a useful things of v-cloak to add a spinner before rendering the full HTML file and thanks to Adam for his Gist - https://gist.github.com/adamwathan/3584d1904e4f4c36096f

If you want to add a spinner before loading your page, you can read this -

  • Add v-cloak inside #app.
  • Make one div v-cloak--inline which we want to show before HTML page rendered.
  • Another Div which will contain the full page with v-cloak--hidden.
  • Must have to add the css's given here.

Let's code - In Master Page,

 <div id="app">

  <div v-cloak>

   <div class="v-cloak--inline"> <!-- Parts that will be visible before compiled your HTML -->
      <i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
      <span class="sr-only">Loading...</span>
   </div>

   <div class="v-cloak--hidden"> <!-- Parts that will be visible After compiled your HTML -->
      <!-- Rest of the contents -->
      @yield('content')
   </div>

  </div>

</div>

With adding these Extra CSS's for v-cloak.

[v-cloak] .v-cloak--block {
  display: block;
}
[v-cloak] .v-cloak--inline {
  display: inline;
}
[v-cloak] .v-cloak--inlineBlock {
  display: inline-block;
}
[v-cloak] .v-cloak--hidden {
  display: none;
}
[v-cloak] .v-cloak--invisible {
  visibility: hidden;
}
.v-cloak--block,
.v-cloak--inline,
.v-cloak--inlineBlock {
  display: none;
}

Then Before compiling the HTML file, a spinner will render. After compiled, spinner will hide. You can use this in your master page. Thus in every time when you load a new page, that will see the effects.

See the Gist - https://gist.github.com/adamwathan/3584d1904e4f4c36096f

查看更多
4楼-- · 2019-03-09 22:13

By adding v-cloak to whole page root div will work

<div id="app">
    <div v-cloak>
        Hello {{ name }}
    </div>
 </div>

<style>
   [v-cloak] {
       display: none;
  }
 </style>

Hide elements during loading using "v-cloak"

查看更多
该账号已被封号
5楼-- · 2019-03-09 22:29

I would hesitate to mix jQuery in Vue.js code for the reason that Vue.js provides a suite of tools that generally eliminate the need for jQuery.

Since you are loading the page and displaying a progress bar, you can take advantage of the Vue.js lifecycle hooks: [created, mounted, beforeUpdate, updated, etc. etc.].

What I would do is to create a small div containing the progress bar, and then an adjacent element with the actual content to display after load. Set a data on the component instance, and then use the lifecycle hooks to toggle the display.

<div v-if='loading'>
  <div class='progress-bar'>
  <!-- Loading bar markup here -->
  </div>
</div>

<div v-else class='content'>
  <table>
  <!-- Content -->
    <tr v-for="log in logs">
      <td>{{log.timestamp}}</td>
      <td>{{log.event}}</td>
    </tr>

  </table>
</div>

Then in the script part of the template:

export default {
  data() {
    return: {
      loading: true,
      logs: [],
      message: ''
    };
  },
  methods: {
    fetchLogs() {
      // using vue-resource / ajax library like axios
      this.$http.get('/api/logs').then((logs) => {
        if (logs) {
          this.logs = logs;
          setTimeout(() => {
            this.loading = false;
          }, 1000);
        } else {
          this.message = 'No logs to display';
          this.loading = false;
        }
      });
    }
  },
  mounted() {
    this.fetchLogs();
  }
};

Using this method, you can also bind classes to the elements to create smooth CSS transitions.

查看更多
Melony?
6楼-- · 2019-03-09 22:30

Other than v-cloak. You could also use v-text attribute. So you don't have to deal with it in CSS.

查看更多
登录 后发表回答