VueJS2, how to call props in data - vuejs2

I created a component, I want to call the model value. If I do it the first way, but when I try to do it the second, I get this error.
[Vue warn]: Error in data(): "TypeError: Cannot read properties of undefined (reading 'value')"
The first way
The second way
I want to use second way because i want create own component vuetify date-picker and i want to pass date to him.
Unless it is possible to rewrite the first one in such a way that I can write the date in this way. Is there any way to "vm"? I am using this https://vuetifyjs.com/en/components/date-pickers/#formatting
Thank you for answering

Vue automatically binds the regular functions that are provided to its data or methods sections to the component instance. However, arrow functions can not be bound - the this keyword inside arrow functions refers to the closest outer context/scope. But since there is no such context for the data section - your this is undefined.
You should either use a regular function instead of arrow function when defining your data section - or you should leave the values in the arrow function undefined and assign the initial values inside the created hook.

You should use in arrow function like this.
props: ['value'],
data: vm => ({
props: vm.value
});

Related

Vue update computed property only when outcome changes

Consider the following simplification of a problem I have:
export default {
data () {
return {
i_change_alot: 0,
};
},
mounted() {
setInterval(() => {
this.i_change_alot = Math.random();
}, 10);
},
computed: {
someComputedValue() {
this.i_change_alot;
return 'a';
}
}
}
I created a property i_change_alot which is changed every 10 milliseconds to a random value. This means the property becomes extremely reactive and thus it will trigger the computed property.
By simply calling this.i_change_alot I trigger a dependency (for the purposes of example), however the outcome of the computed property never changes.
The end result is that the computed property someComputedValue updates every 10 ms and this triggers a view rerender as far as I am aware.
How can I make it so that someComputedValue is only rerendered when the value/outcome changes?
(The original problem is about showing reactive relative dates, e.g. "1 second ago", "2 seconds ago" and so on. However, after some time, this becomes 30 minutes ago, 31 minutes ago which means for a full minute the string representation has not changed, but it is still rerendered every 10 ms because of the dependent date property).
According to https://github.com/vuejs/vue/issues/11399 I could create a structure with a watcher but it looks so counterintuitive.
Why does Vue trigger the computed when the value is unchanged?
Because Vue will never know if the final result is changed or not until it makes the re-calculation. So the computed variable will be re-calculated every time its dependencies changed and there is no way to avoid it.
The common misunderstanding is Vue cache the computed variables by their value but actually, Vue cache the computed variables by their dependencies' state.
To avoid re-render too frequently
You can create a watcher (as you already know) or wrap your template that uses the computed value into a component.
Why wrap into another component help here?
Because Vue will convert your template to a render function. This function will be re-calculated every time its dependencies change. Sound familiar? Right, it works like a computed variable. The dependencies of a render function are all the variables that you use in the template. So, if you wrap your frequent change variable into a component, Vue will re-render that component only and avoid re-rendering your big component. It will have a big impact on your performance

Vue and Vue 3 access vue instance from DOM [duplicate]

Is there a reliable way to check if an object is a Vue.js component?
You can use instanceof, as following code:
var isVueComp = vuecomp instanceof Vue
If it isVueComp is true, it is a Vue.js componeny otherwise not.
You can also use vuecomp.prototype.constructor, which will return reference to the Object constructor function that created the instance object.
Check this fiddle.
Like Saurabh wrote, instanceof is probably the best way to be sure. However, in case you don't want to import Vue just for this purpose, you could use this._isVue.
The simplest way to check if a an object is a Vue component, as in 2020l, is probably the _isVue property of the component, which, in case of the given object being a Vue.js component, exists as key-value at the root of the object and returns true.
Const isVueComponent = [VUE_COMPONENT_OBJECT]._isVue

Vue: (Marvel API) Error in render: "TypeError: Cannot read property 'path' of undefined"

As mentioned, I'm using the Marvel API. At mounted() I use this action:
mounted() {
this.$store.dispatch("get/getCharacter", this.$route.params.id);
},
This uses axios to call for the character object, and sends that payload to a mutation, which updates the state of character: {}. I use a getter to call the state of the character to output in my page. Everything works, the image appears and if I interpolate the string to the page, that appears as it should. However, I'm still getting the typeError. I'm creating the img like this:
<img :src="`${character.thumbnail.path}/portrait_incredible.${character.thumbnail.extension}`
So, doing this {{ character.thumbnail.path }} outputs the correct 'path' string from the object. The image loads perfectly on my computer too, but not on my Oppo phone (I've uploaded it to Netlify to check). Strangely, my friends iPhone does load the images using the Netflify link.
What am I doing wrong, and how can I make this error go away?
Thanks for any help!
I know this question is old, but I would like to give my solution since no one has answered this question. So it may help someone in future.
You can use the optional chaining operator to solve this,
The ?. operator is like the . chaining operator, except that instead of causing an error if a reference is nullish (null or undefined), the expression short-circuits with a return value of undefined. When used with function calls, it returns undefined if the given function does not exist.
See Optional chaining (?.)
character.thumbnail?.path
character.thumbnail?.extension

Why next function in beforeRouteEnter happends after the component is loaded?

In beforeRouteEnter event I call to promise/http which take a second to get some data.
After I get the data I pass to the result prop in the component. (using next function).
Also I have a getter that take the value from the prop.
The problem is vue is invoke the getter before it set the value (by next function), so I got undefined.
How can I solve this error?
Here is an code example of the problem
Problem is that when you use next(vm ...) you work with context of page component where is your #Prop defined. You can't modify #Prop value this way. There is some hacks how you can do that but is it really necessary to use #Prop in this case? Why you simply don't use basic variable in page component?
If you replace
#Prop() result
with:
result: Object = {};
everything works great.
If you really need prop here maybe you can just copy prop value to some variable (use watch if you need detect changes) but i don't see any purpose for prop here.
Hope this answer helps you :)

