Why write this article? The purpose of the title is also very clear, is to record my learning process. It will also be easier to identify the shortcomings and highlights of the project when you review it later. Thanks to the VNode community for the API.

You can also scan the following TWO-DIMENSIONAL code preview online project:





Qr code

I. Demand analysis

Before making a project, I think we should first make a summary of the functions and write the project according to the requirements, so as to achieve a definite target.

So I wrote the requirements of the project according to the API, as shown below:





CNode function requirement analysis

2. Technology stack

The technology stack used in this project is the standard Vue family bucket, namely:

Vue2.0: Build projects, part of the underlying framework. Vue-router: changes the hash value to change the route of the page structure. Vuex: Indicates an official Vue status management mode. Axios, vue-axios: HTTP request module. ES6: A new popular Javascript syntax for production applications. Sass: CSS precompiler. Webpack: Used to package projects.Copy the code

3. Project initialization

Using the initial tools provided by vue-CLI, run the following code:

# install vue-cli
$ npm install --global vue-cli
# create a new project using the "webpack" template
$ vue init webpack my-project
# install dependencies and go!
$ cd my-project
$ npm install
$ npm run devCopy the code

At this point, open http://localhost:8080/ to access the initialized page.

Iv. Project preparation

Note: details can be viewed from the source code.

After initialization, we can start writing the project. The code is divided into four parts, namely: Components, VUE-Router, VUEX and Common (for placing common styles, fonts and common function codes). Before the project is written, constrained by the dependencies to be installed, the code is as follows:

Install vuex, VUE-Router, axios, Vue-axios $NPM install vuex vue-router axios vue-axios --save # NPM install node-sass sas-loader --save-devCopy the code

1.common Public file

This includes styles, fonts, and utils (including time formatting and cookie access).

2. com ponents components

There are currently 14 components in total, including:

AboutMe
Article
ArticleCard
BackBar
BottomBar
Content
Loading
Login
MessageCard
MyCollect
navBar
Notification
Publish
UserDetailCopy the code

See the project catalog below for details.

3. Configure vue-router routes

Through routing, it is divided into seven pages: ① home page ② article details page ③ user details page ④ User login page ⑤ Publish article page ⑥ User collection page ⑦ my notice page

5. Vuex: Indicates the status management mode

Status management is divided into six modules: Content (home page), article (article page), Navbar (navigation bar), User (user details), login (user login status) and Notification (notification).

5. Project Catalog

.├ ─ Build // WebPack Set │ ├─ Build.js │ ├─ Check-versions.js │ ├─ dev-client-js │ ├── utils ├ ─ ─ vue - loader. Conf. Js │ ├ ─ ─ webpack. Base. Conf., js │ ├ ─ ─ webpack. Dev. Conf., js │ └ ─ ─ webpack. Prod. Conf., js ├ ─ ─ the config / / Project development and packaging set │ ├ ─ ─ dev. The env. Js │ ├ ─ ─ index. The js │ └ ─ ─ the prod. The env. Js ├ ─ ─ docs/address/static resources │ ├ ─ ─ index. The HTML │ └ ─ ─ the static │ ├ ─ ─ CSS │ │ │ └ ─ ─ app. D99bca81a0eef77c7e0d8c70f520707c. CSS ├ ─ ─ fonts │ │ ├ ─ ─ iconfont. 8553 d3c. The vera.ttf │ │ └ ─ ─ iconfont. B29ac85. The eot │ ├ ─ ─ img │ │ └ ─ ─ iconfont. D4553f2. SVG │ └ ─ ─ js │ ├ ─ ─ app. Cb09e437ae0bec6205b9. Js │ ├ ─ ─ the manifest. Aa9548ef140031379c30. Js │ └ ─ ─ vendor. F3d0844a66c0c2cabe0b. Js ├ ─ ─ SRC / / project file location │ ├ ─ ─ App. Vue / / component total entry │ ├ ─ ─ common / / gm file │ │ ├ ─ ─ │ fonts / / fonts │ │ ├ ─ ─ iconfont. Eot │ │ │ ├ ─ ─ iconfont. SVG │ │ │ ├ ─ ─ iconfont. The vera.ttf │ │ │ └ ─ ─ iconfont. Woff │ │ ├ ─ ─ style / / style │ │ │ ├ ─ ─ Animation. SCSS / / animation │ │ │ ├ ─ ─ base. The SCSS / / basic styles │ │ │ └ ─ ─ icon. The SCSS / / iconfont font style icon │ │ └ ─ ─ utils / / tools function │ │ ├ ─ ─ Cookies. Js / / cookie access and delete │ │ └ ─ ─ timeFormat. Js / / formatting time function │ ├ ─ ─ the components / / all of the components │ │ ├ ─ ─ AboutMe / / about │ │ │ └ ─ ─ AboutMe. Vue │ │ ├ ─ ─ the Article / / Article details page │ │ │ └ ─ ─ the Article. The vue │ │ ├ ─ ─ ArticleCard / / Article list of single post CARDS │ │ │ └ ─ ─ ArticleCard. Vue │ │ ├ ─ ─ BackBar / / at the top of the back bar (return to the home page and back) │ │ │ └ ─ ─ BackBar. Vue │ │ ├ ─ ─ BottomBar reply / / at the bottom of the column (also includes collecting and editing files) │ │ │ └ ─ ─ BottomBar. Vue │ │ ├ ─ ─ the Content / / homepage │ │ │ └ ─ ─ content. vue │ │ ├ ─ ─ Loading / / being loaded components │ │ │ ├ ─ ─ Loading. The vue │ │ │ └ ─ ─ Loading. The SVG │ │ ├ ─ ─ the Login / / Login │ │ │ └ ─ ─ the Login. The vue │ │ ├ ─ ─ MessageCard / / a single notice details card │ │ │ └ ─ ─ MessageCard. Vue │ │ ├ ─ ─ MyCollect / / My collection page │ │ │ └ ─ ─ MyCollect. Vue │ │ ├ ─ ─ Notification/page/notify │ │ │ └ ─ ─ Notification. Vue │ │ ├ ─ ─ the Publish / / published articles and Publish updates page │ │ │ └ ─ ─ the Publish. Vue │ │ ├ ─ ─ UserDetail / / the user details page │ │ │ └ ─ ─ UserDetail. Vue │ │ └ ─ ─ navBar / / home page at the top of the navigation bar │ │ ├ ─ ─ │ ├─ ├─ ├─ ├─ ├─ cnodejs_light. SVG │ ├─ ├─ ├─ cnodejs_light. README. The pictures in the md │ │ ├ ─ ─ CNode 237 � � \ \ 212\203 � � \ 234\200 � \ � 202 � \ 210\206\236\220. PNG │ │ └ ─ ─ QR - Code. PNG │ ├ ─ ─ the router / / routing setting │ │ └ ─ ─ index. Js │ └ ─ ─ store / / state management │ ├ ─ ─ modules │ │ ├ ─ ─ the article / / article details page │ │ │ ├ ─ ─ the article - mutation - types. Js │ │ │ └ ─ ─ article. Js │ │ ├ ─ ─ the content / / homepage │ │ │ ├ ─ ─ the content - mutation - types. Js │ │ │ └ ─ ─ content. js │ │ ├ ─ ─ the login / / login page │ │ │ ├ ─ ─ the login - mutation - types. Js │ │ │ └ ─ ─ the login. The js │ │ ├ ─ ─ navbar / / home page navigation │ │ │ ├ ─ ─ navbar - mutation - types. Js │ │ │ └ ─ ─ Navbar. Js │ │ ├ ─ ─ notification/page/notify │ │ │ ├ ─ ─ notification - mutation - types. Js │ │ │ └ ─ ─ notification. Js │ │ └ ─ ─ user / / User details page │ │ ├ ─ ─ the user - mutation - types. Js │ │ └ ─ ─ the user. The js │ └ ─ ─ store. Js / / state management total entry ├ ─ ─ the README. Md ├ ─ ─ index. The HTML └ ─ ─ package.jsonCopy the code

6. Problems encountered in the process

This project is my first complete mobile phone and PC compatible project, about the article. The whole project, encountered a lot of bugs, natural harvest is also a lot. The summary is as follows:

1. Long words stretch out of bounds, resulting in a wider viewable area.

Word-wrap: break-word; Achieve interruption effect.

2. When entering the article the second time, there will be residue (not yet solved).

Solution: The hook function beforeRouteEnter is used to obtain data. If the data fails to be obtained, the Loading page is displayed. After the Loading is complete, the article details page is displayed to solve this problem.

3. When you return to the home page, you cannot retain the original state (not yet resolved).

Solutions:

① This method is easy to fix the height of the solution. (Specific method: Vuex and VUE-Router hook functions are used to solve this problem, that is, through the scroll event to dynamically save the scrollTop straight, when the beforeRouteEnter of the route starts, the value of the scrollTop will be restored.)

② If there is no fixed height, the keep-alive component of Vue is directly used to preserve the status of the component.

4. How to do the loading animation?

Solution: I used CSS3 to draw a graphic, but found it too ugly, so I used Iconfont SVG and added animation.

5. How to implement lazy loading of the main page article list?

Solution: Determine the total height of the slide – the distance from the top of the slide <= the available height of the screen, which is the following formula:

 document.documentElement.offsetHeight - window.scrollY
 <= window.screen.heightCopy the code

There’s a bug that happens here, and if you keep sliding, it’ll load multiple times. You can fix this bug by adding a state indicating that it is being loaded at this point (see the source code for details).

6. How do I go back to the top animation?

Solution: Divide the current window.scrollY into n parts and set a timer. Every m seconds, scroll up one part of the height and terminate the timer when window.scrollY >= 0. (where m and n are arbitrary numbers, set according to the situation)

7. How to control the display of the page being loaded?

Workaround: Because loading data is asynchronous, you can control the display of the loaded page by changing a state like isLoading (with your own name) before and after loading.

8. How do I set the login function?

Solution: Because the official only provides access-token, so you can store this value and some user-related values in document.cookie, I wrote a cookie tool function separately, the code is as follows:

** * Created by Jerryshen on 2017/7/15. ** * Created by Jerryshen on 2017/7/15. * Set single, get All, Get Single, Delete All, */ export function setCookie (name, value, exdays = 30) { var time = new Date() time.setTime(time.getTime() + exdays * 24 * 3600 * 1000) var expires = 'expires=' +  time.toGMTString() document.cookie = name + '=' + value + '; ' + expires } export function getAllCookies () { if (document.cookie === '') { return {} } const cookies = document.cookie.split('; ') const newCookies = {} for (let i = 0; i < cookies.length; i++) { let cookie = cookies[i].trim() const splitCookie = cookie.split('=') newCookies[splitCookie[0]] = splitCookie[1] } return newCookies } export function getCookie (name) { const cname = name + '=' const cookies = document.cookie.split('; ') for (let i = 0; i < cookies.length; i++) { let cookie = cookies[i].trim() if (cookie.indexOf(cname) === 0) { return { success: true, cookie: { name, value: cookie.split(cname)[1] } } } else { return { success: false, cookie: { name, value: undefined } } } } } export function deleteAllCookie () { document.cookie += '; expires=Thu, 01 Jan 1970 00:00:00 GMT' } export function deleteCookie (name) { document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT` }Copy the code

9. How to convert time in API to =>.. Years ago,.. Months ago,.. Days ago wait, what about this type of format?

Solution: I wrote a formatted tool function, the code is as follows:

Export default function timeFormat (date) {// Get the current time and the date object const nowTime = new date () const inDate = new Date(Date) if (nowtime.getYear () -indate.getYear () > 0) {// Year difference > 0, Return '${nowtime.getFullYear () -indate.getFullYear ()} else if (nowtime.getMonth () -indate.getMonth () > 0) {return' ${nowTime.getFullYear() -indate.getFullYear ()} else if (nowtime.getMonth () -indate.getMonth () > 0) { // Month difference > 0, Return '${nowtime.getMonth () -indate.getMonth ()} months ago'} else if (nowtime.getDate () -indate.getDate () > 0) {// Date difference > 0, Return day return '${nowtime.getDate () -indate.getDate ()} day before'} else if (nowtime.gethours () -indate.gethours () > 0) {// Hour difference > 0, ${nowtime.gethours () -indate.gethours ()}} else if (nowtime.getminutes () -indate.getminutes () > 0) {return '${nowtime.gethours () -indate.gethours ()}} else if (nowtime.getminutes () -indate.getminutes () > 0) { Return '${nowtime.getminutes () -indate.getminutes ()} before'} else {${nowtime.getminutes () -indate.getminutes ()} before '} else {${nowtime.getminutes ()} before '} else { Return '${nowtime.getseconds () -indate.getseconds ()} seconds before'}}Copy the code

10.BUG: Scroll event of the home page is still triggered when entering other routes.

Mounted is used for the lifecycle hook, so scroll event will still exist when entering other routes. Therefore, the lifecycle hooks of beforeRouteEnter and beforeRouteLeave are used to mount scroll events when loading a route and unload Scroll events when leaving a route respectively. This prevents lazy loading of homepage content from being triggered all the time.

11. How to return to the main page by clicking back after jumping to the details page of a new article or update?

Solution: now preliminary is used, route jump, jump to the home page first, then to the article details page, and then press back, will return to the home page.

12. How to click the reply button on the right of the comment, add the @ message and focus the input box?

Solution: VuEX can record relevant information in real time, and judge whether to focus by value of watch input box.

13. There is a strange bug: in ios, if the window. ScrollY will keep the window.

Solution: As a last resort, in the beforeRouteEnter hook, add a timer to the function that binds the scrolling event and make it bind after 100ms, so window.scrollY becomes the same value as before.

Seven, afterword.

I novice a, but also in the pain of looking for a job T_T. If you find bugs in the code, you can communicate with me through comments and learn from each other! Have any good idea, can also put forward, discuss together.