Vue Router Data persistance - vuejs2

I have an app that requires a persistent connection (uses WEBRtc) The VUEX store can change based on a data transfer.
In my routes I have (for simplicity sake) 2 navs in my router view
<b-dropdown-item
href="#"
#click="$router.push({name: 'marriagesection', params: {id:Math.floor(Math.random() *10 )}})"
>Previous Marriages</b-dropdown-item>
<b-dropdown-item
href="#"
#click="$router.push('/applic/children',s,e)"
>Children / Grandchildren</b-dropdown-item>
When I navigate between them, I loose the data.
I have tried putting a :key on the router-view, explored beforeEnter, and created a mutation that I subscribe to to get the info initialized again - this works if I console log it, but it doe not update the DOM. I have used :keys in the do after getting the info and still doesn't work. I have more than 3 days on this problem and there is a severe lack of documentation on this issue.
I have MUCH to much to keep all of the information in a store, and the DOM has to respond to changes in other views, making use of VUEX almost impossible, or so large it almost would become useless.
Please help

Related

Target and manipulate single DOM element in vue

Somehow I still can't wrap my head around some core vue concepts.
I have made some simple webpage using phalcon. Created it so, that it would work without JS and now is the time to add some bells and whistles - ajax queries and the like, for the user experience to be better.
I wanted to do everything using vue, to see how it all adds up. But after hours of googling I still can't find solution for the simplest of tasks.
Say: I want to get a text paragraph in a series of <li>-s and change it somewhat. Maybe make excerpt of it and add 'see more' button behind it. Now, in jQuery I would just iterate with each() and perform the tasks. With vue targeting set of DOM elements is much harder for me, probably because of whole paradigm being "the other way round".
I know I could iterate with v-for, but these elements are already in the DOM, taken from the database and templated with volt. I had even this wild idea of creating .js files from phalcon, but it would completely negate my strategy of making functional webpage first and then enhance it progressively.
Frankly speaking I feel like I'm overcomplicating for the sake of it, right now. Is vue even fit for a project like this, or is it exclusively a tool to build app from the ground up?
Vue's templating is client-side, which means if you are delivering an already templated html page (by your backend) there is little vue can still do for you. Vue needs data, not DOM elements to build its viewmodels.
This becomes pretty obvious when building a single page application for example, which would be rendered only on the client-side. You'd simply load the data asynchronously from a backend api (REST for example) and then do all the rendering on the client.
As far as I understand your usecase you want to mix client and server side rendering, rendering most of the non-interactable content using your backend's templating engine and adding some interactivity using vue. In this case you'll need to add some vue components (with their own rendering logic) to your backend template and pass data to that component using vue's data-binding.
Here's an example:
...
<div id="app">
<my-vue-list :products="{% products %}"></my-vue-list>
</div>
...
And in your JS:
var app = new Vue({
el: '#app',
data: {
components: {MyVueList} // You will have to register all the components you want to use here
}
})
Vue provides the ref attribute for registering a reference to a dom element or child component:
// accessible via this.$refs.foo
<li ref="foo">...</li>
Do note, however, that refs are not reactive, as stated in the docs:
$refs is also non-reactive, therefore you should not attempt to use it in templates for data-binding.

passing data between components with vue-router

There a re quite a few question with kind of a similar title to mine, but that is where my problem lies. Let's take a very common case where i'm building a recipe book.
i'm looping over my recipes and creating a link to the Recipe.vue component:
<router-link v-for="recipe in recipes" :to="{path: `/recipe/${recipe.title}`">
<a>{{recipe.id}}</a>
</router-link>
now from what i understand there are few solutions:
1. setting props:true and pass a prop:
<router-link v-for="recipe in recipes" :to="{name: 'Recipe', params: {recipe}}">
<a>{{recipe.title}}</a>
</router-link>
set Recipe as child component and pass the data as a regur parent=>child data transfer
use Vuex and state management to then "withdraw" the data from the store in the Recipe component
pass id to the Recipe component and then when its mounted() execute an http request to get the data of the specific item.
I'm finding it hard to understand what is considered best practice here and what should i choose for my production env.
the voice inside me says that number 3 - state management is an overkill and #4 is an unnecessary api call since i already have the data i need.
Any advice on which method should i use in the basic case of: first component is a list of recipes and then navigate from it to a component with single purpose of displaying the recipe data?

Trouble with routing Vue.js 2 and browser history

