Weex的多頁面配置

前言

Weex是使用Vue和WebPack進行項目配置的。Weex創建的項目默認是隻有一個入口的,也就是說,是單頁面應用。對於移動開發來說,使用單頁面(使用vue-router)是沒有原生的頁面跳轉效果。在Weex的官方文檔中,Weex提供了navigator內置模塊來實現Web端前進、後退頁面,以及iOS/Android的navigator導航效果。

Weex的多頁面配置

我使用的是最近的weex創建的項目,下面是weex的項目結構。


我們打開weebpack.config.js。

// You can see all the config in `./configs`.
const  buildPlugins = require('./configs/plugin');
let webpackConfig;
module.exports = env => {
  switch (env.NODE_ENV) {
    case 'prod':
    case 'production':
      webpackConfig = require('./configs/webpack.prod.conf');
      break;
    case 'test':
    case 'testing':
      webpackConfig = require('./configs/webpack.test.conf');
      break;
    case 'plugin':
      buildPlugins();
    case 'common':
      webpackConfig = require('./configs/webpack.common.conf');
      break;
    case 'release':
      webpackConfig = require('./configs/webpack.release.conf');
      break;
    case 'dev':
    case 'development':
    default:
      webpackConfig = require('./configs/webpack.dev.conf');
  }
  return webpackConfig;
}

可以看到webpackConfig的配置根據特定環境放在不同的文件。

我們打開configs文件夾下的webpack.common.conf.js,這個文件是配置weex和web的入口。weex把移動端和web端的webpack入口和出口配置分爲weex和web。

weexConfig的入口和出口配置(iOS/Android)

我們在configs/webpack.common.conf.js下找到weexEntry。

const weexEntry = {
  'index': helper.root('entry.js'),
  'login': helper.root('login.js'),
}

這裏我已經創建了src/login.js文件,這個文件和src/entry.js的內容是一樣的,只是對應的vue不同。和entry.js一樣都會在使用web/index.html作爲頁面渲染。下面是src/login.js。

/*global Vue*/

/* weex initialized here, please do not move this line */
const router = require('./router');
const App = require('@/login.vue');
/* eslint-disable no-new */
new Vue(Vue.util.extend({el: '#root', router}, App));
router.push('/');


以上就是weexConfig的入口配置(iOS/Android的webpack入口配置)。weex已經幫我們配置好weexConfig的出口配置。

const weexConfig = {
  entry: weexEntry,
  output: {
    path: path.join(__dirname, '../dist'),
    filename: '[name].js'
  },
  /**
   * Options affecting the resolving of modules.
   * See http://webpack.github.io/docs/configuration.html#resolve
   */
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': helper.resolve('src')
    }
  },
  /*
   * Options affecting the resolving of modules.
   *
   * See: http://webpack.github.io/docs/configuration.html#module
   */
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [{
          loader: 'babel-loader'
        }],
        exclude: config.excludeModuleReg
      },
      {
        test: /\.vue(\?[^?]+)?$/,
        use: [{
          loader: 'weex-loader',
          options: vueLoaderConfig({useVue: false})
        }],
        exclude: config.excludeModuleReg
      }
    ]
  },

webConfig的入口和出口配置(web)

我們在configs/webpack.common.conf.js下找到webEntry。

// The entry file for web needs to add some library. such as vue, weex-vue-render
// 1. src/entry.js 
// import Vue from 'vue';
// import weex from 'weex-vue-render';
// weex.init(Vue);
// 2. src/router/index.js
// import Vue from 'vue'
const webEntry = getEntryFile();

上面有一些註釋,說明webConfig的入口文件需要導入Vue和weex-vue-render模塊。我們找到getEntryFile()函數。

const getEntryFile = () => {
  const entryFile = path.join(vueWebTemp, config.entryFilePath)
  const routerFile = path.join(vueWebTemp, config.routerFilePath)
  fs.outputFileSync(entryFile, getEntryFileContent(helper.root(config.entryFilePath), routerFile));
  fs.outputFileSync(routerFile, getRouterFileContent(helper.root(config.routerFilePath)));
  const loginFilePath = 'login.js'
  const loginFile = path.join(vueWebTemp, loginFilePath)
  fs.outputFileSync(loginFile, getEntryFileContent(helper.root(loginFilePath), routerFile));

  return {
    index: entryFile,
    login: loginFile,
  }
}

這個函數的entryFile使用的是path/vueWebTemp/config.entryFilePath的文件,routerFile使用的是path/vueWebTemp/config.routerFilePath的文件。

