Difference between the created and mounted events in Vue.js - javascript

Vue.js documentation describes the created and mounted events as follows:
created
Called synchronously after the instance is created. At this
stage, the instance has finished processing the options which means
the following have been set up: data observation, computed properties,
methods, watch/event callbacks. However, the mounting phase has not
been started, and the $el property will not be available yet.
mounted
Called after the instance has just been mounted where el is replaced
by the newly created vm.$el. If the root instance is mounted to an
in-document element, vm.$el will also be in-document when mounted is
called.
This hook is not called during server-side rendering.
I understand the theory, but I have 2 questions regarding practice:
Is there any case where created would be used over mounted?
What can I use the created event for, in real-life (real-code)
situation?

created() : since the processing of the options is finished you have access to reactive data properties and change them if you want. At this stage DOM has not been mounted or added yet. So you cannot do any DOM manipulation here
mounted(): called after the DOM has been mounted or rendered. Here you have access to the DOM elements and DOM manipulation can be performed for example get the innerHTML:
console.log(element.innerHTML)
So your questions:
Is there any case where created would be used over mounted?
Created is generally used for fetching data from backend API and setting it to data properties. But in SSR mounted() hook is not present you need to perform tasks like fetching data in created hook only
What can I use the created event for, in real-life (real-code) situation?
For fetching any initial required data to be rendered(like JSON) from external API and assigning it to any reactive data properties
data:{
myJson : null,
errors: null
},
created(){
//pseudo code
database.get().then((res) => {
this.myJson = res.data;
}).catch((err) => {
this.errors = err;
});
}

For the created() hook, the data after manipulation in the browser it not shown in the DOM before mounted. In simple words the data takes time to manipulate the DOm seen the browser .
The mounted() hook is called after the DOM has been mounted or rendered which enables you to have access to the DOM elements and you can perform DOM manipulation.The best use for the mounted hook is if you need to access the DOM immediately before or after the initial render.

Related

Need a callback when it is OK to access the DOM

