Expressions vs computed properties in templates in Vue.js - vue.js

What is better to use in templates: expressions or computed properties?
Ex:
<span :class="'static_part' + dynamic_part"></span>
...
data: {
dynamic_part: 'xxx',
}
or
<span :class="span_class"></span>
...
data: {
dynamic_part: 'xxx',
},
computed: {
span_class() {
return 'static_part' + dynamic_part;
}
}
1-st way is smaller and easier to understand. But what about performance?

According to official docs
In-template expressions are very convenient, but they are meant for simple operations. Putting too much logic in your templates can make them bloated and hard to maintain
and
Instead of a computed property, we can define the same function as a method. For the end result, the two approaches are indeed exactly the same. However, the difference is that computed properties are cached based on their reactive dependencies
I see that using computed property could also separate the logic from the content and help other who will read your code that this properties are calculated and based on other ones

Related

Vue: Forcing child component to react to changes in its prop (which is a dictionary)

I am currently generating a table which lists problems encountered during the selected test using a component generated with this code:
<tr is="entry" v-for="problem in problems" :key="problem.id" v-bind:foo="problem"></tr>
Each problem corresponds to an item whose relevant information is contained within the problem dictionary and referenced in the first few columns of the table. Since the same item can have multiple problems, the same item can appear in multiple rows of the table. Now, each row features some buttons which allow you to modify the underlying item so as to fix the problems.
Whenever I modify one of those underlying items I need to modify it in all the rows, which i do by calling a function in the parent component, but modifying the data inside of the dictionary does not seem to trigger any of my watches or computes inside of the child component, which currently looks something like this:
Vue.component('entry', {
props: ['foo'],
data: function(){
//does some computations
return data
},
watch:{
foo: function(){
this.recompute_entry()
},
},
methods:{
//various methods, including:
recompute_entry: function(){
//updates the data according to changes brought to the entry
},
},
});
I have attempted to include a different prop which i could bind to an entry in a list in my parent component but, besides being pretty clunky, that didn't end up working either, which makes me think I might've gotten something wrong with my component.
Ultimately, I have relied on the fact that v-for iterates through my list in an orderly fashion, which combined with the fact that I generate no other children in my parent component means that a child component would have the same index in my component's children array as it would in my problems array. Therefore I can use this:
this.$children[problem_index].recompute_entry();
Which kind of feels hack-ish and unreliable, but actually works, for once. Is there no alternative safer method to recalculate my child components based on changes made to their props? I really feel there has to be.
I probably would need to see the exact implementation but it sounds like you need to clone your dictionary to trigger the prop change, ie:
let newProblem = Object.assign({}, this.problem);
// change any nested property
newProblem.some.value = 1
// assign back the cloned and modified dictionary
this.problem = newProblem

VueJS define computed logic in two components vs. in $store

In my vue app i have the following computed property in two different components:
normalizeName() {
website = this.form.website_id;
let res = '', new_val = '';
if (this.websites.find(obj => obj.website_id === website)) {
this.form.name = '';
res = this.websites.find(obj => obj.website_id === website);
new_val = res.acronym + ' - ';
this.form.name = new_val;
return new_val;
}
}
Now, i have a state mgmt defined using the $store but the question is:
in terms of best practice and performance, should i define normalizeName() in the $store and use its logic from there or should i implement the exact same logic in two different components?
Realistically there will be little performance difference either way. In terms of your code duplication vs $store abstraction problem - personally I find that a small amount of duplication lends to better readability and maintainability. When compared to pushing that function to somewhere else.
This article explains why that can be the case much better than I could.
You need to consider whether it makes sense for a $store to have a function for normalising a name. Also if more than just these two component use the store - that function probably belongs in the components themselves rather than in the store. To me that normalisation functionality would look out of place in a store.
Perhaps if you thought that function was going to be needed to be implemented a 3rd time, then you should find a way to move it elsewhere for the sake of consistency/convenience.

sorting list of object by property in VueJS

I have just started to learn VueJS 2 and the more questions I have the harder it becomes.
The idea is that I have a sample problem with an array of objects, where I want to sort the array by "votes" property, which can be dynamically updated for each separate element. I want to sort my list by votes dynamically. Thus the question is how can I do that without doing weird code.
In angular you will do something like
for candidate in candidates | orderBy: 'votes'
but in here I could of though only of something like
v-for="(value, index, key) in sorted_candidates"
where in .js I'll have
computed : {
sorted_candidates() {
return this.candidates.sort((a, b) => { return b.votes - a.votes;});
}
}
So my question would be if there is a more elegant way to solve this problem?
Note: I am sorting on object property.
This is already a simple enough solution, in Vue1 you can still use OrderBy but in Vue2 they suggest you opt for the current solution you currently have, you can reference on here

Is it possible to use custom mappers in cytoscape.js 2.0?

I can see that there is already support for direct mapping from a data attribute or a predefined linear mapping with mapData, is there a best-practice for using custom mapping functions?
http://cytoscape.github.io/cytoscape.js/#style/mappers
i.e. doing something like this:
...
style: cytoscape.stylesheet()
.selector('node')
.css({
'width': function() { return nonLinearFunction(this.data("attr")); }
})
...
What kind of function are you looking for? For performance reasons, it's important that the stored style values are not truly "dynamic": Mapper values are cached, and updated only on changes to data, for example.
It would be easier to add the kind of function you're looking for if it's something like a logarithmic function, some type of mathematical function, or similar. The main thing to keep in mind is that a callback function for "custom mappers" is not performant.

DoJo get/set overriding possible

I don't know much about Dojo but is the following possible:
I assume it has a getter/setter for access to its datastore, is it possible to override this code.
For example:
In the dojo store i have 'Name: #Joe'
is it possible to check the get to:
get()
if name.firstChar = '#' then just
return 'Joe'
and:
set(var)
if name.firstChar = '#' then set to #+var
Is this sort of thing possible? or will i needs a wrapper API?
You can get the best doc from http://docs.dojocampus.org/dojo/data/api/Read
First, for getting the data from a store you have to use
getValue(item, "key")
I believe you can solve the problem the following way. It assumes you are using a ItemFileReadStore, you may use another one, just replace it.
dojo.require("dojo.data.ItemFileReadStore");
dojo.declare("MyStore", dojo.data.ItemFileReadStore, {
getValue:function(item, key){
var ret = this.inherited(arguments);
return ret.charAt(0)=="#" ? ret.substr(1) : ret;
}
})
And then just use "MyStore" instead of ItemFileReadStore (or whatever store you are using).
I just hacked out the code, didn't try it, but it should very well show the solution.
Good luck
Yes, I believe so. I think what you'll want to do is read this here and determine how, if it will work:
The following statement leads me to believe the answer is yes:
...
By requiring access to go through
store functions, the store can hide
the internal structure of the item.
This allows the item to remain in a
format that is most efficient for
representing the datatype for a
particular situation. For example, the
items could be XML DOM elements and,
in that case, the store would access
the values using DOM APIs when
store.getValue() is called.
As a second example, the item might be
a simple JavaScript structure and the
store can then access the values
through normal JavaScript accessor
notation. From the end-users
perspective, the access is exactly the
same: store.getValue(item,
"attribute"). This provides a
consistent look and feel to accessing
a variety of data types. This also
provides efficiency in accessing items
by reducing item load times by
avoiding conversion to a defined
internal format that all stores would
have to use.
...
Going through store accessor function
provides the possibility of
lazy-loading in of values as well as
lazy reference resolution.
http://www.dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/what-dojo-data/dojo-data-design
I'd love to give you an example but I think it's going to take a lot more investigation.