【vue项目实战】Vue工程化项目--猫眼电影移动端(四)

第四节

  • 底部导航
  • vuex --参考:vuex 使用总结(详解)
  • 登陆验证、用户注册 --这里是使用vuex模拟数据库里的读存操作(结合真实数据库请参考【全栈初体验】Vue+Node+MySQL实现前后端分离开发)
  • demo地址 :第四节
  • 结合代码 看以下文字,建议 从第一节看起
  • 这些文章都看完之后,可以看一下 猫眼升级版 技术栈:vue-cli3 + typescript + axios

底部导航

  1. 菜单样式为图标和字体的组合,布局使用弹性盒子即可。

  2. 图标用到了iconfont,所以将其封装成了本地组件以供使用, 参考:vue中手动封装iconfont组件

  3. 点击相应tab,首先要改变状态,然后使用 $emit 跟父组件通信,告诉他我点击了什么按钮。

    // 文件路径:src/components/pageFooter.vue
    <template>
      <div class="nav">
        <ul class="icon">
          <li @click="changeTab('film')">
            <icon :name="''" :iconStyle="activeTab === 'film'? iconStyleActive : iconStyle">icon>
            <span class="text">电影span>
          li>
          <li @click="changeTab('cinema')">
            <icon :name="''" :iconStyle="activeTab === 'cinema'? iconStyleActive : iconStyle">icon>
            <span class="text">影院span>
          li>
          <li @click="changeTab('mine')">
            <icon :name="''" :iconStyle="activeTab === 'mine'? iconStyleActive : iconStyle">icon>
            <span class="text">我的span>
          li>
        ul>
      div>
    template>
    
    <script>
    export default {
      name: 'pageFooter',
      data() {
        return {
          activeTab: 'film',
          iconStyle: {fontSize: '20px', color: '#696969'},
          iconStyleActive: {fontSize: '20px', color: '#f03d37'}
        }
      },
      methods: {
        changeTab(type) {
          this.activeTab = type
          this.$emit('chooseMenu', type)
        }
      }
    }
    script>
    
    <style lang="scss" scoped>
    @import '@/assets/scss/main.scss';
    ul{
      @include flex-box(row, space-between);
      li{
        @include flex-box(column, space-between);
        > .text {
          color: #696969;
          font-size: 10px;
        }
      }
    }
    style>
    

【vue项目实战】Vue工程化项目--猫眼电影移动端(四)_第1张图片

主页面逻辑更新

  1. 首先主页面逻辑是点击相应按钮,显示相应页面(注意不是通过路由进入一个新页面,猫眼升级版 是使用路由控制 ),所以看下一步

  2. 给每个子页面做一个标记(film、cinema、mine),每次只显示一个子页面(通过标记去显示),而点击底部导航按钮会改变这个标记,进而实现切换

  3. 这个标记是通过 底部导航 传递过来的。这里是通过 @chooseMenu 接收(不懂的请看“底部导航”第3步骤)

    // 文件路径:src/pages/index.vue
    <template>
      <div>
        <div class="top">
          <page-title >猫眼电影page-title>
          <ul v-if="showMainType==='film'" class="topNav">
            <li :class="[showHot==1?'active':'']" @click="showHot=1">正在热映li>
            <li :class="[showHot==0?'active':'']" @click="showHot=0">即将上映li>
          ul>
        div>
        <div class="main">
          <div v-if="showMainType==='film'">
            <hoting v-show="showHot==1">hoting>
            <comming v-show="showHot==0">comming>
          div>
          <div v-else-if="showMainType==='mine'">
            <mine>mine>
          div>
          <div v-else>
            <cinima>cinima>
          div>
        div>
        <div class="footer-nav">
          <page-footer
            @chooseMenu="chooseMenu"
          >page-footer>
        div>
      div>
    template>
    
    <script>
    import hoting from '@/components/hoting'
    import comming from '@/components/comming'
    import cinima from '@/pages/cinima'
    import mine from '@/pages/mine'
    
    export default {
      components: {
        hoting, comming, cinima, mine
      },
      data() {
        return {
          showHot: 1,
          showMainType: 'film'
        }
      },
      methods: {
        chooseMenu(val) {
          this.showMainType = val
        }
      }
    }
    script>
    

【我的】页面

  1. 我的页面分两类:已登录和未登录

  2. 通过vuex获取用户登录状态(正确登录后,会将用户信息存储到vuex)参考:vuex 使用总结(详解)

    // 文件路径:src/mine/index.vue
    <template>
     <div>
         <isLogin v-if="isLogin">isLogin>
         <notLogin v-else>notLogin>
     div>
    template>
    <script>
     import isLogin from './isLogin'
     import notLogin from './notLogin'
     import { mapState } from "vuex";
     export default {
         components: {
             isLogin, notLogin
         },
         computed: {
             ...mapState(['isLogin'])
         }
     }
    script>
    
  3. 未登录显示登陆按钮,让其跳转到登录页去登录 (文件路径:src/mine/notLogin.vue)

  4. 已登录就可以正常显示【我的】一些信息,具体显示什么可以自定义 (文件路径:src/mine/isLogin.vue)

【vue项目实战】Vue工程化项目--猫眼电影移动端(四)_第2张图片

登录验证,登录逻辑

  1. 这里的读存用户信息是使用vuex模拟数据库(结合真实数据库请参考【全栈初体验】Vue+Node+MySQL实现前后端分离开发)

    // 文件路径:src/store/index.js
    state: {
      isLogin: 0,  // 判断用户是否登陆
      userNick: '',	
      defaultHeadImg: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2363028509,190015165&fm=26&gp=0.jpg', // 用户默认头像
      userHeadImg: this.defaultHeadImg,
      // 模拟数据库用户信息
      testInfo: [
        {
          account: 'bjpengyuyan',
          password: '111111',
          userNick: '滨江彭于晏',
          userHeadImg: 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3279316276,2228302562&fm=26&gp=0.jpg',
          likeList: ['健身', '台球']
        }
      ]
    },
    // 通过用户名获取用户信息,在登陆验证时会用到
    getters: {
      testUserInfo: state => account => {
        let userinfoIndex = state.testInfo.findIndex(info => info.account === account)
        return userinfoIndex === -1 ? undefined : state.testInfo[userinfoIndex]
      }
    }
    
  2. 登录(基本的表单校验,登录成功和不成功的操作)

    // 文件路径: src/pages/login/index.vue
    login() {
      if(!this.user.trim()) return alert('用户名不能为空!');
      if(!this.password) return alert('请输入密码!');
      let testInfo = this.testUserInfo(this.user) // 从vuex去取用户的信息
      if (!testInfo) return alert('用户名不存在!');
      if (this.user === testInfo.account && this.password === testInfo.password) {
        // 这里是登陆成功后的操作:将用户信息存到本地vuex中,然后跳转到【我的】页面
        this.loginIn(testInfo)
        this.$router.push('/')
      } else {
        alert('密码错误!!')
        // 可选项:输入错误后清空用户名和密码
        // this.user = ''
        // this.password = ''
      }
    }
    
    // 文件路径:src/store/index.js
    mutations: {
      // 用户成功登陆后,将用户信息存到vuex
      loginIn(state, payload) {
        state.isLogin = 1
        state.userNick = payload.userNick
        state.userHeadImg = payload.userHeadImg || state.defaultHeadImg
      }
    }
    

    事实上 用户登录校验是在后台做的,前端需要把用户名和密码传给后端,然后后端再返回是否验证通过,且密码最好不要以明文传递。密码加密参考 使用AES实现密码加密解密 ,这里不提密码加密的有效性。

  3. 然后就是退出,退出操作就是清空用户本地信息。

    // 文件路径:src/store/index.js
    mutations: {
      // 退出时,清空用户在vuex的信息
      loginOut(state) {
        state.isLogin = 0
        state.userNick = ''
        state.userHeadImg = state.defaultHeadImg
      }
    }
    

用户注册

  1. 注册之前,先判断账号是否已存在

  2. 注册成功后将注册信息存到数据库,这里是存到vuex中来模拟

    // 文件路径: src/pages/register/index.vue
    handleRegister() {
      if(!this.nick.trim()) return alert('昵称不能为空!');
      if(!this.account.trim()) return alert('用户名不能为空!');
      if(!this.password) return alert('请输入密码!');
      let testInfo = this.testUserInfo(this.account)  // 从vuex去取用户的信息
      if (testInfo && testInfo.account) {
        alert('用户名已存在!')
        this.account = ''
        this.password = ''
      } else {
        const params = {
          userNick: this.nick,
          account: this.account,
          password: this.password,
        }
        this.register(params)
        alert('注册成功')
        this.$router.back() //注册成功后返回登陆页
      }
    }
    
    // 文件路径:src/store/index.js
    mutations: {
      // 用户注册成功后,将用户信息存到模拟的数据库信息中
      register: (state, payload) => state.testInfo.push(payload)
    }
    
    【vue项目实战】Vue工程化项目--猫眼电影移动端(四)_第3张图片

最后

目前整个逻辑都差不多了,后面有时间就继续优化demo和丰富细节,或者(建议)可以自己动手去丰富细节。
本节完整 demo
这些文章都看完之后,可以看一下 猫眼升级版 技术栈:vue-cli3 + typescript + axios

你可能感兴趣的:(Vue,vue项目实战,项目工程化,猫眼,vue-cli,vue.js)