vue2.0 饿了么学习笔记(17)seller组件开发

BScroll回顾: 外层有一个容器,定义了视口的高度,内层div可以被内容自动撑高,当内层容器高度超过视口高度时,就会出现滚动

1)接收传递进来的seller数据,并编写界面和样式

 props: {
    //APP.vue的routerview中已经将seller传进来了,这里只需要接收就好
    seller: {
      type: Object
    }
  },
      <div class="overview">
        <h1 class="title">{{seller.name}}</h1>
        <div class="desc border-1px">
          <star :size="36" :score="seller.score"></star>
          <span class="text">({{seller.ratingCount}})</span>
          <span class="text">月售{{seller.sellCount}}单</span>
        </div>
        <ul class="remark">
          <li class="block">
            <h2>起送价</h2>
            <div class="content">
              <span class="stress">{{seller.minPrice}}</span>元
            </div>
          </li>
          <li class="block">
            <h2>商家配送</h2>
            <div class="content">
              <span class="stress">{{seller.deliveryPrice}}</span>元
            </div>
          </li>
          <li class="block">
            <h2>平均配送时间</h2>
            <div class="content">
              <span class="stress">{{seller.deliveryTime}}</span>元
            </div>
          </li>
        </ul>
        <div class="favorite"  @click="toggleFavorite($event)">
          <i class="icon-favorite" :class="{'active':favorite}"></i> <!-- 对应是否收藏两种样式-->
          <span>{{favoriteText}}</span> <!-- 有没有选中对应不同的文本,所以这里要绑定一个变量,放到data中 -->
        </div>
      </div>
2)添加公告与活动部分,先添加一个split组件,在添加内容,不要忘了把图片拷贝过来
<div class="bulletin">
        <h1 class="title">公告与活动</h1>
        <div class="content-wrapper border-1px">
          <p class="content">{{seller.bulletin}}</p>
        </div>
        <ul v-if="seller.supports" class="supports">
            <li class="support-item border-1px" v-for="(item,index) in seller.supports" :key="(item.id,index.id)">
              <span class="icon" :class="classMap[seller.supports[index].type]"></span>
              <span class="text">{{seller.supports[index].description}}</span>
            </li>
          </ul>
      </div>
      <split></split>

3)页面过长,将BScroll引入进来

3.1 .初始化BScroll语句放在created(),按照DOM的生命周期来说,执行到DOM的时候不能保证DOM已经被渲染了,在goods.vue中把BScroll初始化语句写在created()中,是因为前半部分先执行了获取api数据的语句,在seller中,数据是通过props传进来的,不能保证数据是否已经被渲染了

3.2 初始化BScroll语句放在ready中又不起作用,DOM被渲染完之后,ready是自动被执行的,在ready中写的代码都可以安全的去使用DOM,但是高度计算不对,无法正确滚动,原因:seller是异步获取的,但是我们的内容都是靠seller里的数据撑开的,,所以一开始内容肯定是小于我我们定义的wrapper的,所以没有被撑开

3.3 将其放入watch:{}中可以watch到seller的变化,将初始化语句写成一个方法,在watch中进行调用

watch: {
    'seller'() {
      this._initScroll();
      this._initPics();
    }
  },
    _initScroll() {
      if (!this.scroll) {
        this.$nextTick(() => {
          this.scroll = new BScroll(this.$refs.seller, {click: true});
        });
      } else {
        this.scroll.refresh();
      } 
    },
    _initPics() {
      if(this.seller.pics) {
        let picWidth = 120;
        let margin = 6;
        let width = (picWidth + margin) * this.seller.pics.length - margin;
        this.$refs.picList.style.width = width + 'px'; //不要忘记加单位
        if(!this.picScroll){
          this.$nextTick(() => {
            this.picScroll = new BScroll(this.$refs.picWrapper, {
              scrollX: true, //表示横向滚动
              eventPassthrough: 'vertical'  //横向滚动图片的时候就忽略垂直方向的滚动
            });
          });
        } else {
          this.picScroll.refresh();
        } 
 
      }
    }

