在渲染之前隐藏 vue.js 模板

Posted

技术标签:

【中文标题】在渲染之前隐藏 vue.js 模板【英文标题】:Hiding vue.js template before it is rendered 【发布时间】:2017-07-04 20:37:24 【问题描述】:

我试图在完全呈现之前隐藏 vue.js 模板的内容。考虑以下模板:

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

当我在服务器上渲染此模板时,用户会在渲染之前看到&lt;tr&gt; 元素的内容。出于这个原因,我使用 hidden 类在它完全渲染之前隐藏它。

在渲染之前,我展示了一个带有动画进度条的加载器元素。

渲染完成后,我只需在 jQuery 中调用 element.show() 并同时隐藏进度条。我的问题是:可以混合使用 jQuery 和 vue.js 来实现这一点吗?

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);

有更好的方法吗?

【问题讨论】:

How do I hide the VueJS syntax while the page is loading?的可能重复 混合使用 jQuery 和 vue.js 并没有什么“错误”,尽管对于这是否是一个好主意,你会得到很多不同的意见。我这样做了,但因为我已经将它用于引导程序。 【参考方案1】:

Vue已经内置了v-cloak指令,你只需要添加相关的css类:

[v-cloak] 
  display: none;

然后像这样将它应用到你的元素:

<div v-cloak>
  message
</div>

这是 JSFiddle:https://jsfiddle.net/2jbe82hq/

如果您在该小提琴中删除v-cloak,您将在实例挂载之前看到带有胡子的message

如果您想在从服务器检索数据时显示loader,那么您可以将布尔标志与v-if 结合起来以显示和隐藏加载程序:

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
  
);

你可以这样做:

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

这是 JSFiddle:https://jsfiddle.net/fa70phLz/

也可以使用loading 类,然后使用v-bind:class 根据标志应用和删除类,如果你想用loader 覆盖整个页面,这很有用。

<div :class="'loading': loading"></div>

【讨论】:

【参考方案2】:

我只是添加了 v-cloak 的一个有用的东西在渲染完整的 html 文件之前添加一个 spinner 并感谢 Adam 的 Gist - https://gist.github.com/adamwathan/3584d1904e4f4c36096f

如果您想在加载页面之前添加微调器,可以阅读此内容 -

#app 中添加v-cloak。 制作一个 div v-cloak--inline,我们希望在呈现 HTML 页面之前显示它。 另一个 Div 将包含带有v-cloak--hidden 的整页。 必须添加此处给出的 css。

让我们编写代码 - 在母版页中

 <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>

为 v-cloak 添加这些额外的 CSS。

[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;

然后在编译 HTML 文件之前,将渲染一个微调器。编译后,微调器将隐藏。您可以在母版页中使用它。因此,每次加载新页面时,都会看到效果。

查看要点 - https://gist.github.com/adamwathan/3584d1904e4f4c36096f

【讨论】:

据我了解 v-cloak div 在这里除了隐藏[v-cloak] .v-cloak--invisible 的css规则之外没有任何作用这是因为一旦应用程序被主应用程序div的内容简单地替换为vue加载。基本上你可以做&lt;div id="app"&gt;Loading...&lt;/div&gt;,它会有同样的效果。 v-cloak 在已经加载 vue 的组件中很有用【参考方案3】:

通过将 v-cloak 添加到整个页面根 div 将起作用

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

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

Hide elements during loading using "v-cloak"

【讨论】:

【参考方案4】:

我不愿意在 Vue.js 代码中混合使用 jQuery,因为 Vue.js 提供了一套工具,通常可以消除对 jQuery 的需求。

由于您正在加载页面并显示进度条,因此您可以利用 Vue.js 生命周期挂钩:[created、mounted、beforeUpdate、updated 等]。

我要做的是创建一个包含进度条的小 div,然后创建一个包含实际内容的相邻元素以在加载后显示。在组件实例上设置数据,然后使用生命周期挂钩来切换显示。

<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>

然后在模板的脚本部分:

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();
  
;

使用此方法,您还可以将类绑定到元素以创建平滑的 CSS 过渡。

【讨论】:

【参考方案5】:

我创建了一个纯 CSS 解决方案,基于 @Maniruzzaman Akask 解决方案。 (我的模板中没有安装很棒的字体,结果很酷;-)

步骤

1) 将 v-cloak 标签放在您的#app div 中(如上述答案中所建议的那样)

<div id="app">

  <div v-cloak>

  <div class="v-cloak--inline"> <!-- Parts that will be visible before compiled your HTML -->
    <div class="spinner"></div> <!-- this is a cool spinner taken from spinKit -->
  </div>

  <div class="v-cloak--hidden"> 
           <!-- Parts that will be visible After compiled your HTML -->
  </div>

  <footer>Content</footer> <!-- my footer is static, so I show it from the beginning -->
</div>

2) 使用来自https://tobiasahlin.com/spinkit/

3) 添加两个元素的 CSS

微调器的 CSS

.spinner 
  width: 40px;
  height: 40px;
  background-color: red;

  margin: 400px auto;
  -webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
  animation: sk-rotateplane 1.2s infinite ease-in-out;


@-webkit-keyframes sk-rotateplane 
  0%  -webkit-transform: perspective(120px) 
  50%  -webkit-transform: perspective(120px) rotateY(180deg) 
  100%  -webkit-transform: perspective(120px) rotateY(180deg)  rotateX(180deg) 


@keyframes sk-rotateplane 
  0%  
    transform: perspective(120px) rotateX(0deg) rotateY(0deg);
    -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg) 
   50%  
    transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
    -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) 
   100%  
    transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
    -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
  

v-cloak 的 CSS

[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;

【讨论】:

【参考方案6】:

v-cloak 除外。 您也可以使用v-text 属性。所以你不必在 CSS 中处理它。

【讨论】:

以上是关于在渲染之前隐藏 vue.js 模板的主要内容,如果未能解决你的问题,请参考以下文章

试图让 vue.js 根据 created() 中的方法有条件地渲染某些东西

如何利用Vue.js库中的v-show显示和隐藏元素

Vue 在隐藏元素之前渲染元素

Vue js数据绑定不起作用

在 Vue.js 中隐藏 div onclick

Vue.js 使用数据列表显示隐藏多个元素