Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reloading page is flashing content on slot in vue component

Is there any way to avoid this flicker on page refresh, it's a modal component which takes HTML as slot, but when I refresh the page it flashes. My app is not using a router so it's not complete SPA.

see the gif.

enter image description here

Here is the code.

.body {
			padding: 2em;
			text-align: center;
			display: table-cell;
		  	vertical-align: middle;
		}

		.modal-mask {
		  position: absolute;
		  z-index: 9998;
		  top: 0;
		  left: 0;
		  width: 100%;
		  height: 100%;
		  background-color: rgba(0, 0, 0, .5);
		  display: table;
		  transition: opacity .3s ease;
		}

		.modal-wrapper {
		  display: table-cell;
		  vertical-align: middle;
		}

		.modal-container {
		  width: 70%;
		  margin: 1em auto;
		  padding: 20px 30px;
		  background-color: #fff;
		  border-radius: 2px;
		  box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
		  transition: all .3s ease;
		  font-family: Helvetica, Arial, sans-serif;
		}

		.modal-header h3 {
		  margin-top: 0;
		  color: #42b983;
		}

		.modal-body {
		  margin: 20px 0;
		}

		.modal-default-button {
		  float: right;
		}


		/*
		 * The following styles are auto-applied to elements with
		 * transition="modal" when their visibility is toggled
		 * by Vue.js.
		 *
		 * You can easily play with the modal transition by editing
		 * these styles.
		 */

		.modal-enter {
		  opacity: 0;
		}

		.modal-leave-active {
		  opacity: 0;
		}

		.modal-enter .modal-container,
		.modal-leave-active .modal-container {
		  -webkit-transform: scale(1.1);
		  transform: scale(1.1);
		}
<!-- template for the modal component -->
<script type="text/x-template" id="modal-template">
  <transition name="modal">
    <div class="modal-mask">
      <div class="modal-wrapper">
        <div class="modal-container">

          <div class="modal-header">
            <slot name="header">
              default header
            </slot>
            <button class="modal-default-button" @click="$emit('close')">Close</button>
          </div>

          <div class="modal-body">
            <slot name="body">
              default body
            </slot>
          </div>

          <div class="modal-footer">
            <slot name="footer">
              default footer
              <button class="modal-default-button" @click="$emit('close')">
                OK
              </button>
            </slot>
          </div>
        </div>
      </div>
    </div>
  </transition>
</script>

<!-- app -->
<div id="app">
  <button id="show-modal" @click="showModal = true">Show Modal</button>
  <!-- use the modal component, pass in the prop -->
  <modal v-if="showModal" @close="showModal = false">
    <!--
      you can use custom content here to overwrite
      default content
    -->
    <div slot="body">
      <div class="modal-body">
        <h4>Text in a modal</h4>
        <p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula.</p>
        <h4>Popover in a modal</h4>
        <p>This <a href="#" class="btn btn-default popover-test" role="button" title="" data-content="And here's some amazing content. It's very engaging. right?" data-original-title="A Title">button</a> should trigger a popover on click.</p>
        <h4>Tooltips in a modal</h4>
        <p><a href="#" class="tooltip-test" title="" data-original-title="Tooltip">This link</a> and <a href="#" class="tooltip-test" title="" data-original-title="Tooltip">that link</a> should have tooltips on hover.</p>
        <hr>
        <h4>Overflowing text to show scroll behavior</h4>
        <p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
        <p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
        <p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
        <p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
        <p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
        <p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
        <p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
        <p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
        <p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p>
      </div>
    </div>
    <h3 slot="header">custom header</h3>
  </modal>
</div>

<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>

<script>
	// register modal component
	Vue.component('modal', {
	  template: '#modal-template'
	})

	// start app
	new Vue({
	  el: '#app',
	  data: {
	    showModal: false
	  }
	})
</script>
like image 726
Saqueib Avatar asked Jan 11 '17 06:01

Saqueib


1 Answers

Most usually this is due to the fact that your vue.js requires to load until it is able to do what you want.

You basically load html content which is by default visible.

After the html you load vue and vue will hide your content due to your v-if or v-show statements. The most simple way to ensure something like this is not happening is to use the v-cloak directive plus a little bit of css.

Place it at a very high level as given in this example

<div id="app"><!-- vue mounted at this div -->
    <div v-cloak>

        <!-- your actual code / content -->

    </div>
</div>

And the css

[v-cloak] { display: none; }

The v-cloak property will be removed as soon as vue is done with loading. Therefore everything is hidden until vue is done with loading. This should ensure your content is not flashing.

like image 199
Frnak Avatar answered Oct 19 '22 23:10

Frnak