Faced such a problem - I send data to the props of the /router-link/ tag, when I click on the link, I go to the article, it gets the data, everything works. Well, if you press the "back" button in the browser and then "forward" there will be no articles, there will be empty fields without data. How can this be avoided?
This is link to the article
<h3 class="database-article__title">
<router-link
:to="{name : 'article',params: {
id: item.id ,
type:item.type ,
name: item.name,
text: item.text,
author: item.author,
isFavorite: item.isFavorite
}}"> {{item.name}} </router-link>
</h3>
Little part of article-template.vue
<div class="content-type marketing">
{{$route.params.type}}
</div>
<h3 class="database-article__title">
{{$route.params.name}}
</h3>
<div class="database-article__text">
{{$route.params.text}}
</div>
Once again, the data transfer is good, when you click on the link, everything is displayed. The problem is that when clicking on the buttons in the browser "back" and "forward" - the browser history is not saved.
Does anyone know the solution to the problem, or where i can read how to solve it?
Thanks!
My guess is that your article route does not specify any of those params in its path. When you click the link, vue-router will remember the params object you specified in the <router-link> and will be accessible through $route.params in the article component.
However, when you click the browser back then forward buttons, the transition to the article route did not occur by clicking the <router-link> like it did the first time, and since those params were not included in the route's path, $route.params will be empty.
I'm guessing you're just trying to pass data from one route to another. If you want it to persist across history state changes (i.e. browser back/forward), then either:
The data needs to be included in the URL, either as params (e.g. /article/:id/:type etc, this needs to be specified upfront in the route's path) or in the query string (e.g. /article?id=1&type=foo). This isn't ideal for this situation.
(Recommended) Store the item object in such a way that it can be accessed by any route. Vuex is one way, but this may be overkill.
Realistically your URLs should only need to have the article's ID in it, like this /article/1. All the other stuff like type/name/etc don't belong in the URL. From the ID you should be able to fetch the full article object either from a REST API (XHR request), or obtain it from some in-memory data store abstraction (Vuex or anything else really).

what is the right way or the vuejs way to data bind the entire page?

Coming from the knockoutJs background. If you don't specific the binding to an element. You can use the model to cover the whole page of elements. For example, i can make a div visible if a click event happened. I'm learning VueJs and from the documentation. I see the vue instance required you to speicif an element with el.
like this:
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
what if my button is not in the same div as the '#app' div. How do i communicate between two vue instance or can I use one vue instance to cover more than one element. what's the vuejs way?
It's very common to bind to the first element inside <body>. Vue won't let you bind to body, because there are all sorts of other things that put their event listeners on it.
If you do that, Vue is managing your whole page, and away you go. The docs cover the case where you have more than one Vue instance on a page, but I haven't come across this outside the docs, and I can't think of a good reason off the top of my head. More commonly, you will be constantly chopping bits out of your root Vue instance and refactoring them into "child" components. This is how you keep file sizes manageable and structure your app.
This is where a lot of folk needlessly complicate things, by over-using props to pass stuff to components. When you start refactoring into components, you will have a much easier time if you keep all your state in a store, outside vue, then have your components talk directly to your store. (put the store in the data element of all components). This pattern (MVVM) is fabulous, because many elements of state will end up having more than one representation on screen, and having a "single source of truth", normalized, with minimal relationships between items in the store, radically reduces the complexity and the amount of code for most common purposes. It lets you structure your app state independently of your DOM.
So, to answer your question, Vue instances (and vue components), don't need to (and shouldn't) talk much to each other. When they do need to (third party components and repeated components), you have props and events, refs and method calls (state outside the store), and the $parent and $root properties (usage frowned on!). You can also create an event bus. This page is a really good summary of the options.
Should your store be Flux/Redux? Vuex is the official implementation of the flux/redux pattern for vue. The common joke goes: when you realize you need it, it's too late. If you do decide to leave Vuex for now, don't just put state in Vue components. Use a plain javascript object in window scope. The right way is easier than the wrong way, and when you do transition to Vuex, your job will be much simpler. Your downstream references might be alright as they are.
Good luck. Enjoy the ride.
You usually put the main Vue instance on the first tag inside the body, then build the rest of your site within it. Everything directly inside that instance (not in a nested component) will have access to the same data.
You can then do this in your HTML:
<body>
<div id="#app">
<p v-if="showMessage">{{message}}</p>
<button v-on:click="showMessage = !showMessage"></button>
</div>
</body>
And set your data to something like this:
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
showMessage: true
}
})
If you want to pass data between components later on you'll have to look up how to emit events, use props, or possibly use Vuex if you got Vue running with the Vue-CLI (which I highly recommend).
If you want to reach tags (such as head tags) outside of the main Vue instance, then there are tools for that. For example you could try: https://github.com/ktquez/vue-head
I haven't tested it thought.

How to use keep-alive in vuejs?

Basically, I want to keep alive 2 components in router-view and it works, however, I don't know if I am doing it correctly.
<keep-alive include="users, data">
<router-view></router-view>
</keep-alive>
users and data are route names. Is this correct way to do it. Are there any disadvantages of keep-alive?
The only disadvantage is that these components are kept in memory and therefore their state is saved and not reset.
You also lose lifecycle hooks like created, mounted, etc. since the component is not being rebuilt from scratch anymore. You can replace those lifecycle hooks with hooks that are specific to keep-alive components. For example:
https://v2.vuejs.org/v2/api/#activated
Whether keep-alive is a disadvantage or advantage is entirely up to your scenario. If you want to keep the state because you want to switch fast and often between the keep-alive components, it could be an advantage. If you really rely on a clean state through components being built and destroyed, it could be a disadvantage.
1. We can achieve it by using
<keep-alive>
// Render component inside
</keep-alive>
special tag which has provided by vueJs.
2. use life cycle hooks:
a. activated()
b. deactivated()