VueJS: Why Trigger 'Input' Event Within 'Input' Event Handler?

I'm learning VueJS. I'm figuring out their currency validation example code.
Vue.component('currency-input', {
template: `
<span>
$
<input
ref="input"
v-bind:value="value"
v-on:input="updateValue($event.target.value)">
</span>
`,
props: ['value'],
methods: {
// Instead of updating the value directly, this
// method is used to format and place constraints
// on the input's value
updateValue: function (value) {
var formattedValue = value
// Remove whitespace on either side
.trim()
// Shorten to 2 decimal places
.slice(
0,
value.indexOf('.') === -1
? value.length
: value.indexOf('.') + 3
)
// If the value was not already normalized,
// manually override it to conform
if (formattedValue !== value) {
this.$refs.input.value = formattedValue
}
// Emit the number value through the input event
this.$emit('input', Number(formattedValue))
}
}
})
The $emit call at the bottom of the updateValue function, triggers an input event.
When I comment it out, the real time currency validation no longer works. So I realize it has a purpose.
But why trigger an input event inside an input event?
You'd think the input event would fire again, causing the updateValue handler to fire again, causing a stack overflow due to recursive calls.
I understand VueJS's much simpler $emit example code. It's just like Jquery's trigger function.
vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
// -> "hi"
But in the currency validation example, I do not understand why $emit is used the way it's used, and why it works the way it works.
Can somebody explain?
The Emit call here is to allow you to hook into the event in parent contexts. The Input event is also used by the v-model directive to handle two way binding with components.
v-model='model' is essentially v-bind:value='model' v-on:input='model = $event.target.value' with some added bits to make it play nice. When you remove the this.$emit('input', Number(formattedValue)) You're removing the mechanism that updates the value outside the component.
EDIT: #Jay careful what you wish for sometimes
All elements in HTML have a series of native handlers for the common events; resize, load, unload, etc. These handle what to do when the page changes it's rendering and can be disabled or added onto, since the introduction of JavaScript browsers have used an event pump system that allows multiple functions to be attached to any event which run in sequence when the event is raised. An example being how you can have 3 functions run on resize to handle edge cases such as minimum/maximum size, screen orientation etc.
Form elements generally implement their own base event functions: keydown, keyup, mousedown, mouseup. These base functions invoke events to make our lives easier as developers, these being: input, blur, focus. Some have specialized events as in select elements implementing change, form tags implementing submit.
Input tags on focus capture keyboard input and display the text input cursor to indicate that it's ready to receive input. It adds in handlers for the tab keycode which finds the next available input and shifts focus to that element. The event pump style function system is great here as it allows you to bind to focus and do things like change the background color or border when the input is focused without having to implement the code for capturing input or displaying the cursor yourself.
Input tags also raise the input event when you type in them indicating that the input has changed, telling the browser to change the value and update the display so that the functionality expected by the user is consistent.
In the currency-input example we are adding the updateValue function to work with the native function and process the input value of the event, in the updateValue function we modify the string representation of the value and need someplace to put it. You could simply add a data property to hold the value and bind the input's value property to the data property allowing the currency-input to internally handle the display of the result but that would lock the value behind a private accessor and you would be unable to modify or retrieve the value of the resulting currency formatted value.
Using this.$emit('input', Number(formattedValue)) the updateValue function is acting similar to the native input tag by raising an event that can be captured by the parent context and worked with. You can store it in a value, use it as the basis for a function, or even ignore it completely though that may not help much. This allows you to keep track of the value of the input and modify it as needed or send it to the server, display it, etc.
It also ties into a few directives most pertinently v-model which is syntactic sugar to allow for a value property binding and an input event binding to a data property inside the current context. By providing a value prop and emitting an input event a custom element can act similar to a native form element in the systems of a Vue application. An extremely attractive feature when you want to package and distribute or reuse components.
It's a lot nicer to go:
...
<currency-input v-model='dollarValue'></currency-input>
<input v-model='dollarValue'>
...
Than to have to add in value and input bindings everywhere ergo:
...
<currency-input v-bind:value='dollarValue' v-on:input='updateDollarValue($event.target.value)'></currency-input>
<input v-bind:value='dollarValue' v-on:input='updateDollarValue($event.target.value)'>
...
Now that my weird rambling is done, I hope this helped with understanding some of the patterns and reasoning behind the currency-input example.