项目实战:supermall

项目实战:supermall,第1张

项目实战:supermall

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

一、划分目录结构?

二、开发步骤

2.1 引入css

2.2  引入vue.config.js和.editorconfig

2.3 项目的模块划分:tabbar=>路由映射关系

2.4 首页开发

2.5 详情页开发

三、项目细节改进

四、nginx项目在windows下的部署


前言

随着vue的学习,实现supermall。


提示:以下是本篇文章正文内容,下面案例可供参考

一、划分目录结构?

二、开发步骤 2.1 引入css

        base.css        normalize.css 2.2  引入vue.config.js和.editorconfig

vue.config.js别名配置

2.3 项目的模块划分:tabbar=>路由映射关系 2.4 首页开发

        2.4.1 navbar的封装

        2.4.2 网络数据的请求

        2.4.3 轮播图

                better-scroll---->2.4.7

        2.4.4 推荐信息

        2.4.5 定位

                position:sticky

                top:44px

        当高度没达到设置高度时,position为sticky,达到后position自动设置为fixed。

        2.4.6 goods:(流行/新款/精选)

        goods:{

                "pop":{ page:0,list:[] },

                "news":{page:0,list:[]},

                "sell":{page:0,list:[]}

}

          2.4.7 Better-Scroll

介绍 | BetterScroll 2.0

侦听position

//默认情况下BScroll是不可以实时的监听滚动位置 
//probe侦测 //0 1:不侦测 
//2:在手指滚动的过程中侦测,手指离开后的惯性滚动过程不中侦测 
//3:只要是滚动都侦测
const bscroll = new BScroll(document.querySelector('.wrapper'), {
    probeType:2,
})
bscroll.on('scroll', (position) => {
    console.log(position);
})

内部可以发生点击事件:

click:true

上拉加载更多:

pullUpLoad:true
bscroll.on('pullingUp',()=>{
    console.log("请求加载更多")
    //发送网络请求,请求更多页的数据
    
    // 等数据请求后,并将新的数据展示出来后
    
    setTimeout(()=>{
        bscroll.finishPullUp()
    },2000)

})

document.querySelector('.wrapper')拿到的元素不准确

解决办法:

ref如果绑定在组件中,通过this.$refs.refname获取到的是一个组件对象

ref如果绑定在普通元素中,那么通过this.$refs.refname获取到的是一个元素对象

高度的计算函数:

height: calc(100% - 93px);

组件的监听:

返回顶部:

this.$refs.scroll.scroll.scrollTo(0,0,500)

        2.4.8  解决首页中可滚动区域的bug

                better-scroll在决定多少区域可滚动时,是根据scrollHeight属性决定的。

                scrollHeight属性是根据放better-scroll的content的子组件的高度

                但是在我们的首页当中,刚开始计算scrollHeight属性时,是没有将图片计算在内的

                所以,计算出来的值是有错误的

                后来图片加载进来之后有了新的高度,但是scrollHeight属性并没有进行更新

                所以滚动出现了问题

        如何解决这个问题?

                监听每一张图片是否加载完成,只要有一张图片加载完成,执行一次refresh()

                如何监听图片加载完成?

                        原生的js监听图片:img.onload = function(){}

                        vue中监听:@load='方法'

                调用scroll的refresh():

                        因为涉及到非父子组件通信,所以选择事件总线(this.$bus)来解决

//vue实例作为事件总线发射监听事件
Vue.prototype.$bus = new Vue()

imageLoad(){
  this.$bus.$emit('itemImageLoad')
}

this.$bus.$on('itemImageLoad',()=>{
  this.$refs.scroll.refresh()
  // console.log('-----');
})
优化:

        因为this.$refs.scroll.refresh()调用太频繁,

对于refresh非常频繁的问题,进行防抖 *** 作:

        防抖:debounce / 节流:throttle

        防抖函数起作用的过程:

                如果直接执行refresh,则需要执行30次                所以将refresh函数直接传给debounce函数中,生成一个新的函数                之后在调用非常频繁的时候,就是用新生成的函数                而新生成的函数,并不会非常频繁的调用,如果下一次执行来的非常快,那么会将上一次取消掉

debounce(func, delay) {
  let timer = null
  return function (...args) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      func.apply(this, args)
    }, delay)
  }
}

        2.4.9  上拉加载更多

       子组件侦听页面监听滚到底部将函数传出到父组件

        父组件根据侦听结果加载更多数据

        但better-scroll内部只会请求一次页面加载更多,故在每次请求完数据后都要执行:

//完成上拉加载更多
this.$refs.scroll.finishPullUp()

        2.4.10 吸顶效果

        必须知道滚动距离达到多少时呈现吸顶效果

        offsetTop

    //组件没有offsetheight属性     
    //所有的组件都有一个$el属性:用于获取组件中的元素     
    this.tabOffsetTop = this.$refs.tabControl.$el.offsetTop     console.log(this.tabOffsetTop)

        但是,如果直接在mounted中获取offsetTop该值是不正确的,

