首先讲原理:通过引入其他页面到本页里,类似html中的iframe也可以理解为ajax的异步加载html,至此就可以达到底部不会闪烁的问题(自定义vue组件跳转会闪烁,狗眼闪瞎…)

1.用到一个插件,方便快捷,大小为6.5KB.,链接为https://ext.dcloud.net.cn/plugin?id=4124
在这里插入图片描述
导入的时候遇到一个坑,它会把原来的node_modues替换掉…导入的时候可以先备份一下,然后综合一下更新到node_modues
2.导入插件后,npm 安装引入npm install uni-lb-tabbar
3.安装完插件后再pages.json加上如下配置:

"easycom": {
  "autoscan": true,
  "custom": {
    "lb-tabbar": "uni-lb-tabbar/components/lb-tabbar/lb-tabbar",
    "lb-tabbar-item": "uni-lb-tabbar/components/lb-tabbar/lb-tabbar-item"
  }
}

4.主页面demo6中如下代码

<template>
  <view class="content">
    <view class="layout-page">
      <!-- 首页 -->
      <home :visible="active === 'home'"
        :height="height"
        @change="handleTabChange">
      </home>
      <!-- 购物车 -->
      <cart :visible="active === 'cart'"
        :height="height"
        @change="handleTabChange">
      </cart>
      <!-- 消息 -->
      <notice :visible="active === 'notice'"
        :height="height"
        @change="handleTabChange">
      </notice>
      <!-- 我的 -->
      <mine :visible="active === 'mine'"
        :height="height"
        @change="handleTabChange">
      </mine>
    </view>
    <!-- 此处因为不需要点击凸起的发布按钮进行页面变化或跳转,故将v-model="active"修改成:value="active" -->
    <!-- 在handleChange中手动判断进行active的赋值 -->
    <lb-tabbar ref="tabbar"
      :value="active"
      :animate="animate"
      @change="handleChange">
      <lb-tabbar-item v-for="item in tabbars"
        :key="item.name"
        :name="item.name"
        :icon="active === item.name ? item.iconActive : item.icon" //进行判断,是否点击状态
        :dot="item.dot"
        :info="item.info"
        :raisede="item.raisede"
        icon-prefix="iconfont"
        @click="handleTabbarItemClick">
        {{ item.text }}
      </lb-tabbar-item>
    </lb-tabbar>
  </view>
</template>

<script>
import Home from '@/pages/demos/demo6/home/home'
import Cart from '@/pages/demos/demo6/cart/cart'
import Notice from '@/pages/demos/demo6/notice/notice'
import Mine from '@/pages/demos/demo6/mine/mine'
export default {
	components: {
		Home,
		Cart,
		Notice,
		Mine
	},
  data () {
    return {
      active: '',
      animate: 'zoomIn',
      height: '',
      tabbarHeight: '',
      tabbars: [
        {
          name: 'home',
          text: '首页',
          icon: 'home',
          dot: true
        },
        {
          name: 'cart',
          text: '购物车',
          icon: 'cart'
        },
        {
          name: 'plus',
          text: '发布',
          icon: 'plus',
          raisede: true
        },
        {
          name: 'notice',
          text: '消息',
          icon: 'notice',
          info: 99
        },
        {
          name: 'mine',
          text: '我的',
          icon: 'mine'
        }
      ]
    }
  },
  onLoad (query) {
    // 可通过地址栏传tab参数可指定默认显示哪个tab页面
    this.active = query.tab || 'home'
  },
  onReady () {
    const res = uni.getSystemInfoSync()
    const { windowHeight } = res
    this.tabbarHeight = this.$refs.tabbar.tabbarHeight
    this.height = windowHeight - this.tabbarHeight + 'px'
  },
  methods: {
    handleChange (e) {
      console.log('change::', e)
      if (e.name !== 'plus') {
		  console.log("输出改变事件结果")
		  console.log(this.active)
        this.active = e.name		
      }
    },
    handleTabChange (name) {
      this.active = name
    },
    handleTabbarItemClick (e) {
      console.log('click::', e)
      if (e.name === 'plus') {
        uni.showToast({
          title: '发布',
          icon: 'none'
        })
      }
    }
  },
  watch: {
    active: {
      handler (newVal) {
        if (newVal) {
          // pages.json中设置页面的title为空,可在此处动态设置标题及颜色等等
          const item = this.tabbars.find(item => item.name === this.active)
          uni.setNavigationBarTitle({
            title: item.text
          })
        }
      },
      immediate: true
    }
  }
}
</script>

<style lang="scss" scoped>
.content {
  height: 100vh;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  overflow: hidden;
  .layout-page {
    min-height: 0;
    flex: 1;
    /deep/ .page {
      height: 100%;
    }
  }
}
</style>

可以看到在主页面里导入了四个页面组件,每个组件代表底部菜单的每一项

5.导航菜单组件home

<template>
  <scroll-view class="page"
    scroll-y
    :style="{
    display: visible ? 'block' : 'none'
  }">
    <view>首页</view>
    <button @click="handleClick">切换到我的</button>
    <view v-if="!isGetData">模拟数据加载中...</view>
    <view v-for="item in list"
      :key="item">
      <text>首页页面的第{{item }}条数据</text>
    </view>
  </scroll-view>
