简介:
Weex 是一套简单易用的跨平台开发方案,能以 web 的开发体验构建高性能、可扩展的 native 应用,使用 Vue 作为上层框架,打造三端一致的 native 应用
BUI-Weex 是一套专门为 Weex 前端开发者打造的一套高质量UI框架
npm install -g weex-toolkit
npm install -g webpack
npm install -g serve
# weex init projectDemo
#npm install
# npm run dev 和 npm run serve
# 浏览器: http://localhost:8080/index.html
JAVA_HOME:C:\Java\jdk1.8.0_20
Path:;%JAVA_HOME%\bin;
CLASSPATH :.%JAVA_HOME%\lib\tools.jar
3.2 下载安装Android SDKForce https://..sources to be fetched using http://...
将这一项勾选上,就可以了mirrors.neusoft.edu.cn 端口:80
android-mirror.bugly.qq.com 端口:8080
ANDROID_HOME:E:\AndroidDevelopTool\android-sdk-windows
path:%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools
android -h
和adb
命令npm install -g weexpack
weexpack create appName&&cd appName && npm install
weexpack platform add android
weexpack platform add ios
android.config.json
或者 ios.config.json
中指定的weex bundle文件 WeexBundle, 改为你的起始文件:如 index.js / main.js
打包:weexpack run android
(开启模拟器,夜神安装目录:nox_adb.exe connect 127.0.0.1:62001,Android SDK/platform-tools目录:adb connect 127.0.0.1:62001)
1) 下载gradle-2.14.1-all.zip
复制到appName\platforms\android\gradle\wrapper
目录
2) gradle-wrapper.properties
修改distributionUrl =gradle-2.14.1-all.zip
3) touch $ANDROID_HOME/licenses/android-sdk-license
8933bad161af4178b1185d1a37fbf41ea5269c55
4)修改 appName\platforms\android\build.gradle
5)更改项目目录下的android.config.json
AppName: 应用名
AppId: application_id 包名
SplashText: 欢迎页上面的文字
WeexBundle: 指定的weex bundle文件(支持文件名和url的形式)
weexpack build ios
weexpack build web&&weexpack run web
1)netstat -aon|findstr “49157” 端口占用
2)端口号 默认为8080
npm run serve
config.devServer = {
historyApiFallback: true,
// progress:true,
inline:true,
contentBase: pathTo.join(__dirname, ''),
compress: true,
hot: true,
host: '0.0.0.0',
port:'8082',
public: ip + ':8082/web'
// publicPath: '/dist/',
};
webpack --watch
{ "presets": ["es2015"] }
touch .gitignore
.idea/
node_modules/
temp/
dist/
function walk(dir) {
dir = dir || '.';
const directory = pathTo.join(__dirname, 'src', dir);
fs.readdirSync(directory)
.forEach((file) => {
const fullpath = pathTo.join(directory, file);
const stat = fs.statSync(fullpath);
const extname = pathTo.extname(fullpath);
const name = pathTo.join(dir, pathTo.basename(file, extname));
if (stat.isFile() && extname !== '.vue' && extname !== '.we') {
entry[name] = fullpath + '?entry=true';
weexEntry[name] = fullpath + '?entry=true';
return;
}
if (directory.indexOf("\\src\\") > 0) {
return;
}
if (stat.isFile() && extname === '.vue' || extname === '.we') {
if (!fileType) {
fileType = extname;
}
if (fileType && extname !== fileType) {
console.log('Error: This is not a good practice when you use ".we" and ".vue" togither!');
}
if (extname === '.vue') {
let entryFile = pathTo.join(vueWebTemp, dir, pathTo.basename(file, extname) + '.js');
fs.exists(pathTo.join(__dirname, 'src', dir, name + '.js'), function(exists) { //异步
if (!exists) {
fs.outputFileSync(pathTo.join(entryFile), getEntryFileContent(entryFile, fullpath));
}else {
fs.copy(pathTo.join(__dirname, 'src', dir, name + '.js'), pathTo.join(entryFile), function(err) {
if (err) return console.error(err)
});
}
})
if (!entry[name]) {
entry[name] = pathTo.join(__dirname, entryFile) + '?entry=true';
weexEntry[name] = fullpath + '?entry=true';
}
}
} else if (stat.isDirectory() && file !== 'build' && file !== 'include') {
const subdir = pathTo.join(dir, file);
walk(subdir);
}
});
}
使用别名
const resolve={
extensions: ['.js', '.vue', '.json'],
alias: {
// 'vue$': 'vue/dist/vue.esm.js',
'@': pathTo.resolve(__dirname, './src')
},
modules: [
pathTo.join(__dirname, './node_modules')
]
}
resolve:resolve
新建页面 mkdir src\views&& touch src\views\Hello.vue
<template>
<div class="wrapper" @click="jump('/')"><text>主页</text></div>
</template>
新建路由跳转方法 mkdir src\mixins&& touch src\mixins\index.js
export default {
methods: {
jump(to){
// jump:function(to) {
console.log('to=' + to);
if (this.$router) {
this.$router.push(to)
}
}
}
}
新建路由文件 touch src/router.js
import Router from 'vue-router';
import Hello from '@/views/Hello.vue';
import index from '@/index.vue';
Vue.use(Router)
export default new Router({
mode: 'abstract',
routes: [
{ path: '/hello', component: Hello },
{ path: '/', redirect: '/index' }
]
})
新建入口文件 touch src/index.js
import App from './index.vue'
import router from './router'
import mixins from './mixins'
Vue.mixin(mixins)
var vm = new Vue(Vue.util.extend(
{ el: '#root',
router,
}, App))
router.push('/')
编辑主页(html) src/index.vue
<template>
<div class="wrapper" @androidback="back">
<image :src="logoUrl" class="logo"></image>
<text class="title" @click="update">Hello </text>
<text class="desc">开始干活吧!!!</text>
<list class="list">
<cell class="cell" @click="jump('/hello')">
<text>hello</text>
</cell>
<cell class="cell" @click="jump('/')">
<text>主页</text>
</cell>
</list>
<router-view style="flex:1"></router-view>
</div>
</template>
<script>
export default {
data: {
logoUrl: 'http://img1.vued.vanthink.cn/vued08aa73a9ab65dcbd360ec54659ada97c.png',
target: 'World',
count: 0
},
methods: {
update: function(e) {
this.count++;
this.target = '美女 ' + this.count;
console.log('target:', this.target)
},
back: function() {
this.$router.back()
}
}
}
</script>
<style>
.wrapper {
align-items: center;
margin-top: 120px;
}
.title {
padding-top: 40px;
padding-bottom: 40px;
font-size: 48px;
}
.logo {
width: 360px;
height: 156px;
}
.desc {
padding-top: 20px;
color: #888;
font-size: 24px;
}
</style>
touch src\vuexStore.js
import Vuex from 'vuex'
if (WXEnvironment.platform !== 'Web') {
Vue.use(Vuex)
}
const vuexStore = new Vuex.Store({
state: {
dic: {}
},
mutations: {
addDic(state, dics) {
state.dic=Object.assign(state.dic, dics);
}
},
getters: {
getDic: (state) => (group) => {
// return `${state.dic}`;
return state.dic;
}
}
})
export { vuexStore as default};
// dic = store.state.dic[group],
// // store.commit("addDic",group);
修改 src/index.js
import App from './index.vue'
import router from './router'
import mixins from './mixins'
import store from './vuexStore'
import { sync } from 'vuex-router-sync'
sync(store, router)
Vue.mixin(mixins)
var vm = new Vue(Vue.util.extend(
{ el: '#root',
store,
router,
}, App))
router.push('/')
修改 src/index.vue
<cell class="cell" @click="jump('/vuexStore')">
<text>vuex</text>
</cell>
修改 src/router.js
import vuexStore from '@/views/vuexStore.vue'
//....
{ path: '/vuexStore', component: vuexStore },
touch src/views/vuexStore.vue
<template>
<div class="wrapper" @androidback="back">
<text class="title" @click="update">添加字典</text>
<text class="desc" @click="getDic">获取字典:</text>
</div>
</template>
<script>
export default {
data() {
return {
target: 'World',
count: 0,
dic: {}
}
},
methods: {
update: function(e) {
this.count++;
this.target = '美女 ' + this.count;
this.$store.commit("addDic", { 'code': this.count, 'lable': this.target });
},
back: function() {
this.$router.back()
},
getDic: function() {
this.dic = {
'aa': this.$store.getters.getDic("parm"),
'bb': this.dic = this.$store.state.dic
};
}
}
}
</script>
安卓打包:
报错信息为:Observed package id ‘build-tools;19.0.0’ in inconsistent location
修改 sdk\build-tools\android4.4目录名为sdk\build-tools\19.0.0
编辑index.js
const stream = weex.requireModule('stream')
Vue.fetch = stream.fetch;
Vue.prototype.$fetch = stream.fetch;
编辑 index.vue
Vue.fetch({
method: 'GET',
url: 'https://cnodejs.org/api/v1/topics',
data: {},
type: 'json',
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }
}, function(res) {
console.log(JSON.stringify(res));
})
mkdir src\fliter&touch src\fliter\index.js
export function double (a) {
return a*a
}
编辑 index.js
import * as filters from './filters'
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
编辑index.vue(使用过滤器)
<text class="title">点击次数*2: 8 </text>
touch src/main.vue
<template>
<div>这是main页
<text @click="gotoPage('main')">返回index页</text>
</div>
</template>
<script>
import mixins from './mixins'
Vue.mixin(mixins)
</script>
touch src/utils.js
export function getBaseURL(vm) {
var bundleUrl = weex.config.bundleUrl;
console.log(`eex.config=${JSON.stringify(weex.config)}`);
var nativeBase;
if (isAndroid()) {
console.log('isAndroid');
nativeBase = 'file://assets/dist/';
} else if (isiOS()) {
console.log('isiOS');
// 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 {
console.log('web');
var host = 'localhost:8080';
var matches = /\/\/([^\/]+?)\//.exec(bundleUrl);
if (matches && matches.length >= 2) {
host = matches[1];
}
nativeBase = 'http://' + host + '/' + '/build/';
}
console.log('nativeBase=' + nativeBase);
var h5Base = './weex.html?page=./dist/web/';
// in Native
var base = nativeBase;
if (typeof window === 'object') {
// in Browser or WebView
base = h5Base;
}
console.log(`getPlatform()=${getPlatform()}`);
console.log(`base=${base}`);
return base
}
export function isAndroid() {
if (getPlatform() == 'Android' || getPlatform() == 'android') {
return true;
} else {
return false;
}
}
export function isiOS() {
console.log(getPlatform() == 'iOS');
return getPlatform() == 'iOS';
}
export function isWeb() {
console.log(getPlatform() == 'Web');
return getPlatform() == 'Web';
}
//{"env":{"platform":"android","osVersion":"4.4.4","appVersion":"1.0","weexVersion":"0.9.5","deviceModel":"HUAWEI ALE-CL00","appName":"com.kunion.weex","deviceWidth":"720","deviceHeight":"1184","scale":"2.0"}}
//{"bundleUrl":"http://localhost:8080/weex.html?page=./dist/web/entry.js","platform":"Web","weexVersion":"0.10.0","userAgent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36","appName":"Netscape","appVersion":null,"osName":"Chrome","osVersion":"56.0.2924.87","deviceModel":"unknown","deviceWidth":750,"deviceHeight":1245}
export function getPlatform() {
if (weex.config.env) {
return weex.config.env.platform;
}
return weex.config.platform;
}
export function getScreenWidth() {
return weex.config.deviceWidth;
}
export function getScreenHeight() {
return weex.config.deviceHeight;
}
修改 mixins/index.js
import { getBaseURL, isAndroid } from '../utils';
const event = weex.requireModule('event');
const navigator = weex.requireModule('navigator')
export default {
methods: {
jump(to){
// jump:function(to) {
console.log('to=' + to);
if (this.$router) {
this.$router.push(to)
}
},
gotoPage: function(page) {
var url = getBaseURL(weex) + page + '.js';
if (typeof window === 'object') {
url = getBaseURL(weex) + page;
// url = url.replace(/\.\/dist\/web\//, '/dist/').replace(/\/web\//, '');
url = url.replace(/\.\/dist\/web\//, '').replace(/\/web\//, '');
}
url = url.replace(/\/weex\.html/, '\/index.html');
// navigator.push({
// url: url,
// animated: "true"//页面压入时需要动画效果
// }, event => { console.log(event); })
event.openURL(url);
}
}
}
修改 index.vue
<cell class="cell" @click="gotoPage('main')">
<text>main页</text>
</cell>
修改 index.html
(function() {
function getUrlParam(key) {
var reg = new RegExp('[?|&]' + key + '=([^&]+)')
var match = location.search.match(reg)
return match && match[1]
};
var page = getUrlParam('page');
var defaultPage = '/dist/index.js';
if (page) {
page.replace(/\.\/dist\/web\//, '/dist/')
if (typeof window === 'object') {
var extName = page.substr(page.length - 3, 3)
if (extName !== '.js') {
page = '/dist/' + page + '.js'
}
}
} else {
page = defaultPage;
}
var bundle = document.createElement('script')
// only for web
bundle.src = page.replace(/\.js$/, '.web.js')
document.body.appendChild(bundle)
})();
编辑 vuexStore.js
import Vuex from 'vuex'
// Vue.use(Vuex)
if (WXEnvironment.platform !== 'Web') {
Vue.use(Vuex)
}
const storage = weex.requireModule('storage')
var state = {
dic: {}
}
// 从storage里加载数据
storage.getItem('STORAGE_KEY', event => {
if (event.result == "success" && event.data){
// 这里可以使用extend等方法,这里仅举例说明
var data = JSON.parse(event.data);
state.dic = data.dic;
}
})
// 存储plugin,存储感兴趣的数据,store里数据太多,没必要全持久化
const storagePlugin = store => {
store.subscribe((mutation, {dic}) => {
storage.setItem('STORAGE_KEY', JSON.stringify({dic}),event => {
console.log('cache success');
})
})
}
export default new Vuex.Store({
plugins:[storagePlugin],
state: state,
mutations: {
addDic(state, dics) {
state.dic=Object.assign(state.dic, dics);
},
addAllDic(state,stateObject){
state=stateObject;
}
},
getters: {
getDic: (state) => (group) => {
// return `${state.dic}`;
return state.dic;
}
}
})
touch main.js
import App from './main.vue'
// import router from './router'
import mixins from './mixins'
import store from './vuexStore'
// import { sync } from 'vuex-router-sync'
const stream = weex.requireModule('stream')
Vue.fetch = stream.fetch;
Vue.prototype.$fetch = stream.fetch;
import * as filters from './filters'
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
// sync(store, router)
Vue.mixin(mixins)
var vm = new Vue(Vue.util.extend({
el: '#root',
store,
// router,
}, App))
// router.push('/')
main.vue
<template>
<div class="wrapper">
<text style=' padding-top: 40px; padding-bottom: 40px; font-size: 48px;'>这是main页</text>
<text @click="gotoPage('index')">返回index页</text>
<text @click="getDic()">获取字典</text>
<!--<image :src="logoUrl" resize="cover" class="background" @load="onload"></image>-->
<slider class="slider" interval="3000" auto-play="true" infinite="true">
<div class="frame" v-for="img in imageList">
<image class="image" resize="cover" :src="img.src"></image>
</div>
<indicator class="indicator"></indicator>
</slider>
<div style="background-color:#1b90f7;margin:30px;border-radius:10px;flex-direction: row;height:40px;border-color:#1b90f7;border-width:1px">
<text style="align-items: center;justify-content: center;flex:3;text-align:center;vertical-align:center">写点啥</text>
<input style="align-items: center;justify-content: center;flex:9;padding-left:5px;text-align:center" type="text" placeholder="你是超人么?" return-key-type="default" class="input" @change="" @return="" @input="" />
</div>
<div class="example">
<text class="label">逛逛呗</text>
<switch checked="true" disabled="false" @change="onchange"></switch>
</div>
<text class="label">下拉加载</text>
<scroller class="scroller">
<refresh class="refresh" @refresh="onrefresh" @pullingdown="onpullingdown" :display="refreshing ? 'show' : 'hide'">
<text class="indicator">Refreshing ...</text>
</refresh>
<div class="cell" v-for="num in lists">
<div class="panel">
<text class="text"></text>
</div>
</div>
</scroller>
</div>
</template>
<script>
// import mixins from './mixins'
// Vue.mixin(mixins)
export default {
data() {
return {
checked: false,
logoUrl: 'https://img.alicdn.com/tps/TB1z.55OFXXXXcLXXXXXXXXXXXX-560-560.jpg',
imageList: [
{ src: 'https://gd2.alicdn.com/bao/uploaded/i2/T14H1LFwBcXXXXXXXX_!!0-item_pic.jpg' },
{ src: 'https://gd1.alicdn.com/bao/uploaded/i1/TB1PXJCJFXXXXciXFXXXXXXXXXX_!!0-item_pic.jpg' },
{ src: 'https://gd3.alicdn.com/bao/uploaded/i3/TB1x6hYLXXXXXazXVXXXXXXXXXX_!!0-item_pic.jpg' }
],
refreshing: false,
lists: [1, 2, 3, 4, 5]
}
},
methods: {
onchange(event) {
console.log(`onchage, value: ${event.value}`)
this.checked = event.value
},
onrefresh(event) {
console.log('is refreshing')
modal.toast({ message: 'refresh', duration: 1 })
this.refreshing = true
setTimeout(() => {
this.refreshing = false
}, 2000)
},
onpullingdown(event) {
console.log('is onpulling down')
modal.toast({ message: 'pulling down', duration: 1 })
},
getDic() {
console.log(this.$store.state.dic);
}
},
mounted: function() {},
ready: function() {}
}
</script>
<style scoped>
.wrapper {
align-items: center;
margin-top: 120px;
}
.logo {
width: 360px;
height: 156px;
}
.desc {
padding-top: 20px;
color: #888;
font-size: 24px;
}
.background {
width: 1000px;
height: 1000px;
}
.example {
flex-direction: row;
justify-content: flex-start;
margin-top: 60px;
}
.label {
font-size: 40px;
line-height: 60px;
width: 350px;
color: #666;
text-align: right;
margin-right: 20px;
}
.info {
font-size: 30px;
line-height: 60px;
color: #BBB;
margin-left: 10px;
}
.image {
width: 700px;
height: 700px;
}
.slider {
margin-top: 25px;
margin-left: 25px;
width: 700px;
height: 700px;
border-width: 2px;
border-style: solid;
border-color: #41B883;
}
.title {
position: absolute;
top: 20px;
left: 20px;
padding-left: 20px;
width: 200px;
color: #FFFFFF;
font-size: 36px;
line-height: 60px;
background-color: rgba(0, 0, 0, 0.3);
}
.frame {
width: 700px;
height: 700px;
position: relative;
}
.indicator {
width: 700px;
height: 700px;
item-color: green;
item-selected-color: red;
item-size: 50px;
position: absolute;
top: 300px;
left: 0px;
color: #888888;
font-size: 42px;
text-align: center;
}
.panel {
width: 600px;
height: 250px;
margin-left: 75px;
margin-top: 35px;
margin-bottom: 35px;
flex-direction: column;
justify-content: center;
border-width: 2px;
border-style: solid;
border-color: #DDDDDD;
background-color: #F5F5F5;
}
.text {
font-size: 50px;
text-align: center;
color: #41B883;
}
</style>
文档地址:http://dev.bingocc.com/buiweex/docs/env.html
第一步:安装 bui-weex-toolkit
npm install -g bui-weex-toolkit
npm update -g bui-weex-toolkit
第二步:安装IDE
推荐:对于命令行集成的比较好的IDE: WebStorm 和 Visual Studio Code
WebStorm安装插件:Setting->plugins->输入: VueJS \ Weex \ Sass
创建项目: bui-weex create buiWeexDemo&&cd buiWeexDemo &&npm install
npm install --save node-sass --registry=https://registry.npm.taobao.org --disturl=https://npm.taobao.org/dist --sass-binary-site=http://npm.taobao.org/mirrors/node-sass
npm run dev
npm run serve
集合到一条命令:
安装依赖:npm install -g concurrently
package.json: "start":"concurrently \"npm run dev\" \"npm run serve\"",
新建 touch weex.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Weex Preview</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-touch-fullscreen" content="yes">
<meta name="format-detection" content="telephone=no, email=no">
<link rel="stylesheet" href="./web/assets/style.css">
<script src="./web/assets/url.js"></script>
<script src="./web/assets/qrcode.js"></script>
<script src="./node_modules/vue/dist/vue.js"></script>
</head>
<body>
<h1>Weex Preview</h1>
<div id="app"></div>
<template id="app-template">
<div id="app">
<div class="mock-phone">
<div class="inner">
<iframe id="preview" src="./index.html"></iframe>
</div>
<div class="camera"></div>
<div class="earpiece"></div>
<div class="home-btn"></div>
</div>
<div id="qrcode">
<h2>QRCode</h2>
<a :href="val" target="_blank"><canvas ref="canvas" width="200" height="200"></canvas></a>
<p class="bundle-url"><a :href="val" target="_blank"></a></p>
</div>
</div>
</template>
<script>
console.log('QR CODE URL: ' + url)
new Vue({
el: '#app',
template: '#app-template',
data: { val: url },
mounted: function () {
var qrcodedraw = new QRCodeLib.QRCodeDraw()
qrcodedraw.draw(this.$refs.canvas, this.val, function () {})
}
})
</script>
</body>
</html>
移动 web/index.html 至根目录
修改 web/assets/url.js
var url = protocol + hostname + port + location.pathname.replace(/\/weex\.html$/, '/').replace(/\/$/, '/dist/index.js')
访问主页: localhost:8082
或 localhost:8082/index.html
访问 二维码页面 localhost:8082/weex.html
npm install --save node-sass --registry=https://registry.npm.taobao.org --disturl=https://npm.taobao.org/dist --sass-binary-site=http://npm.taobao.org/mirrors/node-sass
npm install --save glob&&npm install --save-dev bui-weex copy-webpack-plugin sass-loader style-loader
创建页面(首页,列表,详情)
touch src/index.vue src/list.vue src/detail.vue src/index.js src/list.js src/detail.js
*.vue
<template>
<div @androidback="back">
<bui-header title="标题栏" :leftItem="leftItem" :rightItem="rightItem" @leftClick="back" @rightClick="rightclick" @centerClick="centerclick">
</bui-header>
<bui-image width="260px" height="260px" src="https://img.alicdn.com/tps/TB1z.55OFXXXXcLXXXXXXXXXXXX-560-560.jpg"></bui-image>
<bui-image src="/image/demo.jpg" width="300px" height="300px"></bui-image>
<text class="title">主页</text>
<list>
<cell class="cell" @click="gotoPage('list')">
<text>列表页</text>
</cell>
<cell class="cell" @click="gotoPage('detail')">
<text>详情页</text>
</cell>
</list>
</div>
</template>
<script>
import buiweex from 'bui-weex';
export default {
data: function() {
return {
leftItem: { icon: 'icon-back' },
rightItem: { text: '更多' }
}
},
methods: {
back1: function() {
this.$router.back()
},
back: function() {
buiweex.pop();
buiweex.toast('left')
},
rightclick: function() {
buiweex.toast('right')
},
centerclick: function() {
buiweex.toast('center')
}
}
}
</script>
<style lang="sass" src="bui-weex/src/css/buiweex.scss"></style>
<style>
.wrapper {
align-items: center;
margin-top: 120px;
}
.title {
padding-top: 40px;
padding-bottom: 40px;
font-size: 48px;
}
</style>
*.js
import App from './index.vue'
import router from './router'
import mixins from './mixins'
import store from './vuexStore'
import { sync } from 'vuex-router-sync'
import buiweex from 'bui-weex';
const stream = weex.requireModule('stream')
Vue.fetch = stream.fetch;
Vue.prototype.$fetch = stream.fetch;
import * as filters from './filters'
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
sync(store, router)
Vue.mixin(mixins)
var vm = new Vue(Vue.util.extend({
el: '#root',
store,
router,
}, App))
router.push('/')
package.json
"start":"concurrently \"npm run watch\" \"npm run serve\""
Webpack.config.js
{
test: /\.(scss|sass)$/,
// include: helpers.root('src', 'app'),
loader: 'style-loader!css-loader!sass-loader'
}
touch src/mixins.js
var buiweex=require("bui-weex");
components: {
'bui-header':buiweex.buiHeader,
'bui-icon': buiweex.buiIcon,
'bui-button': buiweex.buiButton,
'bui-image':buiweex.buiImage,
'bui-content':buiweex.buiContent,
'bui-content-scroll':buiweex.buiContentScroll
}
文件拷贝 webpack.config.js
const copy = require('copy-webpack-plugin');
// 文件拷贝插件,将图片和字体拷贝到dist目录
var copyPlugin = new copy([
{from: './src/image', to: "./image"},
{from: './node_modules/bui-weex/src/font', to: "./font"}
])
plugins: [bannerPlugin, copyPlugin]
修改 node_modules/bui-weex/src/components/bui-icon.vue
var bundleUrl = weex.config.bundleUrl;
var url = bundleUrl.split('/').slice(0, -1).join('/');
url += '/font/iconfont.ttf';
// if (typeof window === 'object') {
if (weex.config.env.platform == 'Android'||weex.config.env.platform == 'android') {
url = 'local://dist/font/iconfont.ttf';
}
var domModule = weex.requireModule("dom");
domModule.addRule('fontFace', {
'fontFamily': 'iconfont',
'src': "url('" + url + "')"
});
package com.alibaba.weex;
import android.net.Uri;
import android.text.TextUtils;
import android.widget.ImageView;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.taobao.weex.WXEnvironment;
import com.taobao.weex.WXSDKManager;
import com.taobao.weex.adapter.IWXImgLoaderAdapter;
import com.taobao.weex.common.WXImageStrategy;
import com.taobao.weex.dom.WXImageQuality;
public class ImageAdapter implements IWXImgLoaderAdapter {
public ImageAdapter() { }
@Override
public void setImage(final String url, final ImageView view,
WXImageQuality quality, final WXImageStrategy strategy) {
WXSDKManager.getInstance().postOnUiThread(new Runnable() {
@Override
public void run() {
if (view == null || view.getLayoutParams() == null) {
return;
}
if (TextUtils.isEmpty(url)) {
view.setImageBitmap(null);
return;
}
String temp = url;
temp = temp.replace("../", "");
temp = temp.replace("./", "");
temp = temp.replace("file://assets/", "file:///android_asset/");
System.out.println("原始图片 URL "+url);
if (view.getLayoutParams().width <= 0 || view.getLayoutParams().height <= 0) {
return;
}
if (!TextUtils.isEmpty(strategy.placeHolder)) {
Picasso.Builder builder = new Picasso.Builder(WXEnvironment.getApplication());
Picasso picasso = builder.build();
picasso.load(Uri.parse(strategy.placeHolder)).into(view);
view.setTag(strategy.placeHolder.hashCode(), picasso);
}
Picasso.with(WXEnvironment.getApplication())
.load(temp)
.into(view, new Callback() {
@Override
public void onSuccess() {
if (strategy.getImageListener() != null) {
strategy.getImageListener().onImageFinish(url, view, true, null);
}
if (!TextUtils.isEmpty(strategy.placeHolder)) {
((Picasso) view.getTag(strategy.placeHolder.hashCode())).cancelRequest(view);
}
}
@Override
public void onError() {
if (strategy.getImageListener() != null) {
strategy.getImageListener().onImageFinish(url, view, false, null);
}
}
});
}
}, 0);
}
}