如何获取正确的值?

        监听组件中img的加载完成        

        加载完成后,发出事件,在相应父组件中获取正确的值

问题:动态的改变tabControl的样式时, 会出现两个问题:

问题一: 下面的商品内容, 会突然上移

问题二: tabControl虽然设置了fixed, 但是也随着Better-Scroll一起滚出去了.

其他方案来解决停留问题.

在最上面, 多复制了一份PlaceHolderTabControl组件对象, 利用它来实现停留效果.

当用户滚动到一定位置时, PlaceHolderTabControl显示出来.

当用户滚动没有达到一定位置时, PlaceHolderTabControl隐藏起来

        2.4.11 保持原来的状态:

                让home不要随意销毁:keep-alive

                让home中的内容保持原来的位置:

                        离开时, 保存一个位置信息saveY.

                        进来时, 将位置设置为原来保存的位置saveY信息即可.

                                  注意: 最好回来时, 进行一次refresh()

activated() {
  this.$refs.scroll.scrollTo(0,this.saveY,0)
  this.$refs.scroll.refresh()
  // console.log('activate');
},
deactivated() {
  // console.log('deactivated');
  this.saveY = this.$refs.scroll.getScrollY()
  // console.log(this.saveY)
},
2.5 详情页开发

监听整个goodsItem的点击事件进入详情页

排除某一个组件的keep-alive

 
         

//数据进行整合的手段,采用Object完成
export class Goods {
  constructor(itemInfo, columns, services) {
    this.title = itemInfo.title
    this.desc = itemInfo.desc
    this.newPrice = itemInfo.price
    this.oldPrice = itemInfo.oldPrice
    this.discount = itemInfo.discountDesc
    this.columns = columns
    this.services = services
    this.realPrice = itemInfo.lowNowPrice
  }
}
//监听某一个属性的变化
watch: {
 detailInfo() {
   // 获取图片的个数
   this.imagesLength = this.detailInfo.detailImage[0].list.length
 }
}

时间戳:以linux时间元年为起点,返回对应的时间戳,1535329958(时间戳)

        如何将时间戳转成时间格式化字符串

        时间戳:

        1.将时间戳转成Date对象

        const date = new Date(1535329958*1000)

        2.将date进行格式化,转成对应的字符串

                date.getYear() | date.getMonth()-1

                datw--->FormatString(太常用)

                fmt.formate(data,'yyyy-MM-dd hh:mm')

正则表达式:做字符串匹配的利器

两个对象(组件之间)之间有重复代码:采用混入的方法解决

        混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

混入 — Vue.js

混入 — Vue.js

import {debounce} from "./utils";

export const itemListenerMixin = {
  mounted() {
    //图片加载完成的事件监听
    let refresh = debounce(this.$refs.scroll.refresh, 200)
    //保存函数
    this.itemImgListener = () => {
      refresh()
      // this.$refs.scroll.refresh()
    }
    //监听item中图片加载完成
    this.$bus.$on('itemImageLoad', this.itemImgListener)
  }
}
//组件
import {itemListenerMixin} from "../../common/mixin";
mixins: [itemListenerMixin]

类之间的继承:extends关键字

class Animal {
  run() {

  }
}

class Person extends Animal {

}

class Dog extends Animal {
  
}

标题和内容的联动效果:

        1. 点击标题滚动到对应内容(利用防抖 *** 作获取相应内容的高度)

错误版本:
this.$nextTick(()=>{
  // 第二次调动,根据最新的数据,DOM已经渲染出来了
  // 但是图片依然没有加载完毕,所以这里的数据还是错误的
  this.themeTopYs = []
  this.themeTopYs.push(0)
  this.themeTopYs.push(this.$refs.params.$el.offsetTop)
  this.themeTopYs.push(this.$refs.comment.$el.offsetTop)
  this.themeTopYs.push(this.$refs.recommend.$el.offsetTop)
  console.log(this.themeTopYs)
})
正确版本:在图片加载完后获取高度才是正确的
//防抖 *** 作,对某一个 *** 作不要频繁的进行使用
this.getThemeTopY = debounce(() => {
  this.themeTopYs = []
  this.themeTopYs.push(0)
  this.themeTopYs.push(this.$refs.params.$el.offsetTop)
  this.themeTopYs.push(this.$refs.comment.$el.offsetTop)
  this.themeTopYs.push(this.$refs.recommend.$el.offsetTop)
  console.log(this.themeTopYs)
})

//跳转到当前对应的位置
titleClick(index) {
  // console.log(index);
  this.$refs.scroll.scrollTo(0, -this.themeTopYs[index], 200)

}

2.滚动到对应位置标题的高亮发生改变:

普通做法:

