weex 项目开发(四)项目框架搭建 及 自定义 TabBar 组件

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 方法。

原文地址:https://www.cnblogs.com/crazycode2/p/7988978.html