How to distinguish between component instances in Vue Devtools - vue.js

When I look at my application state in Vue's devtools chrome extension, I can see multiple instances of the same component in the tree view. However, there is no way to distinguish one instance from another. For example, in the screenshot below there are three <Todo> components. Imagine instead there are 30. How do I attach some kind of instance name or id to my components? It seems silly to have to click through 30 components to find the one I need.

I had the same idea also a couple of months ago.
So I gave it a try.
My PR has been submitted: https://github.com/vuejs/vue-devtools/pull/331
It's probably a bit early to rely on my solution since the core team could still reject the PR or request other naming conventions.
Until then you can build my proposal version yourself from my repo:
https://github.com/nerdyglasses/vue-devtools/tree/verbose-component-tree
Is that helping you?
Best, Christian

You can use the ':key' attribute. And you even HAVE TO use it if your component depends on a v-for loop.
here you can see the keys

Related

Is there a way to store a reference to a specific component within the DOM?

The problem:
I am currently working on a file tree, more specifically on a "Selected Folder" functionality. I'm doing this to have a specific target for creating new files and folders, other that the root folder. (I'm using Vue within Electron, but this is not really relevant to the question)
Selection happens on click. Due to the nature of file trees, I use recursive components (and this limits my 'easy' access to some components).
While achieving this on the back-end is trivial, my exact problem is that while marking the selected folder with, say a different background color or bold text (by binding an id or class that has some corresponding style on my stylesheet), I need to unmark the previously selected directory.
So, how do I gain access to an indirect (due to the recursive components) child component?
What I've tried, and looked into:
Now, I know that within JS you can't store pointers or references in variables (otherwise this would've been easily achieved by storing a reference to the previous DOM element).
I have some solutions up my sleeve, but they're really tedious and not very straightforward. Previously, I had to re-render (by re-reading) specific sub-directories, based on file system updates. I achieved this partial re-rendering by propagating child function calls from the root directory until I reached the directory that needed to be re-rendered. I had to do this since the FS watcher was created on the root component.
Similarly, I could do this with the un-marking task. When I select the new folder, I start by propagating child function calls until I reach the previously selected folder, and un-mark it by un-binding the style id. Having done this previously, I know it's not a pleasant method.
Since I can get the click event target, I wondered if I could somehow store any kind of reference to the previously 'selected' DOM element and just use that reference later when I need to 'deselect' it.
Here's what my folder component looks like. I tried giving self-explanatory names to the properties, but if there's any confusion, I'll answer any question.
<folder-comp
#openFile="openFile"
v-for="folder of folders"
:key="`folder-${folder.shortFolderName}`"
:folder-name="folder.shortFolderName"
:ref="folder.shortFolderName"
:full-folder-path="folder.fullFolderPath"
:local-directory="recursiveScanDir"
:indentation-level="indentationLevel + 1">
</folder-comp>
The propagation method I used was necessary previously since all I had was an event File System path, unrelated to my Vue structures, and so I needed to somehow translate traversing that path. Here, though, everything happens only within the Vue environment, so I thought there would be some sort of way to deal with this easily.
EDIT: Well, as it happened with me in the past, just writing about the problem itself on stackoverflow helped me reach a solution.
I have a Global Event Bus set up on my Vue project, so I can bind an event listener on the currently selected folder. Once another folder is clicked (thus selected), it emits an event in the Global Event Bus, triggering the previously selected folder. This is followed by the un-marking and the unbinding of the event listener.
This is only one solution though, so the question still stands. Is this a good solution? Are there any drawbacks to this approach? Is there a better solution?
Instead of a global event bus, you can also use state management such as Vuex. When you change folders, you simply dispatch an action. This uses an command pattern, as opposed the the mentioned listener pattern. You have the choice to make this action asynchronous or synchronous as well.
There are several ways to register your listeners/watchers, from within components, or outside of them.
Using this architecture will allow you to easily add undo/redo capabilities, and also be able to navigate back and forth through your history of mutations.
You also gain the integrated debug features provided by the Vue tools in your browser.
In fact, Vuex was built exactly for situations like this, when components need to communicate with each other but the parent/child prop/emit/inject mechanisms start to become tedious and and fall apart.
There is a high probability that once you starting using Vuex, you will never look back.

Vue.js add attribute from mixin

I'm working on a rather complex and big project. Our QA team decided they want unique id's to do automated testing. Since our developers are rather lazy (we are developers, you know?), we are trying to inject these id's automatically.
I've tried to create a mixin that tries to add an attribute on mounted.
mounted() {
this.$el.setAttribute('data-test-id', 'a-random-id-01');
}
But this fails all the time because $el is not always available right away. Does anyone have any insight how we could do this?
Find your question from google :)
this.$el.dataset.testId = 'a-random-id-01'

How to understand the vuejs lifecycle better

I am trying to better understand Vuejs lifecycles. The documentation is short and I guess assumes most people are familiar with the lifecycle concept.
However, I've only been using created(){} as it suits my need to initialize a function/data (to put it vaguely) when the "page is loaded".
But I am sure every lifecycle hook has its own distinct feature or purpose. So, I am hoping someone can provide a better intro/example of when each hook can be used from the context of page load to page finish.
To put it simply. When you request a web page, there are two observable steps
1: page is loading
2: page finished loading.
My question is, when do the created, mounted, updated and destroyed hooks take place within those two stages? I didn't mention the before/after hooks as they are obvious by their meaning.
Lifecycle hooks relate to a Vue instance, not to a page load. Components are Vue instances, as is the main Vue instance that is typically called on the whole page.
The diagram gives a pretty good rundown of where each hook sits in relation to what is going on on the instance. In simple terms, created happens before you have DOM to work with, and all the others happen after.

is there any way to prevent a view from being unbound on deactivation?

I find, even when assigning the decorator #singleton(false) to the view-model, that while the view-model does then persist as a singleton across activation/deactivation, the bindings and components, etc do not.
(I assume this is because they are stored in a container that is disposed on deactivation.)
The result is that upon every deactivation/activation of a view with a singleton view-model, the view is un-bound and then re-bound.
Is it possible to cause the bindings to persist across deactivation/activation?
This one stumped me for a good while. It also confused me as to why implementing it was not a higher priority for the Aurelia Team.
This takes a fair amount of code to get working. I have put the code in a Gist here: https://gist.github.com/Vaccano/1e862b9318f4f0a9a8e1176ff4fb727e
All the files are new ones except the last, which is a modification to your main.ts file. Also, all my code is in Typescript. If you are using Javascript you will have to translate it.
The basic idea behind it is that you cache the view and the view model. And your replace the router with a caching router. So when the user navigates back to your page, it checks first to see if there is a view/view model already created and uses that instead of making a new one.
NOTE: This is not "component" level code. That means I have tested that this works for the scenario that I use it for.
I got my start for making this change here: https://github.com/aurelia/router/issues/173 There is another user (Scapal) made something that works for him and posted it there. If what I am posting does not work for you, his may help you out.
i'm also interested in an answer to this.
maybe i'm now making a complete fool out of me but why not use aurelia-history navigate(..) command?

Access closure property names in the content block at runtime

I want to evaluate my content blocks before running my test suite but the closures' property names is in bytecode already. I'm ooking for the cleanest solution (compared with parsing source manually).
Already tried solution outlined in this post (and I'd still wind up doing some RegEx/parsing) but could only get it to work via script execution engine. It failed in IDE and GroovyConsole. Rather than embedding a Groovy script in project's code, I thought I'd try using Geb's native classes.
Is building on the suggestion about extending Geb Navigators here viable for Geb's PageContentSupport class whose contentTemplates contain a LinkedHashMap of exactly what I need? If yes, would someone provide guidance? If no, any suggestions?
It is currently not possible to get hold of all content elements for a given page/module. Feel free to create an issue for this in Geb's bug tracker, but remember that all that Geb can provide is either a list of content element names or a map from these names to closures that create these elements.
Having that information isn't a generic solution to your problem because it's possible for content elements to take parameters and there are situations where your content elements will be available on the page only after some other actions are performed (for example you have to click on button to reveal a section of a page that uses ajax to retrieve it's content). So I'm afraid that simply going over all elements and checking if they don't throw any errors will not cut it.
I'm still struggling to see what would "evaluating" all content elements prior to running the suite buy you. Are you after verifying that your content elements still work to get a faster feedback than running the whole suite? I'm pretty sure that you won't be able to fully automate detection of content definitions that don't work anymore. In my view it will be more effort than it's worth.