if (this.currentIndex !== i && ((i < length - 1 && positionY >= this.themeTopYs[i]
  && positionY < this.themeTopYs[i + 1])
  || (i === length - 1 && positionY >= this.themeTopYs[i]))) {
  // console.log(i)
  this.currentIndex = i
  // console.log(this.currentIndex)
  this.$refs.nav.currentIndex = this.currentIndex
}

条件一:this.currentIndex !== i   防止赋值的过程过于频繁

条件二:(i < length - 1 && positionY >= this.themeTopYs[i] && positionY < this.themeTopYs[i + 1]) || (i === length - 1 && positionY >= this.themeTopYs[i])

        条件1:i < length - 1 && positionY >= this.themeTopYs[i] && positionY < this.themeTopYs[i + 1]) 

                 判断区间:在0和某个数字之间(i

        条件2:i === length - 1 && positionY >= this.themeTopYs[i]  

                判断区间:判断大于等于(i===length-1)

hack做法:用空间换时间

this.themeTopYs.push(Number.MAX_VALUE)

if (this.currentIndex !== i && (positionY >= this.themeTopYs[i]
  && positionY < this.themeTopYs[i + 1])) {
  this.currentIndex = i
  // console.log(this.currentIndex);
  this.$refs.nav.currentIndex = this.currentIndex
}        

底部工具栏:

        点击加入购物车

    监听加入购物车按钮的点击,并且获取商品信息 将数据利用vuex存储在store中:npm install vuex --save购物车展示:构建购物车页面,调用store中的数据
      导航栏展示购物车商品的展示商品的选中和不选中切换底部工具栏的汇总

store中的mapGetters:

mapGetters的映射关系:

import {mapGetters} from 'vuex'

...mapGetters(['cartCount'])

   回到顶部:

        详情页回到顶部   :利用混入mixin解决,实现多组件数据共享

mapActions的映射关系:

import {mapActions} from 'vuex'

...mapActions(['addCart'])         或者

...mapActions({ add:'addCart' })

toast的封装:

        普通封装

        插件形式封装

三、项目细节改进

1.fastClick----->在移动端减小点击300毫秒的延时

npm install fastClick --save

import FastClick from 'fastClick'

FastClick.attach(document.body)

2.图片懒加载

什么是图片懒加载?

        图片需要显示在屏幕区域上时再加载。

lazeload:Lazy Load延迟加载插件延迟了长网页中图像的加载。用户滚动到视窗之外的图像之前,不会加载它们。这与图像预加载相反。

1.npm install vue-lazyload --save

2.import VueLazyload from "vue-lazyload";

3.//lazylad插件

        Vue.use(VueLazyload)

4.v-lazy="showImage" alt="" @load="imageLoad">

5.占位符(可有可无)

Vue.use(VueLazyload,{
  loading:require('assets/img/common/placeholder.png')
})

3.单位转换插件:postcss-px-to-viewport

1.1.下载插件

npm install postcss-px-to-viewport --save--dev

2.配置postcss.config.js文件

module.exports = {
    plugins: {
        autoprefixer: {},
        "postcss-px-to-viewport": {

             //375*750 iphone6的屏幕
            viewportWidth: 375,//视窗的宽度,对应的是我们设计稿的宽度(retina 高清屏)
            viewportHeight: 667,//视窗的高度,对应的是我们设计稿的高度
            unitPrecision: 5,//指定'px'转换为视窗单位值得小数位数(很多时候无法整除)
            viewportUnit: 'vw',//指定需要转换成的视窗单位,这里使用vw
            selectorBlackList: ['ignore', 'tab-bar', 'tab-bar-item'],//指定不需要转换的类
            minPixelValue: 1,//小于或等于‘1px’不转换为视窗单位
            mediaQuery: false,//允许在媒体查询中转换'px'
            exclude: [/TabBar/, /CartBottomBar/]//不进行单位转换的文件(数组中内容为正则表达式)
        },
    }
}

正则的规则:

        1.^abc:表示匹配的内容,必须以什么内容开头

        2.abc$:表示匹配的内容,必须以什么内容结尾

四、nginx项目在windows下的部署

服务器:一台电脑(没有显示器,主机)24小时开着,为用户提供服务。

公司有没有服务主机?------->没有,租借阿里云/华为云/腾讯云

主机-> *** 作系统->windows/Linux->tomcat/nginx(软件)

第一:将自己的电脑作为服务器->winsow->nginx

第二:远程部署(Mac)

mainline version:主力在做的版本,可以说开发版

stable version:最新稳定版本

legacy version:遗留老版本的稳定版

部署方法:

        1.下载:nginx: download

        2.解压并双击启动:(路径不能有中文)

                localhost会显示

        3.复制打包的dist文件夹到nginx当前文件夹下面的html文件下,同时复制dist中的文件到html文件中,重新启动服务则会访问当前项目

或者

1.在配置文件中修改:

 location / {
            root   dist;
            index  index.html index.htm;
        }

在任务管理器进程中结束nginx进程,重新启动。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5704605.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存