zoukankan      html  css  js  c++  java
  • 跟我一起做一个vue的小项目(十)

    接下来我们对城市列表页面进行优化,除了对数据优化,也会进行节流处理

    //srcpagescitycomponentsAlphabet.vue
    <template>
       <ul class="list">
           <li class="item"
            v-for="item of letters"
            @click="handleLetterClick"
            @touchstart="handleTouchStart"
            @touchmove="handleTouchMove"
            @touchend="handleTouchEnd"
            :key="item"
            :ref="item"
            >{{item}}</li>
           <!-- <li class="item">B</li>
           <li class="item">C</li>
           <li class="item">D</li>
           <li class="item">E</li>
           <li class="item">F</li>
           <li class="item">G</li> -->
       </ul>
    </template>
    <script>
    import { clearTimeout, setTimeout } from 'timers'
    export default {
      name: 'CityAlphabet',
      props: {
        cities: Object
      },
      computed: {
        letters () {
          const letters = []
          for (let i in this.cities) {
            letters.push(i)
          }
          return letters
        }
      },
      data () {
        return {
          touchStatus: false,
          startY: 0,
          timer: null
        }
      },
      updated () {
        this.startY = this.$refs['A'][0].offsetTop
      },
      methods: {
        handleLetterClick (e) {
          this.$emit('change', e.target.innerText)
          // console.log('e.target.innerText', e.target.innerText)
        },
        handleTouchStart () {
          this.touchStatus = true
        },
        handleTouchMove (e) {
          if (this.touchStatus) {
            // const startY = this.$refs['A'][0].offsetTop
            // console.log(startY)
            if (this.timer) {
              clearTimeout(this.timer)
            }
            this.timer = setTimeout(() => {
              const touchY = e.touches[0].clientY - 79
              const index = Math.floor(touchY - this.startY) / 20
              if (index >= 0 && index < this.letters.length) {
                this.$emit('change', this.letters[index])
              }
              console.log(touchY)
            }, 16)
          }
        },
        handleTouchEnd () {
          this.touchStatus = false
        }
      }
    }
    </script>
    <style lang="stylus" scoped>
    @import '~styles/varibles.styl';
    .list
        display:flex
        flex-direction:column
        justify-content:center
        top:1.58rem
        right:0
        bottom:0
        .4rem
        position:absolute
        .item
            text-align:center
            line-height:.4rem
            text-align:center
            color:$bgColor
    </style>
    

    接下来我们来进行搜索列表的实现

    <template>
    <div>
        <div class="search">
            <input type="text"
            v-model="keyword"
            class="search-input"
            placeholder="请输入城市名或拼音">
        </div>
        <div class="search-content"
        ref="search"
        v-show="keyword"
        >
            <ul>
                <li
                :key="item.id"
                v-for="item of list"
                class="search-item border-bottom">
                    {{item.name}}
                </li>
                <li
                 class="search-item border-bottom"
                 v-show="!list.length"
                >
                没有找到匹配数据
                </li>
            </ul>
        </div>
    </div>
    </template>
    <script>
    import { clearTimeout, setTimeout } from 'timers'
    // 解决搜索框内容不能滚动
    import Bscroll from 'better-scroll'
    export default {
      name: 'CitySearch',
      props: {
        cities: Object
      },
      data () {
        return {
          keyword: '',
          list: [],
          timer: null
        }
      },
      computed: {
        hasNoData () {
          return !this.list.length
        }
      },
      watch: {
        keyword () {
          if (this.timer) {
            clearTimeout(this.timer)
          }
          if (!this.keyword) {
            this.list = []
            return
          }
          this.timer = setTimeout(() => {
            const result = []
            for (let i in this.cities) {
              this.cities[i].forEach((value) => {
                if (value.spell.indexOf(this.keyword) > -1 || value.name.indexOf(this.keyword) > -1) {
                  result.push(value)
                }
              })
            }
            this.list = result
          }, 100)
        }
      },
      mounted () {
        this.scroll = new Bscroll(this.$refs.search)
      }
    }
    </script>
    <style lang="stylus" scoped>
    @import '~styles/varibles.styl';
    .search
        height:.72rem
        background:$bgColor
        padding:0 .1rem
        .search-input
            box-sizing:border-box
            height:.62rem
            100%
            line-height:.62rem
            text-align:center
            border-radius:.06rem
            color:#666
    .search-content
        z-index:1
        overflow:hidden
        position:absolute
        top:1.58rem
        left:0
        right:0
        bottom:0
        background:#eee
        .search-item
            line-height:.62rem
            padding-left:.2rem
            background:#fff
            color:#666
    
    </style>
    

    我们看下效果

    接下来我们使用vuex进行城市定位选择,也就是城市选择页面的数据要传递给首页,也就是City组件中的数据要传递给home组件中
    安装vuex

     cnpm install vuex --save
    

    先看下实现的效果

    代码如下

    <template>
        <div class="list" ref="wrapper">
           <div>
                <div class="area">
                <div class="title border-topbottom">
                    当前城市
                </div>
                <div class="button-list">
                    <div class="button-wrapper">
                        <div class="button">{{this.$store.state.city}}</div>
                    </div>
                </div>
            </div>
             <div class="area">
                <div class="title border-topbottom">
                    热门城市
                </div>
                <div class="button-list">
                    <div
                        class="button-wrapper"
                        v-for="item of hot"
                        :key="item.id"
                        @click="handleCityClick(item.name)"
                    >
                        <div class="button">{{item.name}}</div>
                    </div>
                    <!-- <div class="button-wrapper">
                        <div class="button">北京</div>
                    </div>
                    <div class="button-wrapper">
                        <div class="button">北京</div>
                    </div>
                    <div class="button-wrapper">
                        <div class="button">北京</div>
                    </div>
                    <div class="button-wrapper">
                        <div class="button">北京</div>
                    </div>
                    <div class="button-wrapper">
                        <div class="button">北京</div>
                    </div> -->
                </div>
            </div>
             <div class="area"
                v-for="(item,key) of cities"
                :key="key"
                :ref="key"
            >
                <div class="title border-topbottom">
                    {{key}}
                </div>
                <div class="item-list">
                    <div class="item border-bottom"
                        v-for="innerItem of item"
                        :key="innerItem.id"
                         @click="handleCityClick(innerItem.name)"
                    >
                        {{innerItem.name}}
                    </div>
                    <!-- <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div> -->
                </div>
            </div>
            <!-- <div class="area">
                <div class="title border-topbottom">
                    B
                </div>
                <div class="item-list">
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                </div>
            </div> -->
            <!-- <div class="area">
                <div class="title border-topbottom">
                    C
                </div>
                <div class="item-list">
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                </div>
            </div> -->
           </div>
        </div>
    </template>
    <script>
    import Bscroll from 'better-scroll'
    export default {
      name: 'CityList',
      props: {
        hot: Array,
        cities: Object,
        letter: String
      },
      methods: {
        handleCityClick (city) {
        //   this.$store.dispatch('changeCity', city)
          this.$store.commit('changeCity', city)
          this.$router.push('/')
        //   alert(city)
        }
      },
      watch: {
        letter () {
        //   console.log('this.letter', this.letter)
          if (this.letter) {
            const element = this.$refs[this.letter][0]
            console.log('element', element)
            this.scroll.scrollToElement(element)
          }
        }
      },
      mounted () {
        this.scroll = new Bscroll(this.$refs.wrapper)
      }
    }
    </script>
    <style lang="stylus" scoped>
    @import '~styles/varibles.styl';
    .border-topbottom
        &:before
            border-color:#ccc
        &:after
            border-color:#ccc
    .list
        overflow:hidden
        position:absolute
        top:1.58rem
        left:0
        right:0
        bottom:0
        .title
            line-height:.54rem
            background:#eee
            padding-left:.2rem
            color:#666
            font-size:.26rem
        .button-list
            padding:.1rem .6rem .1rem .1rem
            overflow:hidden
            .button-wrapper
                33.33%
                float:left
                .button
                    margin:.1rem
                    text-align:center
                    border:.02rem solid #ccc
                    border-radius:.06rem
                    padding:.1rem 0
        .item-list
            .item
                line-height:.76rem
                color:#666
                padding-left:.2rem
    </style>
    

    接下来我们使用localstorage存储数据,使刷新的时候,也能记住我们选择的城市,另外代码还做了隐身模式或者浏览器不能保存数据的处理

    //index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    let defaultCity = '上海'
    try {
      if (localStorage.city) {
        defaultCity = localStorage.city
      }
    } catch (e) {
    
    }
    
    export default new Vuex.Store({
      state: {
        // city: localStorage.city || '上海'
        city: defaultCity
      },
      //   actions: {
      //     changeCity (ctx, city) {
      //       ctx.commit('changeCity', city)
      //     }
      //   },
      mutations: {
        changeCity (state, city) {
          state.city = city
          try {
            localStorage.city = city
          } catch (e) {
    
          }
        //   localStorage.city = city
        }
      }
    })
    

    接下来我们来拆分index.js文件,将store中的内容按照state,mutation等进行处理

    //state.js
    let defaultCity = '上海'
    try {
      if (localStorage.city) {
        defaultCity = localStorage.city
      }
    } catch (e) {}
    export default {
      city: defaultCity
    }
    
    //mutations.js
    export default {
      changeCity (state, city) {
        state.city = city
        try {
          localStorage.city = city
        } catch (e) {
    
        }
        //   localStorage.city = city
      }
    }
    
    //index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    import state from './state'
    import mutations from './mutations'
    Vue.use(Vuex)
    // let defaultCity = '上海'
    // try {
    //   if (localStorage.city) {
    //     defaultCity = localStorage.city
    //   }
    // } catch (e) {
    
    // }
    
    export default new Vuex.Store({
      state,
      //   actions: {
      //     changeCity (ctx, city) {
      //       ctx.commit('changeCity', city)
      //     }
      //   },
      mutations
    })
    
    //header.vue
    <template>
      <div class="header">
        <div class="header-left">
          <div class="iconfont back-icon">&#xe624;</div>
        </div>
        <div class="header-input">
          <span class="iconfont">&#xe632;</span>
          输入城市/游玩主题</div>
          <router-link to="/city">
            <div class="header-right">
              {{this.city}}
                <span class="iconfont arrow-icon">&#xe600;</span>
            </div>
          </router-link>
      </div>
    </template>
    <script>
    import {mapState} from 'vuex'
    export default {
      // 1rem = html font-size=50px
      name: 'HomeHeader',
      computed: {
        ...mapState(
          [
            'city'
          ]
        )
      },
      props: {
        // city: String
      }
    }
    </script>
    <style lang="stylus" scoped>
    @import '~styles/varibles.styl'
      .header
        line-height:$headerHeight
        background:$bgColor
        color:#fff
        display:flex
        .header-left
          0.64rem
          float:left
          .back-icon
            text-align:center
            font-size:0.4rem
        .header-input
          margin-top: 0.12rem;
          line-height: 0.64rem;
          -webkit-box-flex: 1;
          -ms-flex: 1;
          margin-bottom: 0.12rem;
          flex: 1;
          background: #fff;
          padding-left: 0.1rem;
          border-radius: 0.1rem;
          color: #ccc;
        .header-right
          min-1.04rem
          padding:0 .1rem
          float:right
          text-align:center
          color:#fff
          .arrow-icon
            margin-left:-.04rem
            font-size:.24rem
    </style>
    
    //list.vue
    <template>
        <div class="list" ref="wrapper">
           <div>
                <div class="area">
                <div class="title border-topbottom">
                    当前城市
                </div>
                <div class="button-list">
                    <div class="button-wrapper">
                        <div class="button">{{this.currentCity}}</div>
                    </div>
                </div>
            </div>
             <div class="area">
                <div class="title border-topbottom">
                    热门城市
                </div>
                <div class="button-list">
                    <div
                        class="button-wrapper"
                        v-for="item of hot"
                        :key="item.id"
                        @click="handleCityClick(item.name)"
                    >
                        <div class="button">{{item.name}}</div>
                    </div>
                    <!-- <div class="button-wrapper">
                        <div class="button">北京</div>
                    </div>
                    <div class="button-wrapper">
                        <div class="button">北京</div>
                    </div>
                    <div class="button-wrapper">
                        <div class="button">北京</div>
                    </div>
                    <div class="button-wrapper">
                        <div class="button">北京</div>
                    </div>
                    <div class="button-wrapper">
                        <div class="button">北京</div>
                    </div> -->
                </div>
            </div>
             <div class="area"
                v-for="(item,key) of cities"
                :key="key"
                :ref="key"
            >
                <div class="title border-topbottom">
                    {{key}}
                </div>
                <div class="item-list">
                    <div class="item border-bottom"
                        v-for="innerItem of item"
                        :key="innerItem.id"
                         @click="handleCityClick(innerItem.name)"
                    >
                        {{innerItem.name}}
                    </div>
                    <!-- <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div> -->
                </div>
            </div>
            <!-- <div class="area">
                <div class="title border-topbottom">
                    B
                </div>
                <div class="item-list">
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                </div>
            </div> -->
            <!-- <div class="area">
                <div class="title border-topbottom">
                    C
                </div>
                <div class="item-list">
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                    <div class="item border-bottom">阿拉尔</div>
                </div>
            </div> -->
           </div>
        </div>
    </template>
    <script>
    import Bscroll from 'better-scroll'
    import {mapState, mapMutations} from 'vuex'
    
    export default {
      name: 'CityList',
      props: {
        hot: Array,
        cities: Object,
        letter: String
      },
      computed: {
        ...mapState({
          currentCity: 'city'
        })
      },
      methods: {
        handleCityClick (city) {
        //   this.$store.dispatch('changeCity', city)
        //   this.$store.commit('changeCity', city)
          this.changeCity(city)
          this.$router.push('/')
        //   alert(city)
        },
        ...mapMutations(['changeCity'])
      },
      watch: {
        letter () {
        //   console.log('this.letter', this.letter)
          if (this.letter) {
            const element = this.$refs[this.letter][0]
            console.log('element', element)
            this.scroll.scrollToElement(element)
          }
        }
      },
      mounted () {
        this.scroll = new Bscroll(this.$refs.wrapper)
      }
    }
    </script>
    <style lang="stylus" scoped>
    @import '~styles/varibles.styl';
    .border-topbottom
        &:before
            border-color:#ccc
        &:after
            border-color:#ccc
    .list
        overflow:hidden
        position:absolute
        top:1.58rem
        left:0
        right:0
        bottom:0
        .title
            line-height:.54rem
            background:#eee
            padding-left:.2rem
            color:#666
            font-size:.26rem
        .button-list
            padding:.1rem .6rem .1rem .1rem
            overflow:hidden
            .button-wrapper
                33.33%
                float:left
                .button
                    margin:.1rem
                    text-align:center
                    border:.02rem solid #ccc
                    border-radius:.06rem
                    padding:.1rem 0
        .item-list
            .item
                line-height:.76rem
                color:#666
                padding-left:.2rem
    </style>
    
    

    接下来我们使用keep-alive优化网页性能
    路由发生改变,请求就会进行多次

    keep-alive进行缓存

    //app.vue 请求之后就放内存中    从内存中取数据,不用再去请求
    <template>
      <div id="app">
        <!-- 当前路由地址所对应的内容 -->
      <keep-alive>
        <!-- 缓存 -->
          <router-view/>
      </keep-alive>
      </div>
    </template>
    
    <script>
    export default {
      name: 'App'
    }
    </script>
    
    <style>
    
    </style>
    

    使用keep-alive的时候,我们会增加生命周期函数activated

    //Home.vue
    <template>
      <div>
      <home-header ></home-header>
      <home-swiper :list="swiperList"></home-swiper>
      <home-icons :list="iconList"></home-icons>
      <home-recommend :list="recommendList"></home-recommend>
      <home-weekend :list="weekendList"></home-weekend>
      </div>
    </template>
    <script>
    import HomeHeader from './components/Header'
    import HomeSwiper from './components/Swiper'
    import HomeIcons from './components/Icons'
    import HomeRecommend from './components/Recommend'
    import HomeWeekend from './components/Weekend'
    import {mapState} from 'vuex'
    import axios from 'axios'
    export default {
      name: 'Home',
      components: {
        HomeHeader,
        HomeSwiper,
        HomeIcons,
        HomeRecommend,
        HomeWeekend
      },
      computed: {
        ...mapState(['city'])
      },
      data () {
        return {
          swiperList: [],
          iconList: [],
          recommendList: [],
          weekendList: [],
          lastCity: null
        }
      },
      methods: {
        getHomeInfo () {
          axios.get('/api/index.json?city=' + this.city)
            .then(this.getHomeInfoSucc)
        },
        getHomeInfoSucc (res) {
          res = res.data
          if (res.ret && res.data) {
            const data = res.data
            this.swiperList = data.swiperList
            this.iconList = data.iconList
            this.recommendList = data.recommendList
            this.weekendList = data.weekendList
          }
        }
      },
      mounted () {
        this.lastCity = this.city
        this.getHomeInfo()
      },
      activated () {
        // 页面重新显示再执行
        if (this.lastCity !== this.city) {
          this.lastCity = this.city
          this.getHomeInfo()
        }
      }
    }
    </script>
    <style>
    </style>
    
  • 相关阅读:
    深度学习:Keras入门(一)之基础篇(转)
    《神经网络与机器学习》导言
    GAN综述
    VS2017专业版和企业版激活密钥
    IntelliJ Idea 常用快捷键列表
    数据库SQL优化大总结之 百万级数据库优化方案
    git使用教程
    VS2015常用快捷键总结
    心跳包实现
    基于OAuth 2.0的第三方认证 -戈多编程
  • 原文地址:https://www.cnblogs.com/smart-girl/p/11185788.html
Copyright © 2011-2022 走看看