Recently, I dedicated some time to revisit Vue.js, the first JavaScript framework I explored several years ago. Over the past two years, the framework has evolved, and revisiting it has provided me with a fresh and enriched perspective on its capabilities and applications. I am thrilled to share my insights and experiences with you!
1. What is vue.js
vue.js is a progressive javascript framework that makes building interactive and reactive web frontends easier.
-$$-
Vue.js is a progressive JavaScript framework that simplifies the process of building interactive and reactive web frontends.reactive means very responsive to what users have done in the page.
-$$-
In web development, reactive refers to a web frontend that is highly responsive to user actions on the page.the advantages of vue are Approachable Performant and Versatile.
-$$-
Vue.js offers several advantages, including its approachable nature, performant capabilities, and versatility.
What's spa
load html only once, and then use javacript to manipulate the doms in the page and you don;t need to wait the page to load.
-$$-
With Vue.js, you can load HTML only once and then use JavaScript to manipulate the DOM elements on the page, eliminating the need to wait for the page to reload.
the only one thing that changes in a spa application is data.
-$$-
In a Single Page Application (SPA), the only thing that changes is the data, allowing for a more seamless and efficient user experience.
Why vue
because if you want to implement a spa application using regular javascript you have to write all the things from beginning, which may cause a lot of time and many bugs.
-$$-
Implementing a Single Page Application (SPA) using regular JavaScript can be time-consuming and prone to errors, as you have to write all the necessary code from scratch.
How to use vue
in 2 ways, you can use vue to control part of page or whole page and you can use it to control other parts of your application other than the pages. That's because in a spa application, we only request html once, and after that vue will take care of this application.
-$$-
Vue.js can be used to control either part of a page or the entire page, and it can also be used to control other parts of your application beyond just the pages. This is because in a Single Page Application (SPA), the HTML is only requested once, and then Vue.js takes care of the rest of the application.
Vue alternatives
of cource, the alternatives are react and angular!
-$$-
Of course, there are other popular JavaScript frameworks available, such as React and Angular, which can also be used for building web applications.
2. First vue app
you can open the website https://vuejs.org/guide/quick-start.html#using-vue-from-cdn
then it will tell you how to use vue in your index.html file.
-$$-
To learn how to use Vue.js in your HTML file, you can visit the Vue.js official website at vuejs.org/guide/quick… for a quick start guide.
Personally, I'd rather use it in module type with import-map, so I can write my first vue application as following:
-$$-
Personally, I prefer to use Vue.js in a modular way with import-map, which allows me to write my first Vue application as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My first vue app</title>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
}
}
</script>
</head>
<body>
<div id="app">{{ message }}</div>
<script type="module">
import { createApp, ref } from "vue";
createApp({
setup() {
const message = ref("Hello Vue!");
return {
message,
};
},
}).mount("#app");
</script>
</body>
</html>
As you can see, unlike using regular javascript, when we choose to use vue framework, we don't have to tell the broswer to do things step by step, which means you don't have to tell the browser how to do a specific task, you just need to tell the browser what you want, then vue will handle the details in this process.
-$$-
As you can see, when using the Vue framework, you don't have to manually tell the browser how to do things step by step. Instead, you simply tell the browser what you want, and Vue handles the details of the process for you.
Start from directives
When we learn how to use vue, we normally start with directives in Vue such as v-on v-for, etc.
-$$-
When learning how to use Vue.js, we typically start with learning about directives such as v-on and v-for.
Before we write some true code, we must make sure that our code at good format, so I highly recommand you to install a vscode extension named Prettier - Code formatter
.
-$$-
Before we write any actual code, we must ensure that our code is in good format. Therefore, I highly recommend that you install a VS Code extension named "Prettier - Code formatter".
3. What do you need to know
- Basic: Core Syntax, Templates, Dierectives, Data, Methods, Computed Properties, Watchers
- Intermdiate: Components, Component Communication, Behind the Scenes, Forms, Http, Routing, Animations
- Advanced: Vuex, Authentication, Deployment & Optimizations, Composition API, Re-using Code
4. Core Concept
The first and the most important concept is Template
which means Vue + HTML. And how to output dynamic content using vue is very important too. The equally important concept is how to react to user's input.
-$$-
The first and most important concept is the Template, which refers to the combination of Vue and HTML. Additionally, understanding how to output dynamic content using Vue is equally important. Similarly, knowing how to respond to user input is also a crucial concept.
Now, let's write our first app:
-$$-
Now, let's proceed to write our first app.
<section id="user-goal">
<h2>My Course Goal</h2>
<p>{{ courseGoal }}</p>
</section>
const app = Vue.createApp({
data(){
return {
courseGoal: 'Finish the course and learn Vue!',
}
}
});
app.mount('#user-goal');
5. Interpolation -- double curly braces syntax
In Vue.js, you can use the variables in a special way in some DOM elements only if these DOM elements are under the control of Vue.js.
-$$-
In Vue.js, variables can be integrated into specific DOM elements through a unique approach, but this capability is only available for elements that fall within Vue.js's managed scope.
Use Interpolation in Anchor Link
Typically, you can only use double curly braces syntax in interHTML of a certain DOM element. Therfore, when you write this sytax in an attribution of an anchor element, it just goes wrong.
-$$-
Typically, the double curly braces syntax in Vue.js is designated for use within the innerHTML of specific DOM elements. Consequently, employing this syntax within the attributes of an anchor element or similar tags will not function as intended and may result in errors.
const app = Vue.createApp({
data(){
return {
googleLink: 'http://www.google.com/',
}
}
});
app.mount('#user-goal');
<a href="{{googleLink}}">GO TO GOOGLE</a>
In this scenario, we can use a different syntax or directive named v-bind
, as the following code shows:
-$$-
In this scenario, an alternative syntax or directive, known as v-bind, can be employed to achieve the desired outcome, as demonstrated in the following code example:
<a v-bind:href="googleLink">GO TO GOOGLE</a>
Noted that you don't need double curly braces.
-$$-
In such cases, the double curly braces are not required. Instead, you should utilize the v-bind directive to ensure proper binding of dynamic values to attributes, as illustrated in the example above.
Futhermore, you can use regular Javascript in double curly braces, such as {{1+1}}
or {{Math.random()}}
. However, you can't use complex control syntax such as {{if () {} else {}}}
.
-$$-
Furthermore, Vue.js allows the use of basic JavaScript expressions within the double curly braces. This means you can perform simple operations like {{ 1 + 1 }} or call functions such as {{ Math.random() }}. However, it's important to note that complex control structures, akin to traditional JavaScript syntax, are not supported within the interpolation syntax. For example, you cannot embed statements like {{ if () {} else {} }} directly within the double curly braces. Instead, for such control logic, Vue.js provides directives like v-if, v-else-if, and v-else to handle conditional rendering within the template.
6. Methods
Except Data property, Vue.js offers another powerful weapon to build a dynamic application named Methods. In this property, you can create your own functions and use them in double curly braces or in directives. And, this really makes Vue.js amazing.
-$$-
In addition to Data properties, Vue.js equips developers with another powerful feature for constructing dynamic applications: Methods. Within this feature, you can define custom functions that are readily accessible for use within double curly braces or integrated into directives. This capability significantly enhances the flexibility and expressiveness of Vue.js, contributing to its reputation as an impressive framework for building interactive user interfaces.
const app = Vue.createApp({
data(){
return {
googleLink: 'http://www.google.com/',
}
},
methods: {
getRandom(){
return Math.random()+'';
}
}
});
app.mount('#user-goal');
<a href="{{googleLink}}">{{getRandom()}}</a>
You might want to know how to use data in methods you created. That's pretty easy because you can find the data you need directly in this
, just as the following code shows:
-$$-
You might be curious about how to access data within the methods you've created in Vue.js. The process is quite straightforward: you can access the required data through the this keyword, which refers to the current Vue instance. This allows you to utilize the data properties and other methods within your instance. Here's a simple illustration of how it works:
const app = Vue.createApp({
data(){
return {
googleLink: 'http://www.google.com/',
}
},
methods: {
getRandom(){
return Math.random() + this.googleLink;
}
}
});
app.mount('#user-goal');
Prety easy, right? Now, let's make the thing more interesting. What if the data actually means XML? In this scenario, you must use another directive named v-html
to render the DOM elements you want.
-$$-
It's quite simple, isn't it? Now, let's delve into a more intriguing scenario. What if the data you're working with is actually XML content? In such cases, the standard data binding with double curly braces won't suffice because it's designed to handle text, not HTML or XML. To render XML or HTML content dynamically, you'll need to employ a different directive: v-html
.
<p v-html="someHtml"></p>
<p v-html="getHtml()"></p>
const app = Vue.createApp({
data(){
return {
someHtml: '<p>http://www.google.com/</p>',
}
},
methods: {
getHtml(){
return this.someHtml;
}
}
});
Let's revoke the concept declarify
. After get in touch with Vue.js, we can summarize that developers write a dom template and mark which part of this template is dynamic and then Vue.js will do other things for us, and that's what declarify means.
-$$-
Let's delve into the concept of 'declarative programming' as it relates to Vue.js. When developers work with Vue.js, they craft a DOM template and explicitly indicate which parts of the template should be dynamic. This approach allows them to describe the desired outcome rather than the step-by-step process of how to achieve it. Vue.js then takes these declarations and handles the rest, updating the DOM reactively based on the underlying data.
-$$-
In essence, 'declarative' refers to the way developers specify what the UI should look like for given data, without explicitly writing the logic to manipulate the UI. This is in contrast to 'imperative programming,' where developers would write detailed instructions for how to change the UI in response to data changes.
Bind methods to DOM elements
It's very important to bind our methods to the DOM elements, in this way, we can capture and then deal with element events. Here are some exampes to demostrate how to do with it.
-$$-
It is crucial to bind our methods to the DOM elements to enable event handling. By doing so, we can effectively capture element events and respond to them accordingly. Below are several examples that illustrate the process of binding methods to DOM elements for event management.
<button v-on:click="count++">Click to Plus</button>
const app = Vue.createApp({
data(){
return {
count: 0,
}
}
})
As you can see, we just put some raw Javascript code in the quotas. However, it's not the best practice becase lack of duplicativity. Other than this form, we can modify the above code like:
-$$-
As you can see, we've simply inserted raw JavaScript code within the quotes. However, this is not considered best practice due to the lack of reusability. Instead of this approach, we can modify the code as follows:
<button v-on:click="add()">Click to Plus</button>
const app = Vue.createApp({
data(){
return {
count: 0,
}
},
methods:{
add(){
this.counter++;
}
}
})
Futhermore, if you don't need to transmit any parameter to method, you can simplify the code as:
-$$-
Furthermore, if there is no need to pass any parameters to the method, you can simplify the code even further as follows:
<button v-on:click="add">Click to Plus</button>
Use Event Object
But what if we really need to use some specific parameter? How can I access to event object when I capture an event emmited from an input element? Or what should I do if I want plus 2 not 1 to variable counter?
-$$-
But what if we need to utilize specific parameters within our event handling methods? How can we access the event object when capturing an event emitted from an input element? For instance, if we want to increment the variable counter by 2 instead of 1, how should we modify our method to accommodate this requirement?
So, in most scenarios, we need to transmit some parameters.
-$$-
So, in most practical scenarios, it is necessary to pass parameters to our methods.
<button v-on:click="add(5)">Click to Plus</button>
const app = Vue.createApp({
data(){
return {
count: 0,
}
},
methods:{
add(num){
this.counter += num;
}
}
})
But, in some situations, the arguments are transmitted by default which means methods can recieve some argument event we didn't pass them when call this method.
-$$-
However, there are certain situations where methods may receive arguments by default, meaning that they can be passed additional arguments even if we do not explicitly provide them when invoking the method.
<input v-on:input="handleInput" type="text" />
const app = Vue.createApp({
data(){
return {
name: ''
}
},
methods:{
handleInput(event){
this.name = event.target.value;
}
}
})
Then, you may want to say what if I want to pass the default event object and other arguments defined by yourself? In this case, we need to transmit the event object in a explicit way.
-$$-
Then, you might ask, what if I want to pass the default event object along with other arguments that I define myself? In such cases, it's necessary to explicitly pass the event object as an argument to the method.
<input type="text" v-on:click="handleInput($event, 'iot-')"
const app = Vue.createApp({
data(){
return {
name: '',
}
},
methods: {
handleInput(event, prefix){
this.name = event.target.value + prefix;
}
}
})
Submit the Form & Prevent Default Actions
Let's look at some basic code about how to submit a form in Vue.js.
-$$-
Let's examine some fundamental code examples that demonstrate how to handle form submission in Vue.js.
<form v-on:submit="handleSubmit">
<input type="text" />
<button type="submit">Sign Up</button>
</form>
const app = Vue.createApp({
data(){
return {}
},
methods:{
handleSubmit(event){
event.preventDefault();
}
}
})
If we don't prevent the default action of submission of the form, our page will refresh and we will lose all the information of the page, which typically does not meet our expections.
-$$-
If we do not prevent the default action of form submission, the page will refresh, potentially causing the loss of all page information, which typically deviates from our expectations.
In Vue.js, you can use some special syntax called modifier to make this process more seamless.
-$$-
In Vue.js, you can utilize special syntax elements known as 'modifiers' to streamline the process of handling form submissions, ensuring a more seamless user experience.
<form v-on:submit.prevent="handleSubmit">
...
</form>
Cool! And there's another example.
-$$-
Fantastic! Now, let's explore another example that further illustrates the concept.
<button v-on:click.right="add(5)">Only Right Click Effects</button>
And the most useful ones are:
v-on:keyup.enter
v-on:keyup.ctrl
v-on:keyup.page-down
etc.
7. Common Use Directives
v-once
v-once is a directive that ensures your content render only once. When you bind this directive to a specific element, this element's content will not change event the corresponding varible changes later.
-$$-
The v-once directive is a unique feature in Vue.js that ensures content is rendered only once. When applied to an element, it guarantees that the content within that element will not update, even if the associated variable changes subsequently. This behavior is particularly useful for optimizing performance by preventing unnecessary DOM updates.
8. Use v-on and v-bind to implement two way binding
You can use v-on and v-bind to implement two way binding, as the following code shows:
-$$-
Implement two-way data binding in Vue.js by utilizing the v-on and v-bind directives, as illustrated in the following example code:
<input v-bind:value="name" v-on:input="name=$event.target.value" />
And Vue.js offers an easy way to do that:
-$$-
Moreover, Vue.js simplifies this process significantly, providing a straightforward approach to achieve two-way binding, as demonstrated in the example code.
<input v-model="name" />
9. Computed -- The Reason Why Methods Are Not The Best Way to Render Dynamic Content
The answer is quiet easy. When you change some variables on the page, the page will reresh causing any methods running again, which may lower performance. So, what is the best solutiuon?
-$$-
The solution is quite straightforward. When variables on the page are altered, a full page refresh can occur, potentially re-triggering methods and impacting performance. To optimize this, consider the following best practices:
So, we change to use another most important feature equiped by Vue.js name computed
. Before that, I must remind you that we have learned data and methods we create an app using Vue.js.
-$$-
Moving forward, we'll delve into another crucial feature provided by Vue.js known as computed. Before we proceed, it's worth recalling that in our journey with Vue.js, we've already explored the foundational concepts of data and methods, which are essential for building applications with Vue.js.
In the aspect of form, you can see computed as a combination of functions, just like the function in methods. However, in the aspect of usage, computed is muck more like the variables in data. That's very interesting, which means you can use the function name as variables in template or bind them to directives.
-$$-
From a structural perspective, computed properties in Vue.js can be viewed as a special kind of function, similar to those found within the methods option. However, when it comes to usage, they behave more akin to the reactive variables in the data object. This is quite intriguing because it allows us to treat the names of these computed functions as if they were variables within our templates or even bind them to directives, leveraging their reactive nature seamlessly.
I think there are three notes you nedd to bare in mind:
- Don't declare a varible with the same name as a function in computed in data. If you do that, the variable in data will override the corresponding function becasue data has a priority over computed.
- Don't use the functions in computed as callbacks as you may want to bind it to DOM elements.
- Computed is used to render dynamically, don't use it to do other things.
-$$-
Here's a refined version of your notes:
Avoid Naming Conflicts:
Refrain from declaring a variable in your data with the same name as a computed property. If you do, the variable in data will take precedence over the computed property, effectively overriding its functionality.Reserved for Direct Use:
Computed properties are designed to be used directly in templates or bound to directives. Avoid using them as callbacks, as this can lead to unexpected behavior when they are intended to be bound to DOM elements.Purpose-Specific:
Computed properties are primarily intended for dynamic rendering. They should not be used for other purposes, such as handling side effects or performing operations that are not directly related to updating the UI based on reactive data changes.
Ok, now let me show you a simple example:
-$$-
Let's dive into a simple example to see computed properties in action.
<div id="app">
<input v-model="firstname" type="text" />
<p>{{fullname}}</p>
</div>
const app = Vue.createApp({
data(){
return {
firstname: 'Li',
lastname: 'XiaoLong',
}
},
methods: {
},
computed:{
fullname(){
return this.firstname + this.lastname
}
}
})
app.mount('#app')
There is a function named fullname exist in computed, and it's return value is related to the variables firstname and lastname in data. So, whenever the value of firstname or the value of lastname changes, the function fullname will be called, and then pass the new value to the template.
The most fasinating thing is we use fullname which is a function to render dynamic content in the template.
-$$-
In Vue.js, consider a computed property named fullname. This property is designed to derive its value from the variables firstname and lastname found in the data object. The beauty of computed properties is their reactivity; whenever either firstname or lastname is updated, the fullname function is automatically invoked. It then computes a new value based on these changes and updates the template accordingly.
10. Watch -- another way to use change
We can understand that the functions in computed are kind of a way to use changes of variables in data in a passitive way. So, we naturelly can image how to use this change in a positive way.
After a certain variable in data changes, we want to do something or generate some effects based on this change. In this case, we can use the feature watch.
-$$-
We can think of computed properties in Vue.js as a reactive mechanism that passively observes changes in the data. They automatically update their values whenever the underlying data changes. This allows us to harness these changes in a proactive manner. When a specific variable in our data changes, and we need to perform actions or generate effects based on this change, we can utilize the watch feature. This feature enables us to define custom reactions to data changes, providing a powerful way to handle dynamic updates in our applications.
<div id="app">
<input v-model="lastname" type="text" />
<p>{{fullname}}</p>
</div>
const app = Vue.createApp({
data(){
return {
firstname: 'Li',
lastname: 'XiaoLong',
fullname: '',
}
},
methods: {
},
computed: {
},
watch: {
lastname(value){
this.fullname = this.firstname + value;
}
}
})
As you can see, because we want to change something after the change, so the functions in watch don't need a return value. But unlike the functions in computed, the functions in watch accept at least one argument as the latest value of the variable with the same name of the function.
-$$-
As you can observe, the purpose of watch functions in Vue.js is to execute code in response to changes. Unlike computed properties, which do not require a return value, watch functions must accept at least one argument. This argument represents the most recent value of the observed variable, and it is passed to the watch function automatically.
11. Short form of v-on:
and v-bind:
In Vue.js, you can always replace v-on:
with @
as well as replace v-bind:
with :
.
-$$-
In Vue.js, the directive v-on:
can be concisely written as @
, and similarly, v-bind:
can be abbreviated as :
.
12. Dynamic Stylings
12.1 Inline Styling
When we treat the attribute style as dynamic, the type of the value of this atrribute is no longer the string.
-$$-
When dynamically assigning the style attribute, the value type is no longer a string but an object.
<p :style="{color: isDark?'#fff':'#ccc'}">How Inline Style Works?</p>
Actually, the value inside of the quatos is a regular object in Javascript.
-$$-
In fact, the value encapsulated within the quotes is a standard JavaScript object.
12.2 Using Dynamic ClassName
When we treat the attribute class as dynamic, the type of the value of this attribute can be assign to a plain object in Javascript, just like what we do in :style
. This is the most popular way but not the only way to use dynamic attribute class.
Actually, we can use dynamic and static attribute together no mater for class or style.
-$$-
When we treat the attribute class as dynamic, the type of the value of this attribute can be assigned to a plain object in JavaScript, similar to what we do with :style
. This is the most popular way, but it is not the only way to utilize dynamic attribute classes. Actually, we can use dynamic and static attributes together, whether for class or style.
<div id="app">
<div
class="static"
:class="{withBgc: needBgc, withBold: needBoldFont}"
>
Test Dynamic ClassName.
</div>
</div>
const app = Vue.createApp({
data(){
return {
withBgc: true,
needBoldFont: false,
}
}
});
app.mount();
We can combine the computed feature with dynamic className to make it even easier.
-$$-
We can combine computed features with dynamic classNames to make the process even easier.
<div id="app">
<div
class="static"
:class="dynamicClass"
>
Test Dynamic ClassName.
</div>
</div>
const app = Vue.createApp({
data(){
return {
withBgc: true,
needBoldFont: false,
}
},
computed: {
dynamicClass(){
retrun {withBgc: this.needBgc, withBold: this.needBoldFont};
}
}
});
app.mount();
You can also assign the value of :class
to be array.
-$$-
You can also assign the value of :class
to be an array, providing flexibility in defining multiple classes.
12.3 Some Tips to Use Dynamic Class
When you use dynamic class, you can assign an array as its value. Once you do in that way, you can use the following tip:
-$$-
When using a dynamic class, you can assign an array as its value. Once you do so, you can utilize the following tip:
getClass () {
const classes = [];
if(meets1) {
classes.push('rule1');
}
if(meets2) {
classes.push('rule2');
}
if(meets3) {
classes.push('rule3');
}
return classes;
}
<span :class="getClass()">AABBCCDD</span>
But if you do want to use it as plain object, then you can do as follows:
-$$-
But if you do want to use it as a plain object, then you can do so as follows:
paraClass(){
return {
rule1: this.applyRule === 1,
rule2: this.applyRule === 2,
rule3: this.applyRule === 3,
}
}
13. Directives
13.1 v-if v-else-if v-else
I think one of the most powerful tools in Vue.js is directive, which includes v-if
, v-else
and so on.
-$$-
I believe one of the most powerful tools in Vue.js is directives, which include v-if, v-else, and so on.
Now, let's have a quick look at how to use it to make our application more dynamic.
-$$-
Let's take a swift glance at the process of integrating this feature to enhance the dynamism of our application.
<p v-if="goals.length === 0">No goals have been added</p>
<ul v-else>
<li>Goal</li>
</ul>
Well, I think you must bear in mind that there should not be any other elements between the elements that use v-if
and v-else
.
-$$-
Indeed, it's crucial to remember that the elements utilizing v-if and v-else should not be interspersed with other elements. This ensures that the conditional rendering functions as intended.
Futhermore, we even can extend the above code using another directive named v-else-if
,
-$$-
Additionally, we can enhance the aforementioned code by incorporating an additional directive called v-else-if
, which allows for more nuanced conditional rendering within our templates.
<p v-if="goals.length === 0">No goals have been added</p>
<ul v-else-if="goals.length>0">
<li>Goal</li>
</ul>
<p v-else>...</p>
As you can see, it's very much like you writing Javascript code.
-$$-
As you can see, the process closely mirrors writing JavaScript code, providing a familiar and intuitive approach to manipulating the DOM reactively based on conditions.
13.2 v-show
and v-if
Besides the directive v-if
, we can use another directive to implement the same effect that can toggle the preference of a certain element. And this is the v-show
directive.
-$$-
In addition to the v-if directive, we have at our disposal another directive that achieves a similar effect, allowing us to toggle the visibility of an element. This directive is known as v-show. It offers an alternative approach to conditional rendering, providing flexibility in how we choose to present elements in our application based on varying preferences or states.
<ul v-show="goals.length>0">
<li>Goal</li>
</ul>
But, what's the difference? Actually, when you use v-if
, especially its value equals to false, you can not find the Dom element in html. But, when you use v-show
, even its value equals to false, you still can find the corresponding element with a display: none
.
-$$-
However, there is a distinct difference between the two directives. When employing v-if, if its condition evaluates to false, the associated DOM element is entirely removed from the HTML, making it untraceable within the document. On the other hand, utilizing v-show maintains the element in the DOM even when its condition is false, simply applying a CSS rule of display: none to hide it. This means that the element remains in the document's structure but is not visible to the user, which can have implications for both layout and accessibility considerations.
13.3 v-for
After these two basic directives, we now can take a look at the third one named v-for
. The directive v-for
is used to duplicate a similar dom structure at any times by your wish.
-$$-
Following our exploration of the foundational directives, we now turn our attention to a third directive known as v-for. This directive is instrumental for iterating over a collection to replicate a similar DOM structure multiple times, based on your specific requirements. v-for provides a powerful way to generate lists, tables, or any repeated elements dynamically, offering flexibility and efficiency in rendering repetitive components within your application.
Look at the following example:
-$$-
Consider the following example to illustrate the concept
<ul v-else>
<li v-for="goal in goals">{{goal.title}}</li>
</ul>
Unlike Angular, in Vue.js, you shouldn't add let at the first position, that's to say v-for="let goal in goals"
is not the right format.
-$$-
Unlike Angular, Vue.js does not require the use of let when declaring a v-for directive. Therefore, a syntax like v-for="let goal in goals" is not correct in Vue.js. The proper format is to directly reference the item and the iterable without the let keyword, as in v-for="goal in goals". This concise syntax simplifies the declaration and aligns with Vue.js's templating syntax standards.
If we introduce the index of each item in v-for
directive, we can make our application even more flexible. Some simple examples, you can use index to figure out which is currently be clicked or activiated.
-$$-
By incorporating the index of each item in the v-for directive, we can enhance the flexibility of our application significantly. This feature allows for straightforward identification and interaction with list items. For instance, you can leverage the index to determine which item has been clicked or activated. This capability is particularly useful in scenarios where you need to perform actions based on the position or identity of the list item within the collection.
<ul v-else>
<li v-for="(goal, index) in goals">{{`#${index} is ${goal.title}`}}<li>
</ul>
The unique syntax v-for="goal in goals"
is not confined to an array, actually, it can also be used when the iteration target's type is plain object in Javascript.
-$$-
The distinctive syntax of v-for="goal in goals"
is not limited to arrays; it is also versatile enough to be applied when iterating over plain JavaScript objects. This means that you can leverage v-for to traverse both arrays and object properties, providing a unified approach to rendering lists and object data in your Vue.js applications.
<li v-for="value in {name:'zs',age:18}">{{value}}</li>
Let's dive into this:
-$$-
Let's delve deeper into this concept:
<li v-for="(value, key, index) in {name:'zs', age:18}">{{`the key of #${index} is ${key}, while its value is ${value}`}}</li>
Additionally, we can use it in a strange way like this:
-$$-
Furthermore, we can explore an unconventional application of the directive, as demonstrated below:
<li v-for="i in 10">{{i}}</li>
So that, v-for
can be used with arrays, objects and ranges.
A quick break
Now, let me introduce a practical situation: a li element binded with a click event that will delete the li element itself wraps an input element. But, you always have to click the input element if you want to input something. But once you click the input element, the click event will bubble up to the container element li, and the li element then disappears.
-$$-
Now, let me present a common practical challenge: Imagine a li element that is bound to a click event designed to remove the li element itself. This li element contains an input element. Typically, you would need to click on the input element to interact with it. However, when you do so, the click event on the input can propagate (or "bubble up") to the parent li element, inadvertently triggering the removal of the li element. This behavior can be problematic if you intend to edit the content within the input without deleting the list item.
So, how to handle this problem?
-$$-
How can we resolve this issue?
I think the solution is decorator.
-$$-
The solution lies in the use of event modifiers, a feature that acts as a decorator in Vue.js.
<li v-for="(goal, index) in goals" @click="removeLi">
<p>{{goal}} - {{index}}</p>
<input type="text" @click.stop>
</li>
I'm sure you have noticed that we didn't bind any callback to @click.stop
, and that's totally fine, we just use it to prevent the propagation of the click event.
-$$-
I'm confident you've observed that we haven't assigned any specific callback to @click.stop. This is entirely acceptable because the primary purpose of using .stop is to halt the propagation of the click event. By employing this modifier, we ensure that the click event does not bubble up to parent elements, thereby preventing unintended actions such as the accidental deletion of the list item when interacting with the input field.
13.4 Use v-for
Properly
Because of the flaw of Vue.js itself, in some special scenarios, we must add an additional key
attribution to the items rendered by using v-for
. We can still use the above code to show this problem.
-$$-
Due to inherent limitations in Vue.js, there are certain scenarios where it becomes necessary to assign a unique key attribute to each item rendered by v-for. This additional attribute helps Vue.js to more efficiently manage and track the dynamic elements in the DOM, thus preventing potential issues that can arise from the way the framework handles list rendering. The example we've discussed earlier can be revisited to illustrate this particular challenge.
<li v-for="(goal, index) in ['g1','g2']" @click="removeLi">
<p>{{goal}} - {{index}}</p>
<input type="text" @click.stop>
</li>
After the above structure rendered, we firstly input some content into the second input and click the first li and delete it. Soon, you'll notice that the content in the second input disappears!
-$$-
Once the aforementioned structure is rendered, let's proceed with the following steps: First, input some content into the second input field. Then, click on the first li element to trigger its deletion. Upon doing this, you will quickly notice an unexpected behavior—the content within the second input field vanishes! This illustrates a common pitfall when manipulating lists with v-for in Vue.js, where the reactivity system may not update the DOM as intuitively expected after an item is removed from the list.
The concept behind this case is a bit complex, and you can add a key attribution to the li element to eliminate this weird case.
-$$-
The underlying concept in this scenario is somewhat intricate, but there's a straightforward solution to prevent this unexpected behavior: adding a key attribute to the li element. By assigning unique keys, Vue.js can more accurately track each list item during updates, which helps to avoid the confusion and anomalies that can occur, such as the disappearance of input content when a list item is removed.
<li :key="goal" v-for="(goal, index) in ['g1','g2']" @click="removeLi">
<p>{{goal}} - {{index}}</p>
<input type="text" @click.stop>
</li>
The key attribution can not only eliminate the weird cases but alse can improve effective and optimize performance of your application.
-$$-
The key attribute serves a dual purpose in Vue.js applications; it not only eliminates the peculiar issues associated with dynamic lists but also significantly enhances performance. By providing a unique identifier for each element in a v-for iteration, the key attribute allows Vue.js to efficiently update the DOM, thus optimizing the rendering process and ensuring a smoother user experience.
Before we finish this chapter, I want to stress one last thing that you shouldn't use v-if and v-for in one element at the same time. If you do need to, just use another layer to split them out. This priciple is also true when you use directives in Angular.js.
-$$-
Before we wrap up this discussion, it's imperative to emphasize a critical principle: the use of v-if and v-for should not coexist on a single element. If your application's requirements demand their concurrent use, it's advisable to encapsulate them within separate structural layers. This approach not only adheres to Vue.js best practices but also aligns with Angular.js's directive guidelines, ensuring a clean and maintainable codebase.
A quick break
Before we delve into the principle of the Vue.js, we must understand Virtual Dom or DOM Updating first.
-$$-
Before we explore the core principles of Vue.js, it's essential to first grasp the concept of the Virtual DOM, which is fundamental to how DOM updates are efficiently managed within the framework.
The following code shows a difference between React.js and Vue.js or AngularJS. In Vue.js, if we change the value of variables in data, the component will update automatically. However, in React.js when you change the variables' value, the component won't refresh itself.
-$$-
The following code illustrates a key distinction between the frameworks React.js, Vue.js, and AngularJS. In Vue.js, the framework is designed to automatically update the component whenever the values of variables within the data function change. This reactivity is a core feature of Vue.js. On the other hand, React.js requires a more explicit approach to state management. When variables in React are updated, the component does not automatically refresh. Developers must use state management techniques, such as lifting state up or using state management libraries, to ensure that changes in state are reflected in the component's UI.
const app = Vue.createApp({
data(){
return {
message: 'Vue is important.',
}
},
methods:{
clearMsg(){
this.message = '';
}
}
})
When the method clearMsg is invoked, the value of message changes, thus the component will update automatically.
-$$-
When the clearMsg method is invoked in a Vue.js component, it modifies the value of the message data property. Due to Vue.js's reactivity system, this change triggers an automatic update to the component's DOM, ensuring that the UI reflects the new state of the message. This automatic synchronization between the data model and the view is one of the defining characteristics of Vue.js's reactive data binding.
The following code shows the meaning of Reactive
:
-$$-
The following code demonstrates the principle of reactivity in Vue.js: when the clearMsg method is called, it updates the message variable, and the component re-renders automatically to reflect the change.
let message = 'Hello';
let longMessage = message + 'World';
console.log(longMessage);
message = 'Hello!!';
console.log(longMessage);
Just as the above code shows, the value of longMessage will not change corresponding to the change of the value of message. So it's not a reactive code. However, we can change it to be reactive using the proxy syntax in Javascript like what Vue.js do.
-$$-
As demonstrated in the code above, the value of longMessage does not automatically update when message changes, indicating that it is not reactive. However, this can be resolved by employing JavaScript's proxy syntax to make longMessage reactive, similar to Vue.js's underlying reactivity system.
const data = {
message: 'Hello',
longMessage: 'Hello! World!',
};
const handle = {
set(target,key,value){
if(key === 'message'){
target.longMessage = value + ' World!';
}
Reflect.set(target,key,value);
}
}
const dataProxy = new Proxy(data, handle);
dataProxy.message = 'Hello!!!';
It's very easy to ignore one important reality that we can use multiple instances of Vue in one project:
-$$-
It's easy to overlook, but a significant feature of Vue is the ability to run multiple instances within a single project.
<div id="app1">
<h1>App 1</h1>
<app1-component></app1-component>
</div>
<div id="app2">
<h1>App 2</h1>
<app2-component></app2-component>
</div>
import { createApp } from 'vue';
// Define the App 1 instance
const app1 = createApp({
setup() {
const message = 'Hello from App 1!';
return { message };
}
});
// Define the App 2 instance
const app2 = createApp({
setup() {
const message = 'Hello from App 2!';
return { message };
}
});
app1.mount('#app1');
app2.mount('#app2');
When creating a Vue.js instance, you have the flexibility to define the template directly within the instance configuration. This approach allows for a clear and concise setup, as shown in the following example:
<div id="app"></div>
const app = Vue.createApp({
template: `<p>{{ favorite }}</p>`,
data() {
return {
favorite: 'Pizza',
};
},
});
app.mount('#app');
This method is equivalent to having a separate HTML element with the template and mounting the Vue instance to it, as demonstrated below:
<div id="app2">
<p>{{ favorite }}</p>
</div>
const app = Vue.createApp({
data() {
return {
favorite: 'Pizza',
};
},
});
app.mount('#app2');
Both examples result in a Vue instance that is bound to a DOM element, but the first example emphasizes the capability to define the template inline during instance creation, streamlining the process and keeping the component's logic encapsulated within the Vue instance.
Use ref
to build a reference to a certain Vue element and then use it by this.$refs
:
-$$-
Utilize the ref attribute to create a reference to a specific Vue element within your template. Once defined, you can access this reference through this.$refs in your component's methods, providing a direct way to interact with the DOM element in a reactive manner.
<section id="app">
<h2>How Vue Works</h2>
<input type="text" ref="userText">
</section>
const app = Vue.createApp({
data(){
return {
iptValue: '',
}
},
showRef(){
const ipt = this.$refs.userText;
this.iptValue = ipt.value;
}
})
Unlike using ref in React.js, we don't need any current property.
-$$-
Unlike React.js, where references are managed through the useRef hook and accessed via a current property, Vue.js simplifies the process. In Vue, you can directly assign a ref attribute to an element, and it will be accessible via this.$refs without the need for an additional current property.
The principle behind the Vue updating. When we update a page establishing by Vue.js, vue takes a strategy that doesn't compare the difference between the new state and the old state of the real DOM structure, instead, vue will compare the difference between the new state and the old state of the virtual DOM structure, and then render the virtual DOM to be the real DOM.
-$$-
Vue.js employs an efficient updating strategy that avoids direct comparison between the new and old states of the actual DOM. Instead, Vue utilizes a Virtual DOM to track changes. When an update occurs, Vue compares the new Virtual DOM state with the previous one. Any detected differences are then applied to the real DOM in a targeted manner, ensuring that only the necessary parts of the page are re-rendered. This approach optimizes performance by minimizing direct DOM manipulations.
The reason why vue does this way is that the real DOM structure is much more complex than the structure of virtual DOM. By using the virtual DOM, vue can improve the performance while updating at a very high level.
-$$-
Vue opts for a Virtual DOM approach for a compelling reason: the real DOM is inherently more complex and costly to manipulate directly. By leveraging a Virtual DOM, Vue can efficiently calculate the minimal changes needed between states. This strategy significantly enhances performance during updates, as only the necessary modifications are applied to the actual DOM, maintaining a high level of responsiveness and efficiency in the rendering process.
We often use div to contain other DOM elements, however, in some cases, the container lose its all children. In this situation, we don't need this container at all, so we just hide this element. But how can we do that?
-$$-
In scenarios where a container element in the DOM loses all its children, the container itself may become redundant. Instead of removing the container, we might choose to simply hide it. This can be achieved by applying a CSS rule to set the display property to 'none', effectively concealing the element without altering the underlying structure of the document.
Now, I will introduce a special css class named :empty
. It can select the elements with no children.
-$$-
Let's delve into a CSS feature that can streamline your DOM management: the :empty
pseudo-class. This selector targets elements that are devoid of any child nodes, including text nodes, element nodes, comments, and processing instructions. Utilizing :empty
, you can apply styles to such elements, such as hiding them, without the need for additional JavaScript or conditional rendering. This can be particularly useful for dynamically managing the visibility of containers that may sometimes be empty.
-$$-
Here's how you can use the :empty
pseudo-class in your CSS:
:empty {
display: none;
}
div.ui.icon.header:empty {
display: none;
}
-$$-
This CSS rule will hide any element that has no children. It's a straightforward and efficient way to manage the visibility of elements based on their content.