原文地址:http://www.kevink.club/archives/276.html
### weex 主要是提供单页面应用
Weex是使用Vue和WebPack进行项目配置的。Weex创建的项目默认是只有一个入口的,也就是说,是单页面应用。对于移动开发来说,使用单页面(使用vue-router)是没有原生的页面跳转效果。在Weex的官方文档中,Weex提供了navigator内置模块来实现Web端前进、后退页面,以及iOS/Android的navigator导航效果。
项目初始化完成后, ```src``` 文件夹
```
src
|--component //组件文件夹
| |--HelloWorld.vue //hello world 组件
|--entry.js //首页
|--index.vue //页面
|--router.js //路由
```
文件 ```webpack.common.conf.js``` 完成了以下事情
* 根据```src```下的 ```entry.js``` 和 ```router.js``` 生成了 ```.temp``` 文件夹下的 ```entry.js``` 和 ```router.js```, 在 ```entry.js, router.js``` 中引入了Vue
```
const webEntry = 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)));
return {
"index": entryFile
}
}
const getEntryFileContent = (source, routerpath) => {
let dependence = `import Vue from 'vue'\n`;
dependence += `import weex from 'weex-vue-render'\n`;
let relativePluginPath = helper.rootNode(config.pluginFilePath);
let entryContents = fs.readFileSync(source).toString();
let contents = '';
entryContents = dependence + entryContents;
entryContents = entryContents.replace(/\/\* weex initialized/, match => `weex.init(Vue)\n${match}`);
if (isWin) {
relativePluginPath = relativePluginPath.replace(/\\/g, '\\\\');
}
if (hasPluginInstalled) {
contents += `\n// If detact plugins/plugin.js is exist, import and the plugin.js\n`;
contents += `import plugins from '${relativePluginPath}';\n`;
contents += `plugins.forEach(function (plugin) {\n\tweex.install(plugin)\n});\n\n`;
entryContents = entryContents.replace(/\.\/router/, routerpath);
entryContents = entryContents.replace(/weex\.init/, match => `${contents}${match}`);
}
return entryContents;
}
```
分析```weexEntry```对象 , 直接在文件```webpack.common.conf.js``` 中写死了. 我们需要改的就是这部分。
```
const weexEntry = {
'index': helper.root('entry.js')
}
```
### 修改
先说一下改后达到的效果:
* 可以方便我们进行自定义页面路径
* 尽量少的更改项目源码,以后升级了,还可以进行兼容
好了, 下面列出修改的文件及我自己新增加的一些文件夹方便区分自己新加的页面
-----
1.新增文件夹 ```src/entry``` 作为我们定义的页面js 文件夹
![2020-08-11T09:27:47.png][1]
```home.js``` 与 ```test.js```中的内容复制```entry.js```, 然后修改其中页面的路径.```千万要带着 /* global Vue */ 在 webpack.common.conf.js 中的方法中会根据这些注释替换成相应的代码, 千万不要删除。 你一般只需要修改 const App = require('@/pages/home.vue') 和 router.push('/test')即可。 ```
以下是```home.js```示例:
```
/* global Vue */
/* weex initialized here, please do not move this line */
const { router } = require('./router')
const App = require('@/pages/home.vue')
/* eslint-disable no-new */
new Vue(Vue.util.extend({el: '#root', router}, App))
router.push('/test')
````
2.新增文件夹 ```src/pages``` 作为自己新建页面的存放文件夹
3.新建文件 ```config/entry.js``` 作为放我们新建的页面js路径, 我们在```src/entry```文件夹中新建了js文件, 要在```config/entry.js``` 中添加
![2020-08-11T09:33:27.png][2]
```config/entry.js``` 中文件内容:
```
const helper = require('./helper');
const entry = {
test: helper.root('entry/test.js'),
home: helper.root('entry/home.js')
}
module.exports = {
entry
}
```
4.修改```config/webpack.common.conf.js``` 修改 11行, const weexEntry 改为 let weexEntry , 因为 const 定义完了不能更改,我们下面要将项目初始化时定义的变量插入我们自定义的页面js
```
let weexEntry = {
'index': helper.root('entry.js'),
}
// 自己定义的entry多页面
const entry = require('./entry')
//合并weexEntry 和 自己定义的entry
weexEntry = Object.assign(weexEntry, entry.entry)
```
5.修改```config/webpack.common.conf.js```修改 ```getEntryFile``` 方法
```
const routerFile = path.join(vueWebTemp, config.routerFilePath)
fs.outputFileSync(routerFile, getRouterFileContent(helper.root(config.routerFilePath)));
let weexEntryKeys = Object.keys(weexEntry);
let weexEntryValues = Object.values(weexEntry)
let back = {}
for (let key in weexEntryKeys) {
let entryFile = path.join(vueWebTemp, weexEntryKeys[key] + '.js')
let helperRoot = weexEntryValues[key]
fs.outputFileSync(entryFile, getEntryFileContent(helperRoot, routerFile))
back[weexEntryKeys[key]] = entryFile
}
let backObject = JSON.parse(JSON.stringify(back))
return backObject
```
经过以上更改,就可以使用weex定义多页面了。
重要的事情要多说几遍,我再总结一下,上述你都更改完成,那么做多页面的时候,要怎么去做:
1. 在 ```src/entry``` 文件夹下新建```home.js``` , 内容复制 ```src/entry.js``` 修改一下页面的路径
2. 在```src/pages```下新建一个vue文件, ```home.vue```, ```home.js```中的页面路径就使用本页面
3. 在```config/entry.js```中添加 ```home.js```配置
以下贴出了```config/webpack.common.conf.js```改动后的全部代码
```
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);
const hasPluginInstalled = fs.existsSync(helper.rootNode(config.pluginFilePath));
const isWin = /^win/.test(process.platform);
let weexEntry = {
'index': helper.root('entry.js'),
}
// 自己定义的entry多页面
const entry = require('./entry')
//合并weexEntry 和 自己定义的entry
weexEntry = Object.assign(weexEntry, entry.entry)
const getEntryFileContent = (source, routerpath) => {
let dependence = `import Vue from 'vue'\n`;
dependence += `import weex from 'weex-vue-render'\n`;
let relativePluginPath = helper.rootNode(config.pluginFilePath);
let entryContents = fs.readFileSync(source).toString();
let contents = '';
entryContents = dependence + entryContents;
entryContents = entryContents.replace(/\/\* weex initialized/, match => `weex.init(Vue)\n${match}`);
if (isWin) {
relativePluginPath = relativePluginPath.replace(/\\/g, '\\\\');
}
if (hasPluginInstalled) {
contents += `\n// If detact plugins/plugin.js is exist, import and the plugin.js\n`;
contents += `import plugins from '${relativePluginPath}';\n`;
contents += `plugins.forEach(function (plugin) {\n\tweex.install(plugin)\n});\n\n`;
entryContents = entryContents.replace(/\.\/router/, routerpath);
entryContents = entryContents.replace(/weex\.init/, match => `${contents}${match}`);
}
return entryContents;
}
const getRouterFileContent = (source) => {
const dependence = `import Vue from 'vue'\n`;
let routerContents = fs.readFileSync(source).toString();
routerContents = dependence + routerContents;
return routerContents;
}
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 testEntryFile = path.join(vueWebTemp, 'test.js')
// // .test/test.js src/test.js
// fs.outputFileSync(testEntryFile, getEntryFileContent(helper.root('test.js'),routerFile))
//
// console.log(testEntryFile)
// console.log(helper.root('test.js'))
//
// let o = {
// "index": "/Library/WebServer/Documents/test_vue/demo-weex-project/.temp/entry.js",
// "test": "/Library/WebServer/Documents/test_vue/demo-weex-project/.temp/test.js"
// }
// /**
// *{
// index: '/Library/WebServer/Documents/test_vue/demo-weex-project/.temp/entry.js',
// test: '/Library/WebServer/Documents/test_vue/demo-weex-project/.temp/test.js'
// }
//
// */
// console.log(o)
//
// return o
// 自己定义的入口
//console.log(weexEntry)
//
const routerFile = path.join(vueWebTemp, config.routerFilePath)
fs.outputFileSync(routerFile, getRouterFileContent(helper.root(config.routerFilePath)));
let weexEntryKeys = Object.keys(weexEntry);
let weexEntryValues = Object.values(weexEntry)
let back = {}
for (let key in weexEntryKeys) {
let entryFile = path.join(vueWebTemp, weexEntryKeys[key] + '.js')
let helperRoot = weexEntryValues[key]
// console.log(weexEntryKeys[key])
// console.log(weexEntryValues[key])
// console.log(entryFile)
// console.log(helperRoot)
fs.outputFileSync(entryFile, getEntryFileContent(helperRoot, routerFile))
back[weexEntryKeys[key]] = entryFile
}
let backObject = JSON.parse(JSON.stringify(back))
/**
* {
"index": "/Library/WebServer/Documents/test_vue/demo-weex-project/.temp/index.js",
"test": "/Library/WebServer/Documents/test_vue/demo-weex-project/.temp/test.js"
}
*/
return backObject
}
// 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();
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [helper.rootNode('src'), helper.rootNode('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
const useEslint = config.dev.useEslint ? [createLintingRule()] : []
/**
* Plugins for webpack configuration.
*/
const plugins = [
/**
* Plugin: webpack.DefinePlugin
* Description: The DefinePlugin allows you to create global constants which can be configured at compile time.
*
* See: https://webpack.js.org/plugins/define-plugin/
*/
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': config.dev.env
}
}),
/*
* Plugin: BannerPlugin
* Description: Adds a banner to the top of each generated chunk.
* See: https://webpack.js.org/plugins/banner-plugin/
*/
new webpack.BannerPlugin({
banner: '// { "framework": "Vue"} \n',
raw: true,
exclude: 'Vue'
})
];
// 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'
},
/**
* 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: {
// webpack 2.0
rules: useEslint.concat([
{
test: /\.js$/,
use: [{
loader: 'babel-loader'
}],
exclude: config.excludeModuleReg
},
{
test: /\.vue(\?[^?]+)?$/,
use: [{
loader: 'vue-loader',
options: Object.assign(vueLoaderConfig({useVue: true, usePostCSS: false}), {
/**
* important! should use postTransformNode to add $processStyle for
* inline style prefixing.
*/
optimizeSSR: false,
postcss: [
// to convert weex exclusive styles.
require('postcss-plugin-weex')(),
require('autoprefixer')({
browsers: ['> 0.1%', 'ios >= 8', 'not ie < 12']
}),
require('postcss-plugin-px2rem')({
// base on 750px standard.
rootValue: 75,
// to leave 1px alone.
minPixelValue: 1.01
})
],
compilerModules: [
{
postTransformNode: el => {
// to convert vnode for weex components.
require('weex-vue-precompiler')()(el)
}
}
]
})
}],
exclude: config.excludeModuleReg
}
])
},
/*
* Add additional plugins to the compiler.
*
* See: http://webpack.github.io/docs/configuration.html#plugins
*/
plugins: plugins
};
// Config for compile jsbundle for native.
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
}
]
},
/*
* Add additional plugins to the compiler.
*
* See: http://webpack.github.io/docs/configuration.html#plugins
*/
plugins: plugins,
/*
* Include polyfills or mocks for various node stuff
* Description: Node configuration
*
* See: https://webpack.github.io/docs/configuration.html#node
*/
node: config.nodeConfiguration
};
module.exports = [webConfig, weexConfig];
```
[1]: http://www.kevink.club/usr/uploads/2020/08/2512974030.png
[2]: http://www.kevink.club/usr/uploads/2020/08/2646791782.png