我們找到vueWebTemp和config.entryFilePath。

const path = require('path');
const fs = require('fs-extra');
const webpack = require('webpack');
const config = require('./config');
const helper = require('./helper');
const glob = require('glob');
const vueLoaderConfig = require('./vue-loader.conf');
const vueWebTemp = helper.rootNode(config.templateDir);

config是當前目錄下的config.js文件。下面是config.js的部分代碼。

const path = require('path');
const ROOT = path.resolve(__dirname, '..');
const ip = require('ip').address();
const config = {
  root: ROOT,
  // webpack-dev-server
  pluginConfigPath: 'plugins/plugins.json',
  pluginFilePath: 'plugins/plugins.js',
  // router
  routerFilePath: 'router.js',
  // common
  templateDir: '.temp',
  entryFilePath: 'entry.js',
  // Module exclude from compile process
  excludeModuleReg: /node_modules(?!(\/|\\).*(weex).*)/,

我們看到templateDir是項目中的.temp文件,entryFilePath是entry.js,routerFilePath是router.js。

在getEntryFile()的entryFile就是項目下的.temp/entry.js。routerFile就是項目下的.temp/router.js。


我們按照上面的例子,創建login.js的webConfig入口文件。下面是login.js代碼,它和entry.js的代碼是一樣的,只是對於的vue不同。

import Vue from 'vue'
import weex from 'weex-vue-render'
/*global Vue*/

weex.init(Vue)
/* weex initialized here, please do not move this line */
const router = require('./router');
const App = require('@/login.vue');
/* eslint-disable no-new */
new Vue(Vue.util.extend({el: '#root', router}, App));
router.push('/');

我們看到之前註釋說明需要導入的vue和weex-vue-render模塊。

按照getEntryFile()函數的指示,我們需要把入口文件和router文件同步到src目錄的入口文件和router文件內容。(helper的root是src文件夾)。以下是helper.js的代碼內容。

// Helper functions
const path = require('path');
const ROOT = path.resolve(__dirname, '..');

const root = (args) => {
  return path.join(ROOT, 'src', args);
}
const rootNode = (args) => {
  return path.join(ROOT, args);
}

const resolve = (dir) => {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  root,
  rootNode,
  resolve
}

由於weex之前已經幫我們在src創建了entry.js和router.js,我們之前在配置weexConfig時已經創建了login.js。所以這段代碼是把.temp文件和src的文件內容同步。最後我們在getEntryFile()返回我們的loginFile入口文件。

以上就是webConfig的入口配置,weex已經幫我們配置好webConfig的出口配置。

// Config for compile jsbundle for web.
const webConfig = {
  entry: Object.assign(webEntry, {
    'vendor': [path.resolve('node_modules/phantom-limb/index.js')]
  }),
  output: {
    path: helper.rootNode('./dist'),
    filename: '[name].web.js'
  },

編譯src文件到dist文件

我們需要編譯src文件到dist文件才能生效。在命令行輸入weex compile src dist編譯src文件夾到dist文件夾。

進行navigator跳轉

由於web和iOS/Android是分開配置的,所以它們的URL分別對應web的http跳轉和iOS/Android生成的本地文件的js跳轉。

methods: {
    login () {
      navigator.push({url:this.getJumpBaseUrl('login')})
    },
    getJumpBaseUrl(toUrl) {  
        var bundleUrl = weex.config.bundleUrl;  
        bundleUrl = new String(bundleUrl);  
        var nativeBase;  
        var native;  
        if (WXEnvironment.platform === 'Android') {  
            nativeBase = 'file://assets/dist/';  
            native = nativeBase + toUrl + ".js";  
        } else if (WXEnvironment.platform === 'iOS') {  
            nativeBase = bundleUrl.substring(0, bundleUrl.lastIndexOf('/') + 1);  
            native = nativeBase + toUrl + ".js";  
        } else {  
            var host = 'localhost:8081';  
            var matches = /\/\/([^\/]+?)\//.exec(bundleUrl);  
            if (matches && matches.length >= 2) {  
                host = matches[1];  
            }  
  
            //此處需注意一下,tabbar 用的直接是jsbundle 的路徑,但是navigator是直接跳轉到新頁面上的.  
            if (typeof window === 'object') {  
                nativeBase = 'http://' + host + '/';  
            } else {  
                nativeBase = 'http://' + host + '/';  
            }  
  
            native = nativeBase + toUrl + ".html";  
        }  
        return native;  
    }  
  }




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章