1.安装 路由模块 及 状态管理模块
npm install vue-router --save npm install vuex --save
2.自定义 TabBar 组件
src / components / TabBar.vue
TabBar.vue
<!-- 底部选项卡 --> <template> <div class="wrapper"> <div class="bar-item" @click="tabTo('home')"> <text class="bar-ic iconfont" :style="testCS">�</text> <text class="bar-txt">首页</text> </div> <div class="bar-item" @click="tabTo('topic')"> <text class="bar-ic iconfont">�</text> <text class="bar-txt">专题</text> </div> <div class="bar-item act" @click="tabTo('class')"> <text class="bar-ic iconfont">�</text> <text class="bar-txt">分类</text> </div> <div class="bar-item" @click="tabTo('shop')"> <text class="bar-ic iconfont">�</text> <text class="bar-txt">购物车</text> </div> <div class="bar-item" @click="tabTo('my')"> <text class="bar-ic iconfont">�</text> <text class="bar-txt">个人</text> </div> </div> </template> <script> var modal = weex.requireModule('modal'); export default { computed:{ testCS:function () { return this.pIndexKey == 'home'?'color:#b4282d;':'' } }, data () { return { pIndexKey:'home' } }, mounted(){ }, methods: { tabTo(_key){ if(this.pIndexKey == _key) return; this.pIndexKey = _key; this.$emit('tabTo',{ status : 'tabTo', data : { key : _key } }) } } } </script> <style scoped> .iconfont { font-family:iconfont; } .wrapper{ position: fixed; bottom: 0; left: 0;right: 0; height: 90px; flex-wrap: nowrap; flex-direction: row; justify-content: space-around; border-top- 1px; border-top-color: #d9d9d9; background-color: #fafafa; } .bar-item{ flex: 1; } .bar-txt,.bar-ic{ color:#666; text-align: center; } .bar-active{ color:#b4282d; } .bar-ic{ padding-top: 14px; font-size: 38px; } .bar-txt{ font-size: 22px; padding-top: 2px; } </style>
3.自定义 工具类
src / utils / util.js
util.js
/** * 工具类 */ let utilFunc = { initIconFont () { let domModule = weex.requireModule('dom'); domModule.addRule('fontFace', { 'fontFamily': "iconfont", 'src': "url('http://at.alicdn.com/t/font_404010_jgmnakd1zizr529.ttf')" }); }, setBundleUrl(url, jsFile) { const bundleUrl = url; let host = ''; let path = ''; let nativeBase; const isAndroidAssets = bundleUrl.indexOf('your_current_IP') >= 0 || bundleUrl.indexOf('file://assets/') >= 0; const isiOSAssets = bundleUrl.indexOf('file:///') >= 0 && bundleUrl.indexOf('WeexDemo.app') > 0; if (isAndroidAssets) { nativeBase = 'file://assets/dist'; } else if (isiOSAssets) { // file:///var/mobile/Containers/Bundle/Application/{id}/WeexDemo.app/ // file:///Users/{user}/Library/Developer/CoreSimulator/Devices/{id}/data/Containers/Bundle/Application/{id}/WeexDemo.app/ nativeBase = bundleUrl.substring(0, bundleUrl.lastIndexOf('/') + 1); } else { const matches = ///([^/]+?)//.exec(bundleUrl); const matchFirstPath = ///[^/]+/([^s]+)//.exec(bundleUrl); if (matches && matches.length >= 2) { host = matches[1]; } if (matchFirstPath && matchFirstPath.length >= 2) { path = matchFirstPath[1]; } nativeBase = 'http://' + host + '/'; } const h5Base = './index.html?page='; // in Native let base = nativeBase; if (typeof navigator !== 'undefined' && (navigator.appCodeName === 'Mozilla' || navigator.product === 'Gecko')) { // check if in weexpack project if (path === 'web' || path === 'dist') { base = h5Base + '/dist/'; } else { base = h5Base + ''; } } else { base = nativeBase + (!!path? path+'/':''); } const newUrl = base + jsFile; return newUrl; }, getUrlSearch(url,name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = url.slice(url.indexOf('?')+1).match(reg); if (r != null) { try { return decodeURIComponent(r[2]); } catch (_e) { return null; } } return null; } }; export default utilFunc;
4.其他页面
src / pages / Home / Home.vue
例如:Home.vue
<!-- 首页 --> <template> <div> <text>首页</text> </div> </template> <script> export default { name: 'Home', data: () => ({ // }), created () { // }, methods: { // } }; </script> <style scoped> </style>
5.配置 路由
src / router / index.js
index.js
/** * 配置路由 */ import Router from 'vue-router' // 首页 import Home from '../pages/Home/Home.vue' // 专题 import Topic from '../pages/Topic/Topic.vue' // 分类 import Class from '../pages/Class/Class.vue' // 购物车 import Shop from '../pages/Shop/Shop.vue' // 个人 import My from '../pages/My/My.vue' Vue.use(Router) export default new Router({ // mode: 'abstract', routes: [ { path: '/', redirect: '/home' }, { path: '/home', component: Home }, { path: '/topic', component: Topic }, { path: '/class', component: Class }, { path: '/shop', component: Shop }, { path: '/my', component: My } ] })
6.主页面 引入 工具类 及 TabBar 组件
src / App.vue
App.vue
<!-- 主页面 --> <template> <div class="app-wrapper"> <router-view class="r-box"></router-view> <tab-bar @tabTo="onTabTo"></tab-bar> </div> </template> <script> var modal = weex.requireModule('modal'); import util from './utils/util.js'; import tabBar from './components/TabBar.vue'; export default { data () { return { // } }, components: { 'tab-bar': tabBar }, created () { util.initIconFont(); }, methods: { onTabTo(_result){ let _key = _result.data.key || ''; this.$router && this.$router.push('/'+_key) } } } </script> <style> body{ margin: 0; padding: 0; background-color: #f4f4f4; color:#333; } </style> <style scoped> .app-wrapper{ background-color: #f4f4f4; } .r-box{ position: absolute; top:0; left: 0; right: 0; bottom: 0; } </style>
7.定义 入口文件 entry.js
src / entry.js
/** * 入口文件 */ import App from './App.vue' import router from './router' // 创建应用程序实例 new Vue(Vue.util.extend({ el: '#root', router }, App)); router.push('/');
8.在 webpack.config.js 中配置 入口文件
/***************** 配置入口文件 start *****************/ const entry = {index: pathTo.resolve('src', 'entry.js')}; const weexEntry = {index: pathTo.resolve('src', 'entry.js')}; /****************** 配置入口文件 end ******************/
9.项目 结构
10.效果图
注:#root 报错
如果你使用的是 entry.js 作为入口文件,就需要删除 webpack.conf.js 文件中的 getEntryFileContent 和 walk 方法。