Summary of the Project of Developing Imitation Tourism Station WebApp with Vue (PART I)

What needs to be said and said has been said in the previous chapter. Thanks to some students in the comments section ~ very encouraging me, but the next chapter is estimated to have no, this summary, the next chapter may be the summary record of the learning road after.

There is something to be said

Friends who are new to Vue should reap the rewards. This project is also the second Vue project made by MOE, using scaffolding tools (VUE-CLI2.x non 3). If you have time to look at it, if you have any bad writing, please give us more guidance! ~

A less low-level use of Vuex in the project

Because this is just a summary of operations/ideas, not step by step to talk about the code, or first give the official website diagram, so that it is convenient to watch:

Assuming that, in scaffolding, we introduce Vuex globally in the same way that routing introduces globally. Create a folder called store and create an index.js script in that folder. Write some Vuex usage logic in store/index.js and import it in main.js. As follows:

Ignore the mosaics for a moment…

In the entry function main.js we introduce:

Now the logic inside index.js

Break up

Taking this project as an example, with the development of the project, the logic in index.js will become more and more complex, so we choose to split it.

So, we create two scripts (state.js and blockroad.js) to store the two pieces of code separately.

Then introduce the following in index.js:

So split finish, concise many.

MapState helper function

In the project, the following figure is used to obtain the data of city in state. Isn’t it a bit long?

Vuex provides a convenient API -> mapState

Used like this:

MapState means I’m mapping the value of the public property in the State field to this computed property.

In this case: map the value of the public property city in state to the calculated property city.

Well, in that case, you can take

To call the calculated property directly:

. MapState ({}/[]) this can be an array or an object. If it’s an array, we’re just going to name the evaluated property city, the same name as the public property.

If it is an object, we can give the calculated property a custom name.

To take one… Example of mapState(object) :

You can also change it here in the current city:

So what we’re doing here is passing an object to mapState, which is essentially mapping the value of the public property city to the evaluated property currentCity.

You can use it like this:

That way it doesn’t have to be complicated.

MapMutations auxiliary function

Using the Vuex API, you can simplify the following code:

Used like this:

What does that mean?

Mutations has a method called changeC2, which maps the changeC2 method in mutations into the changeC2 method of methods in this component in the methods of this component.

. The mapMutations() parameter is also acceptable for []/{}.

Or with… MapMutations make it easier to understand, as follows, and take a test:

(Disorderly little sister ~)

I could write it this way. It’s easier to understand the mapping here.

Getter, the Module

Getter and Module are not used in the project.

Getter

If we want to get a new value based on the value of state by doing some calculation, we can use getters to provide new data and avoid data redundancy. It is also defined in the same way as computed.

A getter can be thought of as a computed property of a store. Just like evaluating properties, the return value of a getter is cached based on its dependency and is recalculated only if its dependency value changes.

A Getter accepts state as its first argument and may also accept other getters as its second argument. There is property access (store.getters), there is method access, and there is a mapGetters helper function (this helper function is primarily a mapping, mapping the getters in the store to the computed properties of the local component). Examples given by the official documentation are also easier to understand, so you can look at the documentation yourself.

Module

Vuex allows us to split the Store into modules. Each module has its own state, mutation, action, getter, and even nested submodules.

When your application becomes very complex, you can use the Module to keep the Store object from becoming too bloated.

I think the specific application of Module can only be proficiently practiced in complex projects. At present, I dare not write it down easily, so I will write it down for the time being.

Use keep-alive to optimize performance

We can see this in XHR for the developer tool Network

Every time we switch routes (from the Home component page to the City component page or vice versa) we send ajax request data.

In this case, ajax data is requested repeatedly, because every time a route is switched to a component, the hook function of that component needs to be reexecuted. If the component has an Ajax request in the mounted hook, the switch will be performed every time. This is bad performance.

This can be optimized using the built-in Keep-alive tag of Vue.

In the global root component app.vue

Represents the component that displays the current route, and by adding the built-in VUE keep-alive tag to this, you can achieve this:

After the contents of my route are loaded once, the contents of my route are put into memory, and the next time I load the contents of this route, I just need to fetch the previous contents out of memory.

At this point, no matter how many times you switch routes, there are only two Ajax data requests left.

Because the keep-alive tag is used, the new life cycle functions activated (when the Keep-alive component is activated) and deactivated (when the keep-alive component is disabled) are available.

After the route switch, ajax data is no longer requested because the component content is retrieved from the inside and is no longer recreated. The mounted hook function is no longer executed.

But the Activated hook executes each time the page is switched and displayed again.

At this point, you can use this hook to implement a requirement:

When, after which city list page can choose to click on the routing switch back to the Home page, the page display of data is the data of the city (meaning that the ajax request only the corresponding city Home component data) of the page, and then if the list page, select the and in the Home page of the same city, will not send an ajax request new data.

Previously, ajax requests were made directly like this:

In fact, you should send an Ajax request with a parameter. This parameter should be the public data in Vuex. That is, when you click on a city, this parameter is the name of the city.

How to include parameters in the request?

Append the requested connection with? = Parameter data

Such as:

Try it on a web page. The parameters to send are below

The idea to realize the requirements is as follows:

Each time the page is displayed again (activated hook function triggers) we determine whether the city on the page is the same as the city on the previous display and send an Ajax request if it is different

Then we set an empty string lastCity (as an intermediate cache value for judgment)

Then, when the page is mounted, we give it the city data of the current page.

Then, when the page is updated, check whether the last value of this.lastCity is the same as the updated value of this.city. If it is not, a new Ajax request is sent, requesting data for the corresponding city; if it is, no ajax request is sent.

At this point, the new keep-alive lifecycle hook function and the lastCity cache value will do the trick.

Details page wants to record things

The main idea of realizing gallery component function

Let’s take a look at a GIF to illustrate what this looks like:

That’s it. This is the gallery. There’s a rotation on the top, page numbers on the bottom.

Since this is not just for one page, but probably for many pages in the future, write a global common component called gallary.vue.

You need to use this common component in a component of the detail page called banner.vue

Gallary fills the screen with fixed.

Using the Flex layout, center the following Wrapper area vertically

Then use vue-awosome-swiper, a third-party plugin, to place two images first

Then define a width and height of 100% for that.wrapper. So if I write it like this, width has a width of 100% and then height is 100% for the width of the width, so I’ve defined the height of 100% to mean that the height is equal to the width of the width to mean that it’s a square.

This page:

We scaled the image to fit the square and removed the background color from the Wrapper. Now the two images will rotate normally:

Then add the page number, which is controlled by the button area and configuration parameters of the plug-in. Add the button area code first:

Vue-awesome-swiper is based on Swiper. The configuration parameters such as pagination can be found on swiper’s official website.

Let’s go to the website and see if we can find the parameters that set our page number requirements. :

This shows that the page-turning style of this page corresponds to the fraction in paginationType in this PaginNation.

Now to configure the parameters, first add :options=”swiperOption” to swiper.

And then configure it in data. First, configure the button area:

The paginationType ‘fraction’ fraction is configured

It is available now, but in small places, the censorship element is visible

The original frame style, by reviewing the elements to find out where is the absolute location.

So let’s just do bottom-1REM, right?

That’s definitely not going to work…

There is a pitfall here, when the code feels right, but the page is not as expected, it is time to review the elements again… The review element found that the plug-in component had a swiper-container with overflow: Hidden defined in it.

So we just need to change the style by going through the scope in the gallery component

The gallery logic is easy to skip, but there is one pit worth mentioning.

All is well in the gallery’s own component gallary. Vue, but gallary is a public component that will be introduced in the Banner. Vue component of the detail page.

The problem is that when we click on the page corresponding to the Banner component and click on the page corresponding to the Gallary component, the rotation plugin will have a problem calculating the width and height. The GIF below looks like this:

To solve this problem, add these two configuration parameters to gallary’s multicast plug-in configuration parameters

Adding these two parameters means:

The swiper plugin automatically refreshes and recalculates its width and height whenever it detects a change in my element or its parent element.

Through this self-refresh, you can solve the problem of calculating the width and height of the round – cast plug-in. (These configuration parameters can be found on swiper’s official website.)

Header block fade out effect

See a GIF.

Just to mention this, as the finger slides down, the div attractions detail box logic gradually becomes clear and continues to be clear.

The piece that is becoming clear is fixed with a div box.

logic

At the beginning, v-show does not display the div box and makes the opacity of the div box 0. Check the global Scroll (window.onscroll) event in the activated hook function (check the state of the scroll bar, which triggers the Scroll event once the scroll bar moves). When the Scroll event is triggered, a method is executed in which the logic is written. The logic of writing is: When the scroll bar to slide forward 60 px outside let this div box v – show parameter to true and by formula let opacity = document. The documentElement. The scrollTop as / 140 to make the div box slipping dynamic resolution higher and higher, Opacity = opacity > 1? 1: opacity.

Is obvious: the document. The documentElement. ScrollTop mean position of the vertical scroll bar for current page.

That works, but there’s an important catch. Unbinding of global events.

Unbinding of global events

In header block logic, we define a global Scroll event in the Activated hook.

Because this is a global event, we can also detect it in other components. This can easily lead to a series of serious hidden bugs.

So we should unbind this component in the header.vue component in the detail:

There is also a deactivated hook that corresponds to a keep-alive reference.

This hook fires when the page is about to be replaced with a new page.

So here we use the Deactivated hook and the removeEventListener function to unbind global events.

The three functions of the name attribute in the component

1. Used when making recursive components

For example, the name of the list component: ‘DetailList’. When a recursive component calls itself in the list component template, it is used as a label (detail-list) call based on the value of name. As follows:

2. This is used when the keep-alive cache is uncached for a page

Suppose you have a detail. vue component whose name is’ Detail’. When you want the keep-alive global component, the page corresponding to the detail. vue component is rerouted to this page instead of fetching the cache value in memory, you can use the name value of the Detail component as follows:

This means that all components except the detail. vue component can have the keep-alive function.

3. Vue-devtools debugging tool

The name of the component shown in the red box above depends on the value of the name property of the component being set.

In dynamic routing, Ajax dynamically retrieves the values of each routing directory

To illustrate the example in the project, note the values in the red box below

In this case, we should obtain the data of parameter ID 0002 in the dynamic route.

After setting this parameter, the corresponding parameter will be stored in the variable ID in the dynamic route.

On each request you want to bring this ID to the back end, you can write:

Writing a

You can now see in the XHR of the network that we sent the request to the back end with the ID attached

Write two

(we put the parameter in params)

There’s still a problem, and I want to summarize this point step by step

Setting up a dynamic route, just adding a dynamic id parameter does not automatically make the page also dynamically display data, dynamic display data has to rely on Ajax request data.

Currently, this component performs ajax requests in mounted hooks and has keep-alive effects. So when the route jumps to id 0003/0004… Page, the component will only fetch from memory the first time it entered a page of that component’s ID. Pages cannot be displayed by ID.

How do you dynamically display data through Ajax requests? There are two ways, both of which are mentioned above.

  • In the first way, when you select a city on the list page, the route automatically redirects to the home page, and the home page displays the corresponding data of the city as recorded here. (Hint: Use the Activated hook to determine if the id of the parameter is equal to the previous ID, and if not, re-execute the Ajax request.)

  • The second of the three roles of the name attribute in the second component already tells us the solution.

These two ways are left for readers to think by themselves. If you can’t figure it out, you can refer to the code in my github warehouse. src/pages/detail/Detail.vue

Route rolling behavior

To see a GIF

This is the effect of redirect pages. Will carry the width and height of the display screen of the current page (home.vue) to the page we jumped to (detail.vue). Cause the phenomenon as shown in GIF above.

So let’s do it this way.

This is known in the official documentation as the scrolling behavior of routes.

We now want to scroll at the top every time the route switches to the next page. Continue with the document.

Copy this code into the route configuration item:

So that’s what we want.

Configuration package

Front and rear end intermodulation

Generally, after the back-end data is written, we will no longer use the data simulated by our own front-end, but to use the data given by the back-end to debug.

To access the data on the server, change target to the server address in the proxyTable under config/index.js (internal IP address or external domain name can be written). If you change pathRewrite, you’ll see where the data is stored on the server.

Real machine test

The front-end project here is started with webpack-dev-server, which by default does not allow IP access to the internal server. Therefore, we need to modify the default configuration items.

To enable webpack-dev-sever to be accessed by IP, configure webpack-dev-sever as follows:

(Seems to have missed a bit… It doesn’t matter….)

Then, when testing the real machine, sometimes you will encounter some bugs that you can’t find when developing on PC and need to consider compatibility. This has to be changed according to the actual situation.

Package online

In vue-cli 2.x, you can execute the NPM run build command in the project directory, and vue’s scaffolding tool will automatically compile and package the source code in the SRC directory to generate code that can be run by the browser. This code is also compressed.

When the package is complete, a dist folder is generated and given to the back-end developer, or the contents of the static folder can be dumped directly into the back-end server root. This is just a basic operation, want to change the access path or what kind of operation, you go to find, you will find ~

conclusion

This article is only the more specific and detailed knowledge and process that I personally think can be summarized and recorded in this project. If you are interested, you can go to IMOOC to support The course of Mr. DellLee ~

There are some places too much code is not convenient to post, want to refer to the code to learn can enter my Github.

I hope I can help you too