• vue2.x--- cube-ui重构饿了么


    一,安装,cube-ui

    安装cube-ui     vue add cube-ui (针对vue-cli3),安装会有一些配置提示, 以后会直接使用cube组件了,按需引入,
    Use post-compile? 后编译 y
    部分引用 Import type
    自定义主题 Custom theme y
    Use rem layout rem 布局 n
    Use vw layout rem 布局的 n

    安装重构后,vue项目中会自动theme.styl的样式,cube-ui.js的组件, 在main.js中引入即可

    二,引入tab-bar组件,以及cube-slide轮播图组件

     
    <template>
      <div class="tab">
        <!-- 切换栏 -->
        <cube-tab-bar
          :showSlider="true"
          v-model="selectedLabel"
          :data="tabs"
          ref="tabBar"
          class="border-bottom-1px"
        >
        </cube-tab-bar>
        <div class="slide-wrapper">
          <!-- 轮播 -->
          <cube-slide
            :loop="false"
            :auto-play="false"
            :initial-index="index"
            ref="slide"
          >
          <!-- 轮播结构 -->
            <cube-slide-item>
              <Goods></Goods>
            </cube-slide-item>
            <cube-slide-item>
              <Ratings></Ratings>
            </cube-slide-item>
            <cube-slide-item>
              <Sellers></Sellers>
            </cube-slide-item>
          </cube-slide>
        </div>
      </div>
    </template>
    
    <script>
    import Goods from "@/views/igoods/igoods";
    import Ratings from "@/views/iratings/iratings";
    import Sellers from "@/views/isellers/isellers";
    export default {
      data() {
        return {
          index: 0,
          tabs: [
            {
              label: "商品"
            },
            {
              label: "评价"
            },
            {
              label: "商家"
            }
          ]
        };
      },
    
      computed: {
        selectedLabel: {
          get() {
            return this.tabs[this.index].label;
          },
          set(newVal) {
            this.index = this.tabs.findIndex(value => {
              return value.label === newVal;
            });
          }
        }
      },
    
      components: {
        Goods,
        Ratings,
        Sellers
      }
    };
    </script>
    
    <style scoped lang="stylus">
    @import "../../assets/stylus/variable"
      .tab
        >>> .cube-tab
          padding: 10px 0
        display :flex
        flex-direction :column
        height :100px
        .slide-wrapper
          flex:1
          overflow: hidden
    </style>

    cube-tab-bar组件里头默认有三个cube-tab组件,根据tabs数组来定义的,用深度选择器的样式来作用

    #Scoped CSS
    当 <style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素。这类似于 Shadow DOM 中的样式封装。
    vue-loader官网介绍;https://vue-loader.vuejs.org/zh/guide/scoped-css.html#%E6%B7%B7%E7%94%A8%E6%9C%AC%E5%9C%B0%E5%92%8C%E5%85%A8%E5%B1%80%E6%A0%B7%E5%BC%8F
    #子组件的根元素
    使用 scoped 后,父组件的样式将不会渗透到子组件中。不过一个子组件的根节点会同时受其父组件的 scoped CSS 和子组件的 scoped CSS 的影响。
    这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。 #深度作用选择器 如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用
    >>> 操作符:

    此时左右滑动轮播图,上面的切换栏不会自动跟随切换,此时我们需要实现一个上下联动,需要添加change事件

          <!-- 轮播 -->
          <cube-slide
            :loop="false"
            :auto-play="false"
            :initial-index="index"
            ref="slide"
            @change="onChange"
          >
     methods:{
        // Slide 页面切换时触发,参数为当前索引值
        onChange(currentIndex){
          this.index = currentIndex
        }
      },

    此时上下联动效果已完成,但是还不够完美,我们还要实现左右滑动有一个渐变效果,轮播图添加scroll事件

    逻辑分析,知道滑动的距离占总轮播图的宽度的距离的比值,乘以切换栏的宽度,利用切换栏的cube-tab-bar的setSliderTransform方法即可

         <!-- 轮播 -->
          <cube-slide
            :loop="false"
            :auto-play="false"
            :initial-index="index"
            ref="slide"
            @change="onChange"
            @scroll= "onScroll"
            :options="slideOptions"
          >
     // 滚动中实时派发
        onScroll(pos){
          // console.log(ops.x)
          // 通过refs获取切换栏tab-bar组件的宽度,需要.$el
          const tabBarWidth = this.$refs.tabBar.$el.clientWidth
          // 获取轮播图silde组件的宽度,是全部滚动的宽度
          const slideWidth = this.$refs.slide.slide.scrollWidth
          // 滑动的宽度 / 总滚动轮播的宽度 * 切换栏的宽度
          const transform = -pos.x / slideWidth * tabBarWidth
          this.$refs.tabBar.setSliderTransform(transform)
          
        }

    切换栏还需要配置选项,以及关闭过渡效果(默认开启)

     slideOptions:{
            listenScroll:true,
            // 在滑动不止时
            probeType:3,
            directionLockThreshold:0
          }
    <!-- 切换栏 -->
        <cube-tab-bar
          :showSlider="true"
          v-model="selectedLabel"
          :data="tabs"
          ref="tabBar"
          class="border-bottom-1px"
          :useTransition="false"
        >
        </cube-tab-bar>

    二,优化,组件抽象和封装,动态组件设置,组件名称和数据在父组件app中定义,传入子组件,动态设置组件,利用component组件

    import { mapState } from "vuex";
    import tab from "@/components/tab/tab";
    import Goods from "@/views/igoods/igoods";
    import Ratings from "@/views/iratings/iratings";
    import Sellers from "@/views/isellers/isellers";
     computed: {
        ...mapState(["sellers"]),
        tabs(){
          return  [
            {
              label:'商品',
              component:Goods,
              data:{
                sellers:this.sellers
              }
    
            },
            {
              label:'评价',
              component:Ratings,
              data:{
                sellers:this.sellers
              }
    
            },
            {
              label:'商家',
              component:Sellers,
              data:{
                sellers:this.sellers
              }
    
            },
          ]
        }
      },
    <div class="tab-wrapper">
          <tab :tabs ="tabs"></tab>
        </div>

    优化后,动态设置组件,vue.js官网动态组件

    我们在一个多标签的界面中使用 is attribute 来切换不同的组件:
    
    <component v-bind:is="currentTabComponent"></component>
    <template>
      <div class="tab">
        <!-- 切换栏 -->
        <cube-tab-bar
          :showSlider="true"
          v-model="selectedLabel"
          :data="tabs"
          ref="tabBar"
          class="border-bottom-1px"
          :useTransition="false"
        >
        </cube-tab-bar>
        <div class="slide-wrapper">
          <!-- 轮播 -->
          <cube-slide
            :loop="false"
            :auto-play="false"
            :initial-index="index"
            ref="slide"
            @change="onChange"
            @scroll="onScroll"
            :options="slideOptions"
          >
            <!-- 轮播结构 -->
            <cube-slide-item v-for="(tab, index) in tabs" :key="index">
              <component :is="tab.component" :data="tab.data"></component>
            </cube-slide-item>
            <!-- <cube-slide-item>
              <Goods></Goods>
            </cube-slide-item> -->
            <!-- <cube-slide-item>
              <Ratings></Ratings>
            </cube-slide-item>
            <cube-slide-item>
              <Sellers></Sellers>
            </cube-slide-item> -->
          </cube-slide>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          index: 0,
          // tabs: [
          //   {
          //     label: "商品"
          //   },
          //   {
          //     label: "评价"
          //   },
          //   {
          //     label: "商家"
          //   }
          // ],
          slideOptions: {
            listenScroll: true,
            // 在滑动不止时
            probeType: 3,
            directionLockThreshold: 0
          }
        };
      },
    
      props: ["tabs"],
    
      methods: {
        // Slide 页面切换时触发,参数为当前索引值
        onChange(currentIndex) {
          this.index = currentIndex;
        },
        // 滚动中实时派发
        onScroll(pos) {
          // console.log(ops.x)
          // 通过refs获取切换栏tab-bar的宽度,需要.$el
          const tabBarWidth = this.$refs.tabBar.$el.clientWidth;
          // 获取轮播图silde组件的宽度,是全部滚动的宽度
          const slideWidth = this.$refs.slide.slide.scrollWidth;
          // 滑动的宽度 / 总滚动轮播的宽度 * 切换栏的宽度
          const transform = (-pos.x / slideWidth) * tabBarWidth;
          this.$refs.tabBar.setSliderTransform(transform);
        }
      },
    
      computed: {
        selectedLabel: {
          get() {
            return this.tabs[this.index].label;
          },
          set(newVal) {
            this.index = this.tabs.findIndex(value => {
              return value.label === newVal;
            });
          }
        }
      }
    
      // components: {
      //   Goods,
      //   Ratings,
      //   Sellers
      // }
    };
    </script>
    
    <style scoped lang="stylus">
    @import "../../assets/stylus/variable"
      .tab
        >>> .cube-tab
          padding: 10px 0
        display :flex
        flex-direction :column
        height :100px
        .slide-wrapper
          flex:1
          overflow: hidden
    </style>

    三,在goods组价中,获取goods数据

    1.我们不在mouted中dispatch下从vuex中获取数据,而是在tabs父组件中的change事件(切换栏触发)时调用子组件goods的请求数据的函数

      <!-- 轮播结构 -->
            <cube-slide-item v-for="(tab, index) in tabs" :key="index">
              <component :is="tab.component" :data="tab.data" ref="component"></component>
            </cube-slide-item>

    在父组件中调用子组件的方法

     methods: {
        // Slide 页面切换时触发,参数为当前索引值
        onChange(currentIndex) {
          this.index = currentIndex;
          // 切换tab栏,发送请求,获取goods数据
          const component = this.$refs.component[currentIndex]
          component.fetch && component.fetch()
        },

    子组件goods定义获取数据的函数

     methods: {
        fetch() {
          this.$store.dispatch("reqgoods");
        }
      },
     computed: {
        ...mapState(["goods"])
      }

    第一次渲染页面,也要调用该函数

      mounted(){
        this.onChange(this.index)
      },
     
  • 相关阅读:
    在X++中使用IoC/DI模式应对不断变化的客户需求
    Predicate<T>与Func<T, bool>泛型委托
    Windows Live Writer插件:在WLW中插入语法高亮代码
    学习C#和.NET的资源
    C#中事件的动态调用
    2008年全国软件工程大会论文集
    C#基础:接口(二)
    【转载】"变化"、"复用"、"抽象"、"稳定" 影响着软件设计模式,架构,开发方法
    【领域驱动设计】.NET实践:实体、值对象和数据传输对象
    RSS订阅之基本使用
  • 原文地址:https://www.cnblogs.com/fsg6/p/14382834.html
Copyright © 2020-2023  润新知