I have an Angular component that fetches markdown, converts it to HTML, then inserts it into the DOM. After insertion it does some more DOM manipulation. So the template is this:
<div id="fixroot" [innerHTML]="content"></div>
and the component is like this:
content: string;
...
async getPage(url: string) {
try {
this.content = this.mdToHtml(await this.http.get(url, { responseType: 'text'}).toPromise();
setTimeout(() => this.fixupDOM(), 400);
....
fixupDom() {
const el = document.getElementById('fixroot');
// do stuff to the DOM element that are children of el
The use of setTimeout here is really awful, but without it the fixupDom method doesn't work
because the DOM is not ready when the Promise concludes. But it has to go.
What I need is a callback (probably from the HTMLElement
el) that calls my routine as soon as the DOM structure is ready. I haven't been able
to make anything work. Anyone know the right function?
You can try and use the ngAfterViewInit hook that fires after your content has been loaded.
If you use a template reference for your div then you can access it after the ngAfterViewInit fires.
This is the angular way of accessing the DOM which makes it framework agnostic in case you want to run in a web worker etc...
Since you are inserting HTML you made also need to pipe that HTML through a Sanitizer because angular has a sanitizing context due to XSS.
ngAfterContentInit lifecycle hook is called earlier during creation and rendering of component and directive.
You can implement it in your directive and access content to be reflected in the directive's view. For example,
ngAfterContentInit() {
const el = this.content.nativeElement;
// mutate el as desired
}

vue nexttick for map

I have a <div id="map" />
I have a mounted method in which I initialize map.
mounted(){
this.map = L.map(this.mapId, { preferCanvas: true }).setView(
[this.initialLatitudeOriginalPoint, this.intiialLongitudeOriginalPoint],
3
)
L.tileLayer(
tileconfig + '?access_token=' + key
{ maxZoom: 25, id: 'mapbox.streets' }
).addTo(this.map)
}
I have a prop called markers. and I have a watcher for it with immediate true
markers:{
handler(newVal, oldVal){
this.showMarkers()
},
immediate: true
},
Question- Looks like watcher gets called first. before mounted. Then showMarkers function throws error as map won't be defined because watcher got first before mounted. I really need immediate true for that watcher. Is there any way I can know that until map is not defined, watcher should wait?
What I think of: I think of using nextTick. but I don't understand one point about it. If I write this.$nextTick in my watcher's handler function, when will that nextTick callback be called? after dom got updated in this specific component or even in parent and parents of parents? if it doesn't care current component, then nextTick might be a little bit wrong in my case. I just want to understand this last thing about nextTick. any clue?
Firstly, you are correct that immediate will cause the watch to be triggered before the component is mounted. The role of watch is primarily to perform updates to properties based on other properties. So it will wait for all the basic properties (props, data, etc.) to be initialised but it assumes that rendering will need the output of the watch to render correctly. In your case this isn't true.
The way I would write this is:
mounted () {
// ... map stuff ...
this.showMarkers()
},
watch: {
markers: 'showMarkers'
}
If there needs to be a nextTick in there I'd be inclined to do that inside showMarkers rather than making it the caller's problem.
However, you don't have to do it this way. You can do it using immediate and nextTick, as suggested in the question.
So the key thing is to understand when exactly nextTick is called.
If a rendering dependency changes Vue will not re-render the component immediately. Instead it's added to a queue. Once all your other code has finished running Vue will process that queue. This is more complicated than it sounds as various components within the parent/child hierarchy may need updating. Updating a parent may result in the child no longer existing.
Once the queue has been processed and the DOM updated, Vue will call any nextTick callbacks. Any further changes that occur inside the callback will be added to a new rendering queue.
There are a couple of key points to note here.
While Vue may have updated the DOM, the browser won't actually paint all the new nodes until the JavaScript code has finished. That includes any nextTick callbacks. So if nextTick triggers further updates the user will not see the interim state of the page.
All of this is assuming that Vue is tracking the updates and performing the rendering. If you're doing rendering outside of Vue, as you are via Leaflet, then Vue can't do as much to help you.
So let's consider the following:
markers:{
async handler(newVal, oldVal){
await this.$nextTick()
this.showMarkers()
},
immediate: true
},
I've used async/await here rather than passing a callback but the end result is the same.
When the handler is called the first time it is before the component has rendered. The $nextTick will be called after all rendering has completed (including other components). So long as other components don't assume that the markers already exist this shouldn't be a problem, they'll still be created before the user sees anything.
When markers subsequently changes it may not actually trigger any rendering within Vue. Unless you're using markers somewhere within one of your templates it won't be a rendering dependency so no new rendering will be triggered. That's not necessarily a problem as $nextTick will still work even if there's nothing for Vue to render.

If component returns null in its render function, why componentDidMount is triggered?

I've been using React for a while, but today I started wondering about one thing.
Why componentDidMount method is fired even though my render function returns null?
From the docs:
componentDidMount() is invoked immediately after a component is
mounted (inserted into the tree). Initialization that requires DOM
nodes should go here. If you need to load data from a remote endpoint,
this is a good place to instantiate the network request.
As I understand it correctly: component returns null, so that there's nothing to mount in the DOM tree and componentDidMount should not be fired.
componentDidMount() will fire exactly after render()! so you're saying that your render function returns null, which means render function executes!
Proof:
If you put a console.log inside your render function, exactly before return (what I do most of time for checking stuff like state updation or checking if current component receives props from parent component) you will see that log result in the console, which means that javascript executes the render.
It doesn't matter what it will render, null or hundred lines of jsx

How to initiate a Standard Javascript Callback in Vue.js

How can I initiate this callback on Vue.js on page load?:
lightGallery(document.getElementById('lightgallery'));
One of Vue's life cycle hooks is beforeMount,
Your code can be:
beforeMount(){
lightGallery(document.getElementById('lightgallery'));
},
Use the initialization in your vue component with lifecycle hooks:
Vue.component('lightGallery', function() {
template: '<div>Place template markup here</div>',
mounted: function() {
$(this.$el).lightGallery();
}
});
Then you can just use the component:
<lightGalleryr></lightGallery>
There are different lifecycle hooks Vue provide:
I have listed few are :
beforeCreate: Called synchronously after the instance has just been initialized, before data observation and event/watcher setup.
created: Called synchronously after the instance is created. At this stage, the instance has finished processing the options which means the following have been set up: data observation, computed properties, methods, watch/event callbacks. However, the mounting phase has not been started, and the $el property will not be available yet.
beforeMount: Called right before the mounting begins: the render function is about to be called for the first time.
mounted: Called after the instance has just been mounted where el is replaced by the newly created vm.$el.
beforeUpdate: Called when the data changes, before the virtual DOM is re-rendered and patched.
updated: Called after a data change causes the virtual DOM to be re-rendered and patched.
You can have a look at complete list here.
You can choose which hook is most suitable to you and hook it to call you function like the sample code provided above.

React's setProps() deprecated warning

In parent component App I render child component PersonsTable:
var App = React.createClass({
addPerson: function() {
// building personToAdd object and passing to personsTable...
this.refs.personsTable.setState({personToAdd: person});
},
render: function() {
return (
<div>
<PersonsTable ref="personsTable" />
...
</div>
);
},
});
Now I'm passing a new object by calling setState method of PersonsTable.
If I call setProps method, it returns a warning
Uncaught Invariant Violation: setProps(...): You called setProps on a component with a parent. This is an anti-pattern since props will get reactively updated when rendered. Instead, change the owner's render method to pass the correct value as props to the component where it is created.
How do I correctly pass such an object to PersonsTable without using setState method?
Here is full code https://jsfiddle.net/jpt5uy1k/
It looks like you're trying to implement an anti-pattern by calling setState on a ref. It's better to pass props to the child and use those. If you need state, set it in a parent and pass it down as a prop.
<div>
<PersonsTable aProp={someCoolInfoOrParentState} />
...
</div>
Refs should be used only when you need to "reach out" and get hold of an actual DOM node for one reason or another. Also, you generally want state in as few places as possible, since it can be complicated and requires extra "machinery" to make work. Better to keep state in a single place and thread it down through other components.
See this from https://github.com/reactjs/react-basic:
We tend to prefer our data model to be immutable. We thread functions through that can update state as a single atom at the top.

Categories

Resources