1.安装vue-cli脚手架
npm i vue-cli -g
2.通过vue-cli创建基本webpack的vue并初始化项目
vue init webpack <project_name>
cd <project_name>
npm i
启动项目
npm run dev
3.加入框架vux
npm install vux --save
vux2必须配合vux-loader使用, 请在build/webpack.base.conf.js里参照如下代码进行配置:
const vuxLoader = require('vux-loader')
const webpackConfig = originalConfig // 原来的 module.exports 代码赋值给变量 webpackConfig
module.exports = vuxLoader.merge(webpackConfig, {
plugins: ['vux-ui']
})
4.项目中用到的插件
less,
less-loader,
vux-loader,
vue-jsonp,
vue-scroller
app.vue
<template>
<div id="app">
<ViewBox>
<!--header-->
<XHeader
class="header"
slot="header"
:left-options="{showBack:false,backText:'back'}"
title="网易"
>
<div slot="left">直播</div>
<div slot="right">搜索</div>
</XHeader>
<!--tabs-->
<sc :lock-y="true">
<Tab class="tab">
<TabItem selected>推荐</TabItem>
<TabItem>要闻</TabItem>
<TabItem>游戏</TabItem>
<TabItem>科技</TabItem>
<TabItem>娱乐</TabItem>
<TabItem>体育</TabItem>
</Tab>
</sc>
<scroller
class="my-scroller"
:on-refresh="refresh"
:on-infinite="infinite"
refresh-text="loading"
ref="myRef"
>
<!--图片滑动-->
<Swiper
:list="swiperList"
v-model="swiperIndex"
:loop="true"
>
</Swiper>
<!--向上滑动队列-->
<div class="my-marquee">
<Marquee
direction="up"
>
<MarqueeItem v-for="list in marqueeList">{{list.title}}</MarqueeItem>
</Marquee>
</div>
<!--新闻列表-->
<Panel :list="dataList">
</Panel>
<Panel :list="moreDataList">
</Panel>
</scroller>
<!--footer-->
<Tabbar slot="bottom">
<TabbarItem>
<img slot="icon" src="./assets/demo/icon_nav_button.png">
<span slot="label">首页</span>
</TabbarItem>
<TabbarItem>
<img slot="icon" src="./assets/demo/icon_nav_msg.png">
<span slot="label">推荐</span>
</TabbarItem>
<TabbarItem>
<img slot="icon" src="./assets/demo/icon_nav_article.png">
<span slot="label">我的</span>
</TabbarItem>
</Tabbar>
</ViewBox>
</div>
</template>
<script>
import {
ViewBox, XHeader, Tabbar, TabbarItem, Tab,
TabItem,Scroller as sc,Swiper,Marquee, MarqueeItem,Panel} from 'vux';
var refreshKey = ['A','B01','B02','B03','B04','B05','B06','B07','B08','B09','B010'];
var key = 0;
var start = 0;
var end = start + 9;
var keyValue='A';
var initLoaded = false;
function getRefreshKey() {
key++;
if(key == refreshKey.length){
key = 0;
}
keyValue = refreshKey[key];
}
export default {
name: 'app',
components: {
ViewBox,
XHeader,
Tabbar,
TabbarItem,
Tab,
TabItem,
sc,
Swiper,
Marquee,
MarqueeItem,
Panel
},
created(){
var url = 'http://3g.163.com/touch/jsonp/sy/recommend/0-9.html';
this.$jsonp(url).then(data => {
console.log(data)
/*
* {
url: 'javascript:',
img: 'https://static.vux.li/demo/1.jpg',
title: '送你一朵fua'
}
* */
// 图片滑动数据
this.swiperList = data.focus.filter(item =>{
return item.addata === null && item.picInfo[0]
}).map(item =>{
return {
url:item.link,
img:item.picInfo[0].url,
title:item.title,
}
});
// 滑动新闻数据
this.marqueeList = data.news.filter(item =>{
return item.addata === null && item.picInfo[0]
}).map(item =>{
return {
title: item.title,
}
});
// 新闻列表
this.dataList = data.list.filter(item =>{
return item.addata === null && item.picInfo[0]
}).map(item =>{
return {
src:item.picInfo[0] && item.picInfo[0].url,
title: item.title,
desc: item.title,
url: item.link,
}
});
initLoaded = true;
})
},
data(){
return {
swiperList: [],
swiperIndex: 1,
dataList: [],
marqueeList:[],
moreDataList:[],
}
},
methods:{
refresh(){
// 下拉更新数据
getRefreshKey();
var url = 'http://3g.163.com/touch/jsonp/sy/recommend/0-9.html';
this.$jsonp(url,{
miss: '00',
refresh: keyValue
}).then(data=>{
console.log(data);
this.dataList = data.list.filter(item =>{
return item.addata === null && item.picInfo[0]
}).map(item =>{
return {
src:item.picInfo[0] && item.picInfo[0].url,
title: item.title,
desc: item.title,
url: item.link,
}
});
this.$refs.myRef.finishPullToRefresh();
// 刷新提示
this.$vux.toast.text(`一共刷新了${this.dataList.length}条数据`, 'top');
})
},
infinite(){
// 上拉加载更多数据
if (!initLoaded) {
this.$refs.myRef.finishInfinite();
return;
}
console.log(222)
var url = `http://3g.163.com/touch/jsonp/sy/recommend/${start}-${end}.html`;
this.$jsonp(url, {
miss: '00',
refresh: keyValue
}).then(data => {
console.log(data)
// 上拉加载更多
setTimeout(()=>{
var datalist= data.list.filter(item =>{
return item.addata === null && item.picInfo[0]
}).map(item =>{
return {
src:item.picInfo[0].url,
title: item.title,
desc: item.title,
url: item.link,
}
});
this.moreDataList = this.moreDataList.concat(datalist);
start += 10;
end = start + 9;
this.$refs.myRef.finishInfinite();
},1000)
})
}
}
}
// http://3g.163.com/touch/jsonp/sy/recommend/0-9.html
// http://3g.163.com/touch/jsonp/sy/recommend/'+start+'-'+end+'.html'
</script>
<style lang="less">
@import '~vux/src/styles/reset.less';
html, body {
height: 100%;
width: 100%;
overflow-x: hidden;
}
#app {
height: 100%;
.header{
position: absolute;
left:0;
top:0;
width:100%;
z-index:111;
}
.my-scroller{
top:90px;
}
.tab{
margin-top:46px;
width:600px;
}
.my-marquee{
margin:10px;
.vux-marquee-box li{
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
}
.weui-media-box__hd,.weui-media-box__hd img{
width:102px;
height:78px;
}
.weui-media-box__bd{
height:78px;
}
.loading-layer{
padding-bottom:90px;
}
}
</style>
main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import VueScroller from 'vue-scroller'
import { ToastPlugin } from 'vux'
import VueJsonp from 'vue-jsonp'
Vue.config.productionTip = false
Vue.use(ToastPlugin)
Vue.use(VueScroller)
Vue.use(VueJsonp);
/* eslint-disable no-new */
new Vue({
el: '#app',
template: '<App/>',
components: { App }
})
package.json
{
"name": "news",
"version": "1.0.0",
"description": "sdfds",
"author": "fengwenxin",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"unit": "jest test/unit/specs --coverage",
"test": "npm run unit",
"build": "node build/build.js"
},
"dependencies": {
"vue": "^2.5.2",
"vue-jsonp": "^0.1.7",
"vue-scroller": "^2.2.4",
"vux": "^2.7.3",
"vux-loader": "^1.1.24"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-jest": "^21.0.2",
"babel-loader": "^7.1.1",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"eventsource-polyfill": "^0.9.6",
"express": "^4.14.1",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"jest": "^21.2.0",
"less": "^2.7.3",
"less-loader": "^4.0.5",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-loader": "^2.0.8",
"rimraf": "^2.6.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"url-loader": "^0.5.8",
"vue-jest": "^1.0.2",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"vue"
],
"moduleNameMapper": {
"^@/(.*)$": "<rootDir>/src/$1"
},
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/babel-jest",
".*\\.(vue)$": "<rootDir>/node_modules/vue-jest"
},
"setupFiles": [
"<rootDir>/test/unit/setup"
],
"mapCoverage": true,
"coverageDirectory": "<rootDir>/test/unit/coverage",
"collectCoverageFrom": [
"src/**/*.{js,vue}",
"!src/main.js",
"!**/node_modules/**"
]
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}