Magren

Magren

Idealist & Garbage maker 🛸
twitter
jike

Final project implemented using Vue.

Finally, I have passed the tense and exciting final exams, as well as the defense of three major assignments and two major projects.

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 I needed even when I searched through the books. 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. Following the principle of choosing something easy to write, easy to understand, and with plenty of templates available on Google/Baidu for us to copy, our group chose the Student Academic Management System.

Teacher: "This assignment will not be checked for plagiarism, and you don't need to implement this project. Just write it based on the template I provided."

The impact of the 6000-word requirement was only half as much as I expected. Although my writing skills are not great, I am really good at copy-pasting.

So, I racked my brains to find ways to get through this assignment. But sometimes, when I saw others working hard, I felt anxious and guilty for being lazy. Just 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 for a moment, and then I continued lying on my bed, scrolling through my phone, and smoothly passing this final exam. It's always good to have a backup plan, but the more I think about it, the more frustrated I get.

Somebody has to win, so why not be me?

I also had to do something. I had recently learned about Vue, so I decided to use it as a practice project. That way, even if I failed, I would have a reason for it (self-consolation).

Part 1: Programming for Search Engines#

To be honest, since this was my first time actually getting hands-on experience, I knew I would encounter many challenges. But I didn't expect to face a major obstacle right from the start.

Issue with a white bar at the top of the page#

I started by creating 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 searched on Google and found a lot of CSS property settings (although it was indeed a styling issue). In the end, after tirelessly searching for answers, I found a solution in an unrelated article, which also provided me with some knowledge.

Firstly, index.html is the entry point of the project, and it contains only one div tag in the body, with an id of "app". This id is 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-related content will be rendered in this div, and the content of the router is defined 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 inside App.vue. So, would adding a style to the div in App.vue with a margin of 0 solve the issue? I added the 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 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.

Issue with passing parameters#

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 filled with 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. Additionally, it should be noted that query is equivalent to a GET request, and the parameters can be seen in the address bar after the redirect, while params is equivalent to a POST request, and the parameters cannot be seen in the address bar.

Now that I know how to pass parameters between pages, when I passed an object with anticipation, I received the data as '[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 into a JSON string:

JSON.stringify(res);

Then, in the receiving page, I converted the JSON string back into an object:

JSON.parse(this.$route.query.res)

About v-bind and v-model#

These two things frequently appeared while I was rushing to complete this project, and I often confused them because they both involve data binding.

v-bind

v-bind can only achieve one-way binding, from the model to the 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. It can bind text:

<input type="text" v-model="val" />

It can bind 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" based on the selected radio button.

Clicking on an image to change the image#

This functionality was a bit tricky, and at first, I couldn't wrap my head around it. But after seeing how others implemented it, I thought it was brilliant...

First, we create an image tag and a file selection tag, and add a click event listener to the image:

<img  v-bind:src="icon" @click="selectIcon" class="icon">

Then, we need to hide the file selection tag by setting its display style to none. We also use the ref attribute to register a reference, which allows us to call it in methods, and set the change event. If we need to allow multiple selections, 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, for example: 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 formats. It is better to validate through JavaScript or on the server-side.

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 based on the different menu items clicked on the sidebar. So, I thought of using different child components on the right side by clicking on the menu items. After creating a component, I first had to import it into the current component:

import selectClass from '.../components/selectClass'

Then, declare it in the components section:

components: {
  selectClass
},

Declare it in the data section:

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 to use props here. By using v-bind, we can bind dynamic props to the parent component's data, so 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 use props to retrieve the data:

<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.

Part 2: Conclusion#

Since this was something I completed in three days (and had to submit), I am quite satisfied with my first project using Vue (hehe). However, there are still many areas for improvement, and I should take advantage of the momentum to delve deeper and learn more before moving on to other things. Also, I am not very proficient in CSS styling, and it turns out that just looking at it is not enough. Actually writing it yourself can help you encounter many pitfalls and prevent complacency.

This final assignment can be considered as a situation where a slacker was forced to operate.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.