Conditional v-once directive - vue.js

I'm working on an app that uses Vue. It is a kind of document editor that allows editing of content.
There's a filmstrip in a sidebar displaying the entirety of the document, and a viewport in the center displaying the current page/spread.
On large documents with 100+ pages, I'd like to throttle the number of updates allowed through to the filmstrip component as it gets a little laggy on resize and when the JS controlled layouts in pages all have to resize simultaneously when global fields are changed etc.
There's a data structure representing the document's content, which is rendered by Vue components in the viewport and the filmstrip.
I could maintain two data structures and only update the data structure used in the filmstrip 1000ms after the last user interaction.
However, it feels like there could be a better way.
Vue has a directive called v-once, which looks promising, however, I can't find out if that can be set conditionally.
If I could, then I could set a timeout on change, and clear it if a change occurs before the timeout ends, and then momentarily unset v-once, then on next tick, add it back on again so that rendering pauses.
If there's a way of doing this, I'd love to know.

Here Proposal: Allowing v-once to accept a boolean flag is very clear, you can't set v-once dynamically. Also there is an example of one way to combine v-if and v-once to achieve the result you want.
Excerpt from the link
v-once is used for static content. v-once tell the compiler don't add any responsive functionalities to save cpu time. Otherwise, if the content is responsive, no methods could be used to save this kind of cpu time.
Hope it helped

Related

Show SnackBars stacked instead of overlapping?

In my app there's a page where I am showing several snackbars depending on results from server.
There can be several triggered by the server's result. They are also triggered from different components, so I don't have a single controller that could render them where I want.
So, they all display at once and overlap each other. I linked the official Vuetify docs page because the problem is clearly visible there. Just click on two of the buttons in short enough succession.
Is there any way I could render them such that they would stack one above the other instead of all bottom-centering over each other?
I was thinking I'd need a way to tell them the component that would be their rendering parent. But I can't seem to find a way to do this. Slots don't seem to be much help with this either since I can't declare global ones.
Is there any way I can do this?

When is the virtual dom rendered?

I'm having a hard time understanding a few reasons of the Virtual-DOM based design.
I think I have grasped the main concept but there is still a few dark areas.
Here what i've understood : in a web application structure around VueJs for example, instead of directly manipulating the DOM, which would result in too muche re-layout/re-paint processes and would be time consuming, the dev manipulates a model of the dom, the virtual dom.
The Virtual DOM is a tree-like data structure and does not render directly.Any modification is not time consuming at all. The data of the Virtual Dom is then applied to the real dom.
My question here is on the then.
How to know when to apply the changes of the virtual dom on the real dom?
I think I've understood that a change in the dom is sometimes a "transitional state" change and that kind of change does not need to be rendered immediatly.
How to decide which change is a "real" change that need to be displayed or which change is a "transitionnal state" change that does not need to be displayed ?
Do you have an example of a "transitional state" change that does not need to be rendered?
If any change is applied, I can't see the performance earning of the virtual dom.
I sense there's something I've missed, but i can't put my finger on it. I thought one of you guys could help.

Vuejs directive masonry detect prepend to array and redraw properly

I am using the vue-masonry plugin which let me create a masonry grid easily.
I created a system of infinite loading where you scroll to the bottom of the page and it append new pictures to an array binded with the vue-masonry plugin.
The problem happen when I created a system of polling for the new pictures that were upoaded by other users. Those new pictures need to be at the top of the masonry grid.
The plugin use two Vue Directive masonry (parent) and masonryTile (element). masonryTile has a v-for which loop through the array binded with my Vue instance (which does all the heavy lifting, preloading, sanityzing, etc...).
Is there a way in the directives to know the differences between something being appended or prepended? And try to react differently (I know masonry has some append/prepend method) but in here and with this plugin, the items where already added (at the beginning so the prepend works with Vue) but there's no masonry interaction nor redraw (I tried to use the prototype to trigger the redraw this.$redrawVueMasonry();).
So I don't know what's next to do. Continue finding a way to differentiate a prepend from a append and trying to bind it to the respective masonry's methods ? Or another method that I didn't think of...
Thanks in advance for you help
Ps : I don't think my code is really relevant since It's more a way to optimize the plugin. If you want some specific part of my code anymay, tell me in the comment !
This probably comes a bit too late, this being a 10 month old question.
However vue-masonry is able to handle situations where items are spliced anywhere in the array. But to properly update the grid this.$redrawVueMasonry() should be called inside this.$nextTick() like this:
this.$nextTick(() => this.$redrawVueMasonry());
Hope this helps, if not the original poster, someone else.

Aurelia: router without losing state

Here is my problem:
I typically have a paginated datagrid with a lot of rows. I want to be able to edit the data for each row of course but I have 2 constraints on this:
I need the edition form to replace the content of the page (I don't want a popup, modal dialog or side panel)
I don't want to lose the state of the datagrid: maybe I navigated down 5 pages in the datagrid and I don't want to be reloaded on the first page. And actually, I'd rather not reload the data I already had (the edited data will be updated automatically by my persistence layer anyway).
Ideally, I would have liked to have some kind of subrouter but I'm not sure how it would fit the first requirement. Otherwise, I could have a component that would be hidden by default and positions itself on top of the datagrid view when necessary but that feels quite hacky and forces me to have everything in the same template. And I will have to handle a stack of these components if I have several different 'full-screen panel'...
Any idea on a correct way to implement this?
Thanks!
I tried different solutions to no avail unfortunately. I had a long discussion with #Kukks on gitter and we agreed that using subrouters and viewports might be a bit overkill for my use case.
I reverted to my original idea of using absolutely positioned components to hide the previous one in a kind of "deck layout". This is not ideal as I would have liked completely separated views and using components forces me to declare them in the main view but it works well and is very easy to implement...
So: not as clean as I would have liked but much easier to implement and less convoluted.
Consider using Router View Ports
http://aurelia.io/hub.html#/doc/article/aurelia/router/latest/router-configuration/9

(CSS) Change element's style upon window resize

I recently stumbled upon this microsite from the Obama campaign:
http://www.barackobama.com/anniversary
Among the many cool features of this site is its dynamic header -- when you resize your browser window smaller, the "OBAMA * BIDEN" logo up top automatically floats to left side of the header and its width gets changed to 36px (thereby "hiding" the "OBAMA BIDEN" text).
How did the developers of this page achieve this effect? Is this javascript/jquery driven, or purely a CSS trick?
Ideas?
This question covers the window.resize event. You can do whatever you need in its handler.
Another option is to use media queries that allow you to change applied CSS once the browser window dimension changes (this is what the site you refer to does. It combines the style class changes with animations (use Chrome Developer Tools to see which styles get applied to the logo in both big and small browser dimensions)).