3.4 .每次切换商家页面时,DOM被重新渲染,又不能滚动了,因为在watch中只能观测到seller的变化,切换区块的时候seller没有变化,所以seller中的watch不会被执行,所以BScroll就不会初始化。我们在ready方法中重新加入初始化语句

watch: {
    'seller'() {
      this._initScroll();
      this._initPics();
    }
  },
  ready() {
    this._initScroll();
    this._initPics();
   //设定ul的宽度
  },

一定要为初始化函数_initScroll()和this._initPics()中的nextTick()下的添加if-else语句,因为ready的执行时机要先于watch中的seller,然后我们在执行seller中的initScroll的时候就会发现BScroll已经被初始化了,所以initScroll失效,即使在watch中观察到变化也只能什么都不做,所以我们将一个else选项,对BScroll进行刷新,完成

6.添加图片,设置样式,横向排列并实现横向滚动,ul是外层的宽度,并不是真实的li撑开的宽度,使用BScroll实现滚动,添加—_initPic()方法,并把它添加到watch和ready中

      <div class="pics">
        <h1 class="title">商家实景</h1>
        <div class="pic-wrapper" ref="picWrapper">
          <ul class="pic-list" ref="picList">
            <li class="pic-item" v-for="pic in seller.pics" :key="pic.id">
              <img :src="pic" width="120" height="90">
            </li>
          </ul>
        </div>
      </div>
      <split></split>
      .pics
        padding 18px
        .title
          margin-bottom 12px
          line-height 14px
          color rgb(7, 17, 27)
          font-size 14px
        .pic-wrapper
          width 100%
          overflow hidden
          white-space nowrap /*不产生折行*/
          .pic-list
            font-size 0
            .pic-item
              display inline-block
              margin-right 6px
              width 120px
              height 90px
              &:last-child
                margin 0

7.添加收藏按钮,设置:active样式(红,白)和字体的变化(收藏和未收藏)

        <div class="favorite"  @click="toggleFavorite($event)">
          <i class="icon-favorite" :class="{'active':favorite}"></i> <!-- 对应是否收藏两种样式-->
          <span>{{favoriteText}}</span> <!-- 有没有选中对应不同的文本,所以这里要绑定一个变量,放到data中 -->
        </div>
data() {
    return {
     // favorite: false, //默认没有被收藏,从localStorge中取读取,不是一个默认值了
      favorite: (() => {
       return loadFromlLocal(this.seller.id, 'favorite', false);
     })()
    };
  },
computed: {
    favoriteText() {
       return this.favorite ? '已收藏' : '收藏';
    }
  },

methods中

 toggleFavorite(event) {
        if (!event._constructed) {
          return;
        }
        this.favorite = !this.favorite;
        //这样写取法区分商家id,不同商家的状态一样
        //localStorage.favorite = this.favorite;
        saveToLocal(this.seller.id, 'favorite', this.favorite);
      },
刷新之后,收藏样式就会消失,将收藏的信息添加到localStorge中,创建store.js实现数据的存取
//savaToLocal(this.seller.id, 'favorite', this.favorite);
export function saveToLocal(id, key, value) { //存储到localStorge
  let seller = window.localStorage.__seller__;
  if (!seller) { //没有seller的时候,初始化,定义一个seller对象,并给他设定一个id
    seller = {};
    seller[id] = {};
  } else {
    seller = JSON.parse(seller); // JSON 字符串转换为对象
    if (!seller[id]) { //判断是否有当前这个商家
      seller[id] = {};
    }
  }
  seller[id][key] = value;
  //将一个JavaScript值(对象或者数组)转换为一个 JSON字符串
  window.localStorage.__seller__ = JSON.stringify(seller);
}
//loadFromlLocal(this.seller.id, 'favorite', false);
export function loadFromlLocal(id, key, def) { //读取,读不到的时候传入一个default变量
  let seller = window.localStorage.__seller__;
  if (!seller) {
    return def;
  }
  seller = JSON.parse(seller)[id];
  if (!seller) {
    return def;
  }
  let ret = seller[key];
  return ret || def;
}
引入:
import {saveToLocal, loadFromlLocal} from 'common/js/store.js';







猜你喜欢

转载自blog.csdn.net/qq_22317389/article/details/80461414
今日推荐