</template>

<script>
export default {
  props: {
    visible: Boolean
  },
  data () {
    return {
      list: [],
      isGetData: false
    }
  },
  methods: {
    // 模拟请求数据
    getData () {
      setTimeout(() => {
        for (let i = 0; i < 50; i++) {
          this.list.push(i + 1)
        }
        this.isGetData = true
      }, 1000)
    },
    handleClick () {
      this.$emit('change', 'mine')
    }
  },
  watch: {
    visible: {
      handler (newVal) {
        if (newVal && !this.isGetData) {
          this.getData()
        }
      },
      immediate: true
    }
  }
}

</script>

6.导航菜单组件home

<template>
  <scroll-view class="page"
    scroll-y
    :style="{
    display: visible ? 'block' : 'none'
  }">
    <view>首页</view>
    <button @click="handleClick">切换到我的</button>
    <view v-if="!isGetData">模拟数据加载中...</view>
    <view v-for="item in list"
      :key="item">
      <text>首页页面的第{{item }}条数据</text>
    </view>
  </scroll-view>
</template>

<script>
export default {
  props: {
    visible: Boolean
  },
  data () {
    return {
      list: [],
      isGetData: false
    }
  },
  methods: {
    // 模拟请求数据
    getData () {
      setTimeout(() => {
        for (let i = 0; i < 50; i++) {
          this.list.push(i + 1)
        }
        this.isGetData = true
      }, 1000)
    },
    handleClick () {
      this.$emit('change', 'mine')
    }
  },
  watch: {
    visible: {
      handler (newVal) {
        if (newVal && !this.isGetData) {
          this.getData()
        }
      },
      immediate: true
    }
  }
}

</script>

7.导航菜单组件cart

<template>
  <scroll-view class="page"
    scroll-y
    :style="{
    display: visible ? 'block' : 'none'
  }">
    <view>购物车</view>
    <button @click="handleClick">切换到消息</button>
    <view v-if="!isGetData">模拟数据加载中...</view>
    <view v-for="item in list"
      :key="item">
      <text>购物车页面的第{{item }}条数据</text>
    </view>
  </scroll-view>
</template>

<script>
export default {
  props: {
    visible: Boolean
  },
  data () {
    return {
      list: [],
      isGetData: false
    }
  },
  onLoad() {
  	console.log(this.visible)
  },
  methods: {
    // 模拟请求数据
    getData () {
      setTimeout(() => {
        for (let i = 0; i < 50; i++) {
          this.list.push(i + 1)
        }
        this.isGetData = true
      }, 1000)
    },
    handleClick () {
      this.$emit('change', 'notice')
    }
  },
  watch: {
    visible: {
      handler (newVal) {
        if (newVal && !this.isGetData) {
          this.getData()
        }
      },
      immediate: true
    }
  }
}

</script>

8.导航菜单组件mine

<template>
  <scroll-view class="page"
    scroll-y
    :style="{
    display: visible ? 'block' : 'none'
  }">
    <view>我的</view>
    <button @click="handleClick">切换到购物车</button>
    <view v-if="!isGetData">模拟数据加载中...</view>
    <view v-for="item in list"
      :key="item">
      <text>我的页面的第{{item }}条数据</text>
    </view>
  </scroll-view>
</template>

<script>
export default {
  props: {
    visible: Boolean
  },
  data () {
    return {
      list: [],
      isGetData: false
    }
  },
  methods: {
    // 模拟请求数据
    getData () {
      setTimeout(() => {
        for (let i = 0; i < 50; i++) {
          this.list.push(i + 1)
        }
        this.isGetData = true
      }, 1000)
    },
    handleClick () {
      this.$emit('change', 'cart')
    }
  },
  watch: {
    visible: {
      handler (newVal) {
        if (newVal && !this.isGetData) {
          this.getData()
        }
      },
      immediate: true
    }
  }
}

</script>

9.导航菜单组件notice

<template>
  <scroll-view class="page"
    scroll-y
    :style="{
    display: visible ? 'block' : 'none'
  }">
    <view>消息</view>
    <button @click="handleClick">切换到首页</button>
    <view v-if="!isGetData">模拟数据加载中...</view>
    <view v-for="item in list"
      :key="item">
      <text>消息页面的第{{item }}条数据</text>
    </view>
  </scroll-view>
</template>

<script>
export default {
  props: {
    visible: Boolean
  },
  data () {
    return {
      list: [],
      isGetData: false
    }
  },
  methods: {
    // 模拟请求数据
    getData () {
      setTimeout(() => {
        for (let i = 0; i < 50; i++) {
          this.list.push(i + 1)
        }
        this.isGetData = true
      }, 1000)
    },
    handleClick () {
      this.$emit('change', 'home')
    }
  },
  watch: {
    visible: {
      handler (newVal) {
        if (newVal && !this.isGetData) {
          this.getData()
        }
      },
      immediate: true
    }
  }
}

</script>

至此结束,运行时直接调用主页面就可以.

如有建议或者想法可以提出,共同改进共同学习
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