Project warehouse address: github.com/konglingwen…

Project online address: http://123.57.204.48:5000

background

Since I learned Vue, I have tried my best to use Vue to realize all the scene use cases that can be solved with Vue. There is no complete project development process for use case requirements alone, and there is a limit to what can be learned from them. Before this, I used Vue to do vue-Music’s mobile music player project and Vue-bytedanceJob (reconstructing the official recruitment website of a unicorn Internet company). I didn’t use Vue to wade into more complex business scenarios on the Web side.

In order to find a project practice, I began the search off the lot, when he saw the https://github.com/ustbhuangyi/vue-sell project, feeling the business scenario is the mobile terminal applications have no contact with, Therefore, I reconstructed the application based on its UI and functions with my own knowledge system and technology stack. In less than half a month, I completed the first COMMIT submission and put the project into operation. This article analyzes the development process and pits of the project from some aspects of application functions and technology implementation.

Project screenshots





Project technology stack

  1. The front end
    • vueDevelop the project core framework
    • axiosHTTP request module
    • lib-flexibleMobile terminal screen adaptation scheme
    • better-scroll 仿IOSEffects scroll library on the mobile side
    • normalize.cssThe third partycssStyle initializes the module
    • es 6/7The next generationjavascriptgrammar
  2. The back-end
    • expressBuild the server application core framework
  3. The development of
    • vue-cliThe project initializes scaffolding
    • vue-devtoolsProject development environment debugging tool
    • vscode chrome git macbookpro
  4. The deployment of
    • Code managed repository Github.com/konglingwen…
    • Online address 123.56.124.33:5000

Application functions

  • Commodity page

    • The linkage effect of commodity classification navigation and commodity list
    • Click the menu of commodity classification to display the list information of corresponding commodities
    • Add/RemoveGoods to cart
    • Click on the product to enter the details page
    • Add items to cart animation effect
    • Page scroll to the corresponding product category title top effect
  • Comments on the page

    • Comprehensive comment information rendering
    • Toggle the comment filter button to display the corresponding information
    • Choose to showWhether there is a comment on the content
  • Merchants page

    • Merchant store information display
    • Collection of shops
    • Business real picture withbounceSliding display of effects
  • Application of the head

    • Click to show details
    • Bulletin information is dynamically displayed in scrolling mode
  • The shopping cart

    • Different states are displayed according to the number of goods
    • Shopping cart list
    • Pay the popup window
    • Empty shopping cart
    • Add/delete items
  • Applied local optimization

The bounce effect refers to the effect that occurs when a page is rolled to an endpoint in an application and continues to slide. A common scenario is the slide effect of an IOS application

Function of the difficulty

Product navigation and content left and right linkage effect

Results demonstrate

Complete component code point github.com/konglingwen… .

Train of thought

Since the item navigation and content are two separate scroll containers, how do you activate the navigation items associated with a target content block when scrolling to it? We know that the navigation item list and the content list are arranged in the same order. If we can calculate the index of the content scroll position in the corresponding interval block, we can also get the target index that the navigation list should activate. Then we can use the idea of Vue data-driven view to achieve all this.

The container’s left and right linkage effect means that when the container scrolls to the target content, it activates its associated navigation menu item and scrolls to the visible area.

Logic implementation

Found to activate the target of the first step in the navigation items indexed content with the needs of each category in the vertical position of the container stored (to find the activation index of target to provide comparative object), as a result of the list when dynamic rendering, so here need to wait for all the data has been rendered to operate, after the completion of the following directly on demo code!

Template section

<template>/* Only part of the code is shown here */<ul class="foods-list">
          <li ref="foodsGroup" class="foods-group" v-for="(item,index) in data" :key="index">
            <dl class="foods-group-wrapper">
              <dt :class="{fixed:currentIndex===index}" class="foods-group-name">{{item.name}}</dt>
              <dd
                class="foods-group-item"
                v-for="(food ,key) in item.foods"
                :key="key"
              >
                 {{food.name}}
              </dd>
            </dl>
          </li>
        </ul>
</template>
Copy the code

Script part

 
export default {
    data(){
      return {
          currentIndex: 0.// Index activated by navigation item
          currentFood: {},
          data: [].sectionHeight: [0].// The first height block coordinate 'y' value is' 0 '
          / / rendering after the completion of the value of ` [0128 1145 9161 2200 0256 5295 2357 4443 0227 6] `}},created() {
        request
          .get("/goods")
          .then(response= > {
            this.data = response;
          })
          .then(() = > {
            setTimeout(() = > {
              const sections = this.$refs.foodsGroup;
    
              sections.reduce((prevTotal, current) = > {
                const sectionHeight = prevTotal + current.clientHeight;
                this.sectionHeight.push(sectionHeight);
    
                return sectionHeight;
              }, 0); }); }); }}Copy the code

Given the y coordinates of each item block, the next step is to register the scroll event of the container element. In the callback function, we obtain the value of currentIndex by finding the real-time scroll position of disanceY between two adjacent elements in the sectionHeight array

<template>
    <div>
        <! -- Navigation menu -->
         <scroll class="menu">
            <ul class="menu-list">
              <li
                @tap="selectMenu(index)"
                class="menu-item"
                :class="{selected:currentIndex===index}"
                v-for="(item,index) in data"
                :key="index"
              >
               <span>{{ item.name}}</span>
              </li>
            </ul>
          </scroll>
          
        <! -- Product content -->
        <scroll ref="foodsScroll" @scroll="onFoodScroll" class="foods">
        <! -- Omits the code for the product content template -->
        </scroll>
    
    </div>
</template>

Copy the code
export default {

    // Omit other code here
    
    methods: {onFoodScroll({ x, y }) {
          const distanceY = Math.abs(Math.round(y));
          for (let index = 0; index < this.sectionHeight.length; index++) {
            if (
              distanceY >= this.sectionHeight[index] &&
              distanceY < this.sectionHeight[index + 1]) {this.currentIndex = index;
            }
          }
        }
    }
}
Copy the code

Complete component code point github.com/konglingwen… . Since the layout containers on the left and right sides are page scrolling based on the Better-Scroll implementation, we need to listen for the Scroll events provided by Better-Scroll instead of the browser’s native scroll events. Look at the Better Scroll event API point here.

Add/remove items to cart

Effect of screenshots

Full code github.com/konglingwen…

Train of thought

Adding goods to the shopping cart is a multi-scene function. Since the shopping cart function here is a multi-page linkage effect, the real-time change of the quantity of goods in the shopping cart also needs to be synchronized to the product content page and the product details page. From function mapping to javascript language data structure level, it is not difficult to think of object reference passing as the underlying architectural idea to implement this functionality, so let’s implement it.

implementation

In order to count the quantity of goods. The first step is to add a count attribute to each commodity information object with a default value of 0. The added object looks like this

{"count": 0, // this variable is used to store the quantity added to the cart "name": "oldPrice": 10, "oldPrice": "", "description": "salty porridge ", "sellCount": 229, "rating": 100, "info": "A bowl of rice porridge with preserved eggs" Ratings ": [{"username": "3******b", "rateTime": [{"username": "3******b", "rateTime": 1469261964000, "rateType": 1, "text": "", "avatar": "http://static.galileo.xiaojukeji.com/static/tms/default_header.png" } ], "icon": "http://fuss10.elemecdn.com/c/cd/c12745ed8a5171e13b427dbc39401jpeg.jpeg?imageView2/1/w/114/h/114", "image": "http://fuss10.elemecdn.com/c/cd/c12745ed8a5171e13b427dbc39401jpeg.jpeg?imageView2/1/w/750/h/750" }Copy the code

Since each item has a quantity selector that can be added to the shopping cart, we designed an object type props named foodInfo for the item selector component so that we could manipulate the count property of foodInfo to synchronize data when increasing or decreasing the number of items.

/components/food-picker.vue component code

<template>
  <div class="food-picker" @click.stop>
    <div class="reduce-wrapper" @click="reduce">
      <i class="iconfont reduce"></i>
    </div>
    <div class="counter">{{foodInfo.count}}</div>
    <div class="add-wrapper" @click="add">
      <i class="iconfont add"></i>
    </div>
  </div>
</template>
<script>
export default {
  name: "food-picker".props: {
    foodInfo: {
      type: Object.default: () = >({})}},methods: {
    reduce() {
      if (parseInt(this.foodInfo.count) > 0) {
        this.foodInfo.count--; }},add() {
      this.foodInfo.count++; }}};</script>
<style lang="less" scoped>
.food-picker {
  min-width: 180px;
  max-width: 200px;

  display: flex;
  align-items: center;
  width: 100%;
  justify-content: space-between;
  .iconfont {
    color: #00a0dc;
    font-size: 38px;
  }
  .counter {
    // margin: 0 20px; }}</style>
Copy the code

Next target

Based on the functions already realized, the data of the entire application is stored in json file format on the server, and there is no API interface for adding, deleting, modifying and searching on the server. In the next step, I plan to make the management background and server API to manage the data of the front-end page, so that the data of all modules can be configured, so that the data rendered by the front-end is also dynamic, which can integrate the three ends into one project and meet the needs of the current Web full-stack development scene.

conclusion

By actually developing such a complex interactive application, I have gained an in-depth understanding of the use and use of Vue in real business scenarios. I have deeply understood the idea of Vue’s data-driven view change, mastered the process of componentized development projects, and also felt the convenience brought by it, so as to build a bridge for my next medium and large projects.

support

If this program helps you to learn, please you to point a stargithub.com/konglingwen… . Also hope you continue to pay attention to my dynamic github.com/konglingwen… With your support, I will be motivated to open source more interesting projects.

Welcome to like and comment, thank you!

This article belongs to the author’s original, reproduced reference please indicate the source, thank you!