Finally, I have passed the tense and exciting final exams and defended three major assignments.
The subject that I was least confident about turned out to be the only open-book exam of the semester - Hadoop. I couldn't find the information in the book, although the operating system was also difficult, at least others had a 46% weightage (6% for regular assessments and 4% for the final exam).
Actually, the main reason is that I didn't pay much attention, hehe.
Zero#
This semester, we had a course called Software Engineering. Fortunately, there was no final exam for this course, but unfortunately, the teacher asked us to write a 6000-word essay (6000 words!).
We had to choose one topic from several options to write the essay. We chose the Student Academic Management System based on the principle of being easy to write, easy to understand, and having many templates available on Google/Baidu for us to copy.
The teacher said, "This assignment won't be checked for plagiarism, and you don't have to implement this project. Just write it based on the template I provided."
The impact of the previous 6000 words was reduced by half for me. Although I am not good at writing, I am really good at copy-pasting.
In this way, I racked my brains to find a way to get through this assignment. But sometimes, when people are lazy, they feel anxious about other people's efforts.
When I was about to start working on it, my roommate suddenly bombarded our roommate group chat with messages.
"XX actually completed the project they chose!"
"What project?"
"The one for Software Engineering."
I could only admire them and continue lying on my bed, scrolling through my phone, and smoothly passing this final exam. If I take a step back, the sky is wide open, but the more I endure, the more angry I become.
Somebody has to win, so why not be me?
I also had to do something. I had looked at Vue.js recently, so I decided to use it as a practice project. That way, even if I failed, I would have a reason (self-consolation).
1. Programming for Search Engines#
To be honest, because this was the first time I was getting hands-on experience, I knew I would definitely encounter many challenges, but I didn't expect to face a major obstacle right from the start.
White bar issue at the top of the page#
I started by writing a login and registration page, but no matter how much I changed the CSS properties, there was always a white bar at the top. I even searched on Google and found a bunch of CSS properties to try (although it was indeed a styling issue).
In the end, I kept searching for answers and finally found the solution in an article that had nothing to do with this problem. It also gave me some knowledge.
Firstly, index.html is the entry point of the project, and there is only one div tag in the body, with an id of "app". This id will be connected to the content in src/main.js, which initializes the Vue instance. In other words, through main.js, we connect to the App.vue component.
Then, in the App.vue component, the router-view tag will render the routing-related content in this div, and the content of the router is in index.js.
In index.js, we publish the components we have written as routes.
This is the loading process of a Vue project. Then, I checked the properties of my page using F12 on the webpage and found that the body had a margin of 8px. However, my login page (component) already had a background that covered the entire page, and our component was rendered in the div of App.vue. So, would adding a style to the div in App.vue with a margin of 0 solve the problem?
Therefore, I added a style to the div in App.vue, setting its margin to 0, and successfully achieved the desired result.
<template>
<div id="app" style="margin: 0px;">
<router-view/>
</div>
</template>
Since all the routes will eventually be loaded into index.html, adding a style with a margin of 0 to the body in HTML can also solve this problem.
Parameter passing issue#
First, let's talk about the ways to pass parameters between pages. One is using query, and the other is using params.
Passing and receiving parameters using query
Passing parameters:
this.$router.push({
path: '/Home',
query: {
id: res.objectId,
}
})
Receiving parameters:
this.$route.query.id
Passing and receiving parameters using params
Passing parameters:
this.$router.push({
name: 'Home',
params: {
id: res.objectId,
}
})
Receiving parameters:
this.$route.params.id
When passing parameters using params, the path in push should only be the name, and params can only be accessed through the name in the route. If the path is written instead of the name, the receiving parameter page will display undefined.
Also, query is equivalent to a GET request, and the parameters can be seen in the address bar after the jump, while params is equivalent to a POST request, and the parameters cannot be seen in the address bar.
Okay, now I know how to pass parameters when navigating between pages. But when I eagerly passed an object, the received data was: '[object object]'. Huh? I checked its type, and it was a String...
Where is my object?
I found the solution on Google. Before passing the object, I converted it to a JSON string:
JSON.stringify(res);
Then, in the receiving page, I converted the JSON string back to an object:
JSON.parse(this.$route.query.res)
About v-bind and v-model#
These two things often appeared when I was rushing to complete this project, and they often confused me because they both involve data binding.
v-bind
v-bind can only achieve one-way binding, from model to view, and cannot achieve two-way binding.
It can be used to bind text:
<p>{{message}}</p>
<p v-bind="message"></p>
It can also be used to bind attributes:
<img v-bind:src="res">
v-model
v-model can achieve two-way binding, but it has a limitation that it can only be used in forms.
Binding text:
<input type="text" v-model="val" />
Binding radio buttons:
<input type="radio" value="one" v-model="radioResult" />
<input type="radio" value="two" v-model="radioResult" />
In this case, the value of radioResult will change to "one" or "two" depending on which radio button is clicked.
Clicking on an image to change the image#
This functionality was a bit tricky for me. At first, I couldn't wrap my head around it, but after seeing how others implemented it, I thought it was brilliant...
First, we write an image tag and a file selection tag, and add a click event listener to the image tag:
<img v-bind:src="icon" @click="selectIcon" class="icon">
Then, we need to hide the file selection tag by setting the display style to none. We also register a reference using the ref attribute, which allows us to access it in the method, and set the change event. If we need to select multiple files, we can set the multiple attribute:
<input type="file" ref="btn_file" @change="getFile" style="display:none">
At this point, we can only see the image but not the file selection button. In the method triggered by the image click, we use $refs to reference our file selection button and trigger it:
selectIcon: function(){
let selectFile = this.$refs.btn_file;
selectFile.click();
}
Now, our file selection will be triggered, and when we select an image, the change event will be triggered:
getFile: function(){
this.file = event.target.files[0];
// Check the selected file format
if(this.file.type!="image/png"&&this.file.type!="image/bmp"&&this.file.type!="image/jpeg"&&this.file.type!="image/jpg"){
window.alert("Only support png, bmp, jpeg, jpg files");
return;
}
// This method returns a DOMString containing a URL representing the object given in the parameter.
this.icon = window.URL.createObjectURL(this.file);
}
To restrict the file upload types, you can also add the accept attribute to the tag, like accept="image/gif, image/jpeg".
If you don't want to restrict the image format, you can write it as: accept="image/*".
However, it is not recommended to use the accept attribute because it may respond slowly or not be supported in some browsers, and sometimes it still allows selecting files outside the specified format. Validation should be done through JavaScript or on the backend server.
Using components in other components and passing data#
When I was working on the homepage of the project, I needed to display different pages on the right side by clicking on different items in the sidebar. So, I thought of using different child components to achieve this.
After writing a component, I first had to import it into the current component:
import selectClass from '.../components/selectClass'
Then, declare it in the components:
components: {
selectClass
},
Declare it in the data:
data(){
return{
···
selectClass:'selectClass',
···
}
}
And then, use the is attribute to include it where needed:
<div :is="contentView" ></div>
Next, I needed to pass data from the parent component to the child component. There are several ways to pass data, and I chose props for this case.
By using v-bind, we can bind dynamic props to the data in the parent component. When the data in the parent component changes, the child component will also change:
<div :is="contentView" v-bind:objectId="objectId"></div>
Then, in the child component, we can access it using props:
<script>
export default{
props:['objectId']
data(){
return{
}
}
},
······
</srcipt>
Now, we can use this.objectId in the child component to access the parameter passed from the parent component.
2. Finally#
Because this was completed in three days (it had to be submitted), I am quite satisfied with my first project using Vue.js (hehe). But from the current perspective, there are still many things that can be optimized. I should take advantage of the momentum and dive deeper into understanding before learning other things. Also, I am not very proficient in CSS styling, so just looking at it is not enough. Actually writing it myself can help me encounter many pitfalls. I shouldn't be complacent.
This final assignment can be said to be a case of a slacker being forced to operate.