提交 518c2970 编写于 作者: hbcui1984's avatar hbcui1984

优化顶部选项卡模板,vue/nvue 复用共同的js逻辑和css样式

上级 5bbb21db
<template>
<div>
<div class="list-cell" @click="bindClick">
<div class="media-list" v-if="data.title">
<div :class="[isImgRight?'media-image-right':'',isImgLeft?'media-image-left':'']">
<text :class="['media-title',isImgRight||isImgLeft?'media-title2':'']">{{data.title}}</text>
<div v-if="showImg" :class="['image-section',isImgRight?'image-section-right':'',isImgLeft?'image-section-left':'']">
<image :class="['image-list1',isImgRight||isImgLeft?'image-list2':'']" v-if="data.image_url" :src="data.image_url"></image>
<image class="image-list3" v-if="data.image_list" :src="source.url" v-for="(source, i) in data.image_list" :key="i" />
</div>
</div>
<div class="media-foot">
<div class="media-info">
<text class="info-text">{{data.source}}</text>
<text class="info-text">{{data.comment_count}}条评论</text>
<text class="info-text">{{data.datetime}}</text>
</div>
<div class="max-close-view" @click="close">
<div class="close-view"><text class="close">×</text></div>
</div>
</div>
</div>
</div>
</div>
<div>
<div class="list-cell" @click="bindClick">
<div class="media-list" v-if="data.title">
<div :class="[isImgRight?'media-image-right':'',isImgLeft?'media-image-left':'']">
<text :class="['media-title',isImgRight||isImgLeft?'media-title2':'']">{{data.title}}</text>
<div v-if="showImg" :class="['image-section',isImgRight?'image-section-right':'',isImgLeft?'image-section-left':'']">
<image :class="['image-list1',isImgRight||isImgLeft?'image-list2':'']" v-if="data.image_url"
:src="data.image_url"></image>
<image class="image-list3" v-if="data.image_list" :src="source.url" v-for="(source, i) in data.image_list"
:key="i" />
</div>
</div>
<div class="media-foot">
<div class="media-info">
<text class="info-text">{{data.source}}</text>
<text class="info-text">{{data.comment_count}}条评论</text>
<text class="info-text">{{data.datetime}}</text>
</div>
<div class="max-close-view" @click="close">
<div class="close-view"><text class="close">×</text></div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
data: {
type: Object,
default: {}
}
},
computed: {
isImgRight() {
return this.data.article_type === 2
},
isImgLeft() {
return this.data.article_type === 1
},
showImg() {
return this.data.image_list || this.data.image_url
}
},
methods: {
close(e) {
this.$emit('close');
e.stopPropagation();
},
bindClick() {
this.$emit('click');
}
}
}
export default {
props: {
data: {
type: Object,
default: function(e) {
return {}
}
}
},
computed: {
isImgRight() {
return this.data.article_type === 2
},
isImgLeft() {
return this.data.article_type === 1
},
showImg() {
return this.data.image_list || this.data.image_url
}
},
methods: {
close(e) {
this.$emit('close');
e.stopPropagation();
},
bindClick() {
this.$emit('click');
}
}
}
</script>
<style>
.list-cell {
width: 750px;
padding: 0 30px;
}
.list-cell:active {
background-color: #eeeeee;
}
.media-list {
flex-direction: column;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #c8c7cc;
padding: 20px 0;
}
.media-image-right {
flex-direction: row;
}
.media-image-left {
flex-direction: row-reverse;
}
.media-title {
flex: 1;
}
.media-title {
lines: 3;
text-overflow: ellipsis;
font-size: 32px;
color: #555555;
}
.media-title2 {
flex: 1;
margin-top: 6px;
line-height: 40px;
}
.image-section {
margin-top: 20px;
flex-direction: row;
justify-content: space-between;
}
.image-section-right {
margin-top: 0px;
margin-left: 10px;
width: 225px;
height: 146px;
}
.image-section-left {
margin-top: 0px;
margin-right: 10px;
width: 225px;
height: 146px;
}
.image-list1 {
width: 690px;
height: 481px;
}
.image-list2 {
width: 225px;
height: 146px;
}
.image-list3 {
width: 225px;
height: 146px;
}
.media-info {
flex-direction: row;
}
.info-text {
margin-right: 20px;
color: #999999;
font-size: 28px;
}
.media-foot {
margin-top: 20px;
flex-direction: row;
justify-content: space-between;
}
.max-close-view{
justify-content:flex-end;
flex-direction: row;
height: 40px;
width: 80px;
}
.close-view {
border-style: solid;
border-width: 1px;
border-color: #999999;
border-radius: 10px;
justify-content: center;
height: 30px;
width: 40px;
}
.close {
text-align: center;
color: #999999;
font-size: 28px;
}
</style>
.list-cell {
width: 750px;
padding: 0 30px;
}
.list-cell:active {
background-color: #eeeeee;
}
.media-list {
flex: 1;
flex-direction: column;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #c8c7cc;
padding: 20px 0;
}
.media-image-right {
flex-direction: row;
}
.media-image-left {
flex-direction: row-reverse;
}
.media-title {
flex: 1;
}
.media-title {
lines: 3;
text-overflow: ellipsis;
font-size: 32px;
color: #555555;
}
.media-title2 {
flex: 1;
margin-top: 6px;
line-height: 40px;
}
.image-section {
margin-top: 20px;
flex-direction: row;
justify-content: space-between;
}
.image-section-right {
margin-top: 0px;
margin-left: 10px;
width: 225px;
height: 146px;
}
.image-section-left {
margin-top: 0px;
margin-right: 10px;
width: 225px;
height: 146px;
}
.image-list1 {
width: 690px;
height: 481px;
}
.image-list2 {
width: 225px;
height: 146px;
}
.image-list3 {
width: 225px;
height: 146px;
}
.media-info {
flex-direction: row;
}
.info-text {
margin-right: 20px;
color: #999999;
font-size: 28px;
}
.media-foot {
margin-top: 20px;
flex-direction: row;
justify-content: space-between;
}
.max-close-view {
align-items: center;
justify-content: flex-end;
flex-direction: row;
height: 40px;
width: 80px;
}
.close-view {
border-style: solid;
border-width: 1px;
border-color: #999999;
border-radius: 10px;
justify-content: center;
height: 30px;
width: 40px;
line-height: 30px;
}
.close {
text-align: center;
color: #999999;
font-size: 28px;
}
</style>
<template>
<view>
<view class="list-cell" hover-class="uni-list-cell-hover" @click="bindClick">
<view class="media-list" v-if="data.title">
<view :class="[isImgRight?'media-image-right':'',isImgLeft?'media-image-left':'']">
<text :class="['media-title',isImgRight||isImgLeft?'media-title2':'']">{{data.title}}</text>
<view v-if="showImg" :class="['image-section',isImgRight?'image-section-right':'',isImgLeft?'image-section-left':'']">
<image :class="['image-list1',isImgRight||isImgLeft?'image-list2':'']" v-if="data.image_url"
:src="data.image_url"></image>
<image class="image-list3" v-if="data.image_list" :src="source.url" v-for="(source, i) in data.image_list"
:key="i" />
</view>
</view>
<view class="media-foot">
<view class="media-info">
<text class="info-text">{{data.source}}</text>
<text class="info-text">{{data.comment_count}}条评论</text>
<text class="info-text">{{data.datetime}}</text>
</view>
<view class="max-close-view" @click.stop="close">
<view class="close-view"><text class="close">×</text></view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
data: {
type: Object,
default: function(e) {
return {}
}
}
},
computed: {
isImgRight() {
return this.data.article_type === 2
},
isImgLeft() {
return this.data.article_type === 1
},
showImg() {
return this.data.image_list || this.data.image_url
}
},
methods: {
close(e) {
this.$emit('close');
e.stopPropagation();
},
bindClick() {
this.$emit('click');
}
}
}
</script>
<style>
view {
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.list-cell {
width: 750upx;
padding: 0 30upx;
}
.uni-list-cell-hover {
background-color: #eeeeee;
}
.media-list {
flex: 1;
flex-direction: column;
border-bottom-width: 1upx;
border-bottom-style: solid;
border-bottom-color: #c8c7cc;
padding: 20upx 0;
}
.media-image-right {
flex-direction: row;
}
.media-image-left {
flex-direction: row-reverse;
}
.media-title {
flex: 1;
}
.media-title {
lines: 3;
text-overflow: ellipsis;
font-size: 32upx;
color: #555555;
}
.media-title2 {
flex: 1;
margin-top: 6upx;
line-height: 40upx;
}
.image-section {
margin-top: 20upx;
flex-direction: row;
justify-content: space-between;
}
.image-section-right {
margin-top: 0upx;
margin-left: 10upx;
width: 225upx;
height: 146upx;
}
.image-section-left {
margin-top: 0upx;
margin-right: 10upx;
width: 225upx;
height: 146upx;
}
.image-list1 {
width: 690upx;
height: 481upx;
}
.image-list2 {
width: 225upx;
height: 146upx;
}
.image-list3 {
width: 225upx;
height: 146upx;
}
.media-info {
flex-direction: row;
}
.info-text {
margin-right: 20upx;
color: #999999;
font-size: 28upx;
}
.media-foot {
margin-top: 20upx;
flex-direction: row;
justify-content: space-between;
}
.max-close-view {
align-items: center;
justify-content: flex-end;
flex-direction: row;
height: 40upx;
width: 80upx;
}
.close-view {
border-style: solid;
border-width: 1px;
border-color: #999999;
border-radius: 10upx;
justify-content: center;
height: 30upx;
width: 40upx;
line-height: 30upx;
}
.close {
text-align: center;
color: #999999;
font-size: 28upx;
}
</style>
<script>
export default {
props: {
index: {
type: Number,
default: 0
}
},
data() {
return {
tabIndex:this.index
}
},
watch:{
index(oldV,newV){
console.log(oldV,newV);
}
},
render(createElement) {
return createElement('slider', {
style: {
flex: 1
},
attrs: {
index:this.tabIndex,
index:0,
infinite: false
}
}, this.$slots.default)
......
<script>
import tabContent from './tabContent.nvue'
export default {
props: {
index: {
type: Number,
default: 0
}
},
data() {
return {
tabIndex: this.index
}
},
components: {
tabContent,
},
render(createElement) {
const vnodes = this.$slots.default;
const newVNodes = []
if (vnodes && vnodes.length) {
for (let i = 0; i < vnodes.length; i++) {
let vnode = vnodes[i]
if (!vnode || !vnode.componentOptions) {
continue
}
if (vnode.componentOptions.tag === 'tab-content') {
import tabContent from './tabContent.nvue'
export default {
props: {
index: {
type: Number,
default: 0
}
},
data() {
return {
tabIndex: this.index
}
},
components: {
tabContent,
},
render(createElement) {
const vnodes = this.$slots.default;
const newVNodes = []
if (vnodes && vnodes.length) {
for (let i = 0; i < vnodes.length; i++) {
let vnode = vnodes[i]
if (!vnode || !vnode.componentOptions) {
continue
}
if (vnode.componentOptions.tag === 'tab-content') {
const newVNode = createElement('tab-content', {
staticClass: vnode.data.staticClass,
'class':vnode.data['class'],
style:vnode.data.style
}, vnode.componentOptions.children)
const newVNode = createElement('tab-content', {
staticClass: vnode.data.staticClass,
'class': vnode.data['class'],
style: vnode.data.style
}, vnode.componentOptions.children)
if (!newVNode.data) {
newVNode.data = Object.create(null)
}
if (!newVNode.data.attrs) {
newVNode.data.attrs = Object.create(null)
}
if (!newVNode.data.props) {
newVNode.data.props = Object.create(null)
}
if (!newVNode.data.on) {
newVNode.data.on = Object.create(null)
}
newVNode.data.attrs.index = this.index
newVNode.data.props.index = this.index
newVNode.data.on.change = this._change
newVNodes.push(newVNode)
}
if (vnode.componentOptions.tag === 'tab-bar') {
if (!vnode.componentOptions.listeners) { //监听子元素传递过来的事件
vnode.componentOptions.listeners = Object.create(null)
}
vnode.componentOptions.listeners._tabBarClick = this._tabBarClick;
newVNodes.push(vnode)
}
}
}
var newNode = createElement('div', {
style: {
flex: 1,
flexDirection: 'column'
},
on: {
change2: this._change2
}
}, newVNodes);
return newNode;
},
methods: {
_tabBarClick(e) {
this.tabIndex = e.index;
this.$emit('change', e);
},
_change(e) {
this.tabIndex = e.index;
this.$emit('change', {
index:e.index
})
}
}
}
if (!newVNode.data) {
newVNode.data = Object.create(null)
}
if (!newVNode.data.attrs) {
newVNode.data.attrs = Object.create(null)
}
if (!newVNode.data.props) {
newVNode.data.props = Object.create(null)
}
if (!newVNode.data.on) {
newVNode.data.on = Object.create(null)
}
newVNode.data.attrs.index = this.index
newVNode.data.on.change = this._change
newVNodes.push(newVNode)
}
if (vnode.componentOptions.tag === 'tab-bar') {
if (!vnode.componentOptions.listeners) { //监听子元素传递过来的事件
vnode.componentOptions.listeners = Object.create(null)
}
vnode.componentOptions.listeners._tabBarClick = this._tabBarClick;
newVNodes.push(vnode)
}
}
}
var newNode = createElement('div', {
style: {
flex: 1,
flexDirection: 'column'
},
on: {
change2: this._change2
}
}, newVNodes);
return newNode;
},
methods: {
_tabBarClick(e) {
this.tabIndex = e.index;
this.$emit('change', e);
},
_change(e) {
if (this.tabIndex === e.index) {
return;
}
this.tabIndex = e.index;
this.$emit('change', {
index: e.index
})
}
}
}
</script>
<template>
<div>
<tabs @change="changeTab" :index="tabIndex">
<tab-bar>
<div class="tab-bar-item" v-for="(tabBar, t) in tabBars" :key="t" :ref="tabBar.id + t">
<text class="tab-bar-title" :class="[tabIndex === t ? 'active' : '']">{{tabBar.name}}</text>
</div>
</tab-bar>
<tab-content>
<list class="list" @loadmore="loadMore(index1)" loadmoreoffset="10" v-for="(tab,index1) in newsitems"
:key="index1">
<refresh class="refresh" @refresh="onrefresh" @pullingdown="onpullingdown" :display="refreshing ? 'show' : 'hide'">
<text class="refresh-text">{{refreshText}}</text>
</refresh>
<cell v-for="(newsitem,index2) in tab.data" :key="index2">
<media-list :data="newsitem" @close="close(index1,index2)" @click="goDetail(newsitem)"></media-list>
</cell>
<cell class="loadmore">
<text class="loadmore-text">{{tab.loadingText}}</text>
</cell>
</list>
</tab-content>
</tabs>
</div>
</template>
<script>
import tabContent from '@/components/tab-nvue/tabContent.nvue'
import tabBar from '@/components/tab-nvue/tabBar.nvue'
import tabs from '@/components/tab-nvue/tabs.nvue'
import mediaList from '@/components/tab-nvue/mediaList.nvue'
const dom = weex.requireModule('dom')
export default {
components: {
tabContent,
tabBar,
tabs,
mediaList
},
data() {
return {
refreshing: false,
refreshText: "下拉可以刷新",
tabIndex: 0,
newsitems: [],
data0: {
"datetime": "40分钟前",
"article_type": 0,
"title": "uni-app行业峰会频频亮相,开发者反响热烈!",
"source": "DCloud",
"comment_count": 639
},
data1: {
"datetime": "一天前",
"article_type": 1,
"title": "DCloud完成B2轮融资,uni-app震撼发布!",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 11395
},
data2: {
"datetime": "一天前",
"article_type": 2,
"title": "中国技术界小奇迹:HBuilder开发者突破200万",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/muwu.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 11395
},
data4: {
"datetime": "2小时前",
"article_type": 4,
"title": "uni-app 支持原生小程序自定义组件,更开放、更自由",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/cbd.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 69
},
data3: {
"article_type": 3,
"image_list": [{
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/cbd.jpg?imageView2/3/w/200/h/100/q/90",
"width": 563,
"height": 316
}, {
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/muwu.jpg?imageView2/3/w/200/h/100/q/90",
"width": 641,
"height": 360
}, {
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg?imageView2/3/w/200/h/100/q/90",
"width": 640,
"height": 360
}],
"datetime": "5分钟前",
"title": "uni-app 支持使用 npm 安装第三方包,生态更趋丰富",
"source": "DCloud",
"comment_count": 11
},
tabBars: [{
name: '关注',
id: 'guanzhu'
}, {
name: '推荐',
id: 'tuijian'
}, {
name: '体育',
id: 'tiyu'
}, {
name: '热点',
id: 'redian'
}, {
name: '财经',
id: 'caijing'
}, {
name: '娱乐',
id: 'yule'
}, {
name: '军事',
id: 'junshi'
}, {
name: '历史',
id: 'lishi'
}, {
name: '本地',
id: 'bendi'
}]
}
},
created() {
setTimeout(() => {
this.newsitems = this.randomfn();
}, 150)
},
methods: {
goDetail(e) {
uni.navigateTo({
url: '/pages/template/tabbar/detail/detail?data=' + e.title
})
},
close(index1, index2) {
uni.showModal({
content: '是否删除本条信息?',
success: (res) => {
if (res.confirm) {
this.newsitems[index1].data.splice(index2, 1);
}
}
})
},
loadMore(e) {
setTimeout(() => {
this.addData(e);
}, 1000);
},
addData(e) {
console.log("加载更多...");
if (this.newsitems[e].data.length > 30) {
this.newsitems[e].loadingText = '没有更多了';
return;
}
for (let i = 1; i <= 10; i++) {
this.newsitems[e].data.push(this['data' + Math.floor(Math.random() * 5)]);
}
},
async changeTab(e) {
this.tabIndex = e.index;
const el = this.$refs[this.tabBars[e.index].id + e.index][0]
let elSize = await this.getElSize(el);
if (elSize.left + elSize.width > 750) {
let index = e.index - 4;
let newEl = this.$refs[this.tabBars[index].id + index][0]
dom.scrollToElement(newEl, {});
return;
}
if (elSize.left < 0) {
dom.scrollToElement(el, {});
}
},
getElSize(el) { //得到元素的size
return new Promise((res, rej) => {
const result = dom.getComponentRect(el, option => {
res(option.size);
})
})
},
randomfn() {
let ary = [];
for (let i = 0, length = this.tabBars.length; i < length; i++) {
let aryItem = {
loadingText: "加载更多...",
data: []
};
for (let j = 1; j <= 10; j++) {
aryItem.data.push(this['data' + Math.floor(Math.random() * 5)]);
}
ary.push(aryItem);
}
return ary;
},
onrefresh(event) {
uni.showToast({
title: "refresh",
icon: "none"
});
this.refreshText = "正在刷新...";
this.refreshing = true;
setTimeout(() => {
console.log("刷新结束")
this.refreshing = false
}, 2000)
},
onpullingdown(event) {
if (this.refreshing) {
return;
}
if (Math.abs(event.pullingDistance) > Math.abs(event.viewHeight)) {
this.refreshText = "释放立即刷新";
} else {
this.refreshText = "下拉可以刷新";
}
}
}
}
</script>
<style>
.tab-bar-item {
width: 150px;
height: 100px;
flex-direction: column;
align-items: center;
justify-content: center;
}
.tab-bar-title {
height: 100px;
line-height: 100px;
font-size: 30px;
color: #555;
}
.active {
color: #007AFF;
}
.loadmore {
height: 70px;
width: 750px;
flex-direction: column;
justify-content: center;
}
.loadmore-text {
font-size: 30px;
text-align: center;
color: #999999;
}
.refresh {
width: 750px;
height: 70px;
flex-direction: row;
align-items: center;
justify-content: center;
}
.refresh-text {
text-align: center;
font-size: 28px;
color: #999999;
}
</style>
<template>
<view class="index">
<scroll-view id="tab-bar" class="swiper-tab" scroll-x :scroll-left="scrollLeft">
<block v-for="(tab,index) in tabs" :key="tab.id">
<view :class="['swiper-tab-list',currentTab==index ? 'on' : '']" :id="tab.id" :data-current="index" @tap="swichNav">{{tab.name}}</view>
</block>
</scroll-view>
<swiper :current="currentTab" class="swiper-box" duration="300" @change="bindChange">
<block v-for="(tab,index1) in newsitems" :key="index1">
<swiper-item>
<scroll-view class="index-bd" scroll-y @scrolltolower="loadMore(index1)">
<block v-for="(newsitem,index2) in tab" :key="index2">
<view class="tab-list">{{newsitem.name}}-{{newsitem.label}}</view>
</block>
</scroll-view>
</swiper-item>
</block>
</swiper>
</view>
<view class="index">
<scroll-view id="tab-bar" class="swiper-tab" scroll-x :scroll-left="scrollLeft">
<view v-for="(tab,index) in tabBars" :key="tab.id" :class="['swiper-tab-list',tabIndex==index ? 'active' : '']"
:id="tab.id" :data-current="index" @tap="tapTab">{{tab.name}}</view>
</scroll-view>
<swiper :current="tabIndex" class="swiper-box" duration="300" @change="changeTab">
<swiper-item v-for="(tab,index1) in newsitems" :key="index1">
<scroll-view class="list" scroll-y @scrolltolower="loadMore(index1)">
<block v-for="(newsitem,index2) in tab.data" :key="index2">
<media-list :data="newsitem" @close="close(index1,index2)" @click="goDetail(newsitem)"></media-list>
</block>
<view class="loadmore">
<text class="loadmore-text">{{tab.loadingText}}</text>
</view>
</scroll-view>
</swiper-item>
</swiper>
</view>
</template>
<script>
export default {
data() {
return {
title: 'tabbar',
scrollLeft: 0,
isClickChange: false,
currentTab: 0,
tabs: [{
name: '关注',
id: 'guanzhu'
}, {
name: '推荐',
id: 'tuijian'
}, {
name: '体育',
id: 'tiyu'
}, {
name: '热点',
id: 'redian'
}, {
name: '财经',
id: 'caijing'
}, {
name: '娱乐',
id: 'yule'
}, {
name: '军事',
id: 'junshi'
}, {
name: '历史',
id: 'lishi'
}, {
name: '本地',
id: 'bendi'
}],
newsitems: []
}
},
onLoad: function () {
this.newsitems = this.randomfn()
},
onUnload:function(){
this.scrollLeft = 0,
this.isClickChange = false,
this.currentTab = 0;
},
methods: {
bindChange: async function (e) {
let index = e.target.current;
if (this.isClickChange) {
this.currentTab = index;
this.isClickChange = false;
return;
}
let tabBar = await this.getWidth("tab-bar"),
tabBarScrollLeft = tabBar.scrollLeft;
import mediaList from '@/components/tab-nvue/mediaList.vue'
export default {
components: {
mediaList
},
data() {
return {
scrollLeft: 0,
isClickChange: false,
tabIndex: 0,
newsitems: [],
data0: {
"datetime": "40分钟前",
"article_type": 0,
"title": "uni-app行业峰会频频亮相,开发者反响热烈!",
"source": "DCloud",
"comment_count": 639
},
data1: {
"datetime": "一天前",
"article_type": 1,
"title": "DCloud完成B2轮融资,uni-app震撼发布!",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 11395
},
data2: {
"datetime": "一天前",
"article_type": 2,
"title": "中国技术界小奇迹:HBuilder开发者突破200万",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/muwu.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 11395
},
data4: {
"datetime": "2小时前",
"article_type": 4,
"title": "uni-app 支持原生小程序自定义组件,更开放、更自由",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/cbd.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 69
},
data3: {
"article_type": 3,
"image_list": [{
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/cbd.jpg?imageView2/3/w/200/h/100/q/90",
"width": 563,
"height": 316
}, {
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/muwu.jpg?imageView2/3/w/200/h/100/q/90",
"width": 641,
"height": 360
}, {
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg?imageView2/3/w/200/h/100/q/90",
"width": 640,
"height": 360
}],
"datetime": "5分钟前",
"title": "uni-app 支持使用 npm 安装第三方包,生态更趋丰富",
"source": "DCloud",
"comment_count": 11
},
tabBars: [{
name: '关注',
id: 'guanzhu'
}, {
name: '推荐',
id: 'tuijian'
}, {
name: '体育',
id: 'tiyu'
}, {
name: '热点',
id: 'redian'
}, {
name: '财经',
id: 'caijing'
}, {
name: '娱乐',
id: 'yule'
}, {
name: '军事',
id: 'junshi'
}, {
name: '历史',
id: 'lishi'
}, {
name: '本地',
id: 'bendi'
}]
}
},
onLoad: function() {
this.newsitems = this.randomfn()
},
methods: {
goDetail(e) {
uni.navigateTo({
url: '/pages/template/tabbar/detail/detail?data=' + e.title
})
},
close(index1, index2) {
uni.showModal({
content: '是否删除本条信息?',
success: (res) => {
if (res.confirm) {
this.newsitems[index1].data.splice(index2, 1);
}
}
})
},
loadMore(e) {
setTimeout(() => {
this.addData(e);
}, 1000);
},
addData(e) {
console.log("加载更多...");
if (this.newsitems[e].data.length > 30) {
this.newsitems[e].loadingText = '没有更多了';
return;
}
for (let i = 1; i <= 10; i++) {
this.newsitems[e].data.push(this['data' + Math.floor(Math.random() * 5)]);
}
},
async changeTab(e) {
let index = e.target.current;
if (this.isClickChange) {
this.tabIndex = index;
this.isClickChange = false;
return;
}
let tabBar = await this.getElSize("tab-bar"),
tabBarScrollLeft = tabBar.scrollLeft;
let width = 0;
let width = 0;
for (let i = 0; i < index; i++) {
let result = await this.getWidth(this.tabs[i].id);
width += result.width;
}
let winWidth = uni.getSystemInfoSync().windowWidth,
nowElement = await this.getWidth(this.tabs[index].id),
nowWidth = nowElement.width;
if (width + nowWidth - tabBarScrollLeft > winWidth) {
this.scrollLeft = width + nowWidth - winWidth;
}
if (width < tabBarScrollLeft) {
this.scrollLeft = width;
}
this.isClickChange = false;
this.currentTab = index; //一旦访问data就会出问题
},
getWidth: function (id) { //得到元素的宽高
return new Promise((res, rej) => {
uni.createSelectorQuery().select("#" + id).fields({
size: true,
scrollOffset: true
}, (data) => {
if (id === 'tab-bar') {
console.log("id=", id, "数据:", data)
}
res(data);
}).exec();
})
},
swichNav: async function (e) { //点击tab-bar
if (this.currentTab === e.target.dataset.current) {
return false;
} else {
let tabBar = await this.getWidth("tab-bar"),
tabBarScrollLeft = tabBar.scrollLeft; //点击的时候记录并设置scrollLeft
this.scrollLeft = tabBarScrollLeft;
this.isClickChange = true;
this.currentTab = e.target.dataset.current
}
},
loadMore: function (e) {
let last = this.newsitems[e][this.newsitems[e].length - 1].label,
name = this.newsitems[e][this.newsitems[e].length - 1].name;
for (let i = 1; i <= 10; i++) {
this.newsitems[e].push({
name: name,
label: i + last
});
}
},
randomfn() {
let ary = [];
for (let i = 0, length = this.tabs.length; i < length; i++) {
let aryItem = [];
for (let j = 1; j <= 20; j++) {
aryItem.push({
name: this.tabs[i].name,
label: j
});
}
ary.push(aryItem);
}
return ary;
}
}
}
for (let i = 0; i < index; i++) {
let result = await this.getElSize(this.tabBars[i].id);
width += result.width;
}
let winWidth = uni.getSystemInfoSync().windowWidth,
nowElement = await this.getElSize(this.tabBars[index].id),
nowWidth = nowElement.width;
if (width + nowWidth - tabBarScrollLeft > winWidth) {
this.scrollLeft = width + nowWidth - winWidth;
}
if (width < tabBarScrollLeft) {
this.scrollLeft = width;
}
this.isClickChange = false;
this.tabIndex = index; //一旦访问data就会出问题
},
getElSize(id) { //得到元素的size
return new Promise((res, rej) => {
uni.createSelectorQuery().select("#" + id).fields({
size: true,
scrollOffset: true
}, (data) => {
res(data);
}).exec();
})
},
async tapTab(e) { //点击tab-bar
if (this.tabIndex === e.target.dataset.current) {
return false;
} else {
let tabBar = await this.getElSize("tab-bar"),
tabBarScrollLeft = tabBar.scrollLeft; //点击的时候记录并设置scrollLeft
this.scrollLeft = tabBarScrollLeft;
this.isClickChange = true;
this.tabIndex = e.target.dataset.current
}
},
randomfn() {
let ary = [];
for (let i = 0, length = this.tabBars.length; i < length; i++) {
let aryItem = {
loadingText: "加载更多...",
data: []
};
for (let j = 1; j <= 10; j++) {
aryItem.data.push(this['data' + Math.floor(Math.random() * 5)]);
}
ary.push(aryItem);
}
return ary;
}
}
}
</script>
<style>
page {
display: flex;
}
page {
display: flex;
}
.index {
display: flex;
flex: 1;
flex-direction: column;
overflow: hidden;
height: 100%;
}
.index {
display: flex;
flex: 1;
flex-direction: column;
overflow: hidden;
height: 100%;
}
.index-bd {
width: 750upx;
height: 100%;
}
.list {
width: 750upx;
height: 100%;
}
.swiper-tab {
width: 100%;
white-space: nowrap;
line-height: 64upx;
height: 64upx;
}
.swiper-tab {
width: 100%;
white-space: nowrap;
line-height: 100upx;
height: 100upx;
border-bottom: 1px solid #c8c7cc;
}
.swiper-tab-list {
font-size: 30upx;
width: 150upx;
display: inline-block;
text-align: center;
color: #777777;
}
.swiper-tab-list {
font-size: 30upx;
width: 150upx;
display: inline-block;
text-align: center;
color: #555;
}
.on {
color: #FF0000;
border-bottom: 5upx solid #FF0000;
}
.active {
color: #007AFF;
}
.swiper-box {
flex: 1;
width: 100%;
height: 100%;
}
.swiper-box {
flex: 1;
width: 100%;
height: calc(100% - 100upx);
}
.swiper-box view {
text-align: center;
}
.loadmore {
height: 70upx;
width: 750upx;
flex-direction: column;
justify-content: center;
}
.tab-list {
width: 100%;
height: 90upx;
line-height: 90upx;
text-align: left;
border-bottom: 2upx solid #EFEFF4;
}
</style>
.loadmore-text {
font-size: 30upx;
text-align: center;
color: #999999;
}
</style>
<template>
<div>
<tabs @change="changeTab" :index="tabIndex">
<tab-bar>
<div class="tab-bar-item" v-for="(tabBar, t) in tabBars" :key="t" :ref="tabBar.id + t">
<text class="tab-bar-title" :class="[tabIndex === t ? 'active' : '']">{{tabBar.name}}</text>
</div>
</tab-bar>
<tab-content>
<list class="list" @loadmore="loadMore(index1)" loadmoreoffset="10" v-for="(tab,index1) in newsitems" :key="index1">
<refresh class="refresh" @refresh="onrefresh" @pullingdown="onpullingdown" :display="refreshing ? 'show' : 'hide'">
<text class="refresh-text">{{refreshText}}</text>
</refresh>
<cell v-for="(newsitem,index2) in tab.data" :key="index2">
<media-list :data="newsitem" @close="close(index1,index2)"@click="goDetail(newsitem)"></media-list>
</cell>
<cell class="loadmore">
<text class="loadmore-text">{{tab.loadingText}}</text>
</cell>
</list>
</tab-content>
</tabs>
</div>
</template>
<script>
import tabContent from '@/components/tab-nvue/tabContent.nvue'
import tabBar from '@/components/tab-nvue/tabBar.nvue'
import tabs from '@/components/tab-nvue/tabs.nvue'
import mediaList from '@/components/tab-nvue/mediaList.nvue'
const dom = weex.requireModule('dom')
export default {
components: {
tabContent,
tabBar,
tabs,
mediaList
},
created() {
setTimeout(() => {
this.newsitems = this.randomfn();
},150)
},
data() {
return {
refreshing: false,
current_rotate:0,
refreshText:"下拉可以刷新",
tabIndex: 0,
newsitems: [],
data0:{
"datetime": "40分钟前",
"article_type": 0,
"title": "uni-app行业峰会频频亮相,开发者反响热烈!",
"source": "DCloud",
"comment_count": 639
},
data1:{
"datetime": "一天前",
"article_type": 1,
"title": "DCloud完成B2轮融资,uni-app震撼发布!",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 11395
},
data2:{
"datetime": "一天前",
"article_type": 2,
"title": "中国技术界小奇迹:HBuilder开发者突破200万",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/muwu.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 11395
},
data4:{
"datetime": "2小时前",
"article_type": 4,
"title": "uni-app 支持原生小程序自定义组件,更开放、更自由",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/cbd.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 69
},
data3:{
"article_type":3,
"image_list": [{
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/cbd.jpg?imageView2/3/w/200/h/100/q/90",
"width": 563,
"height": 316
}, {
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/muwu.jpg?imageView2/3/w/200/h/100/q/90",
"width": 641,
"height": 360
}, {
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg?imageView2/3/w/200/h/100/q/90",
"width": 640,
"height": 360
}],
"datetime": "5分钟前",
"title": "uni-app 支持使用 npm 安装第三方包,生态更趋丰富",
"source": "DCloud",
"comment_count": 11
},
tabBars: [{
name: '关注',
id: 'guanzhu'
}, {
name: '推荐',
id: 'tuijian'
}, {
name: '体育',
id: 'tiyu'
}, {
name: '热点',
id: 'redian'
}, {
name: '财经',
id: 'caijing'
}, {
name: '娱乐',
id: 'yule'
}, {
name: '军事',
id: 'junshi'
}, {
name: '历史',
id: 'lishi'
}, {
name: '本地',
id: 'bendi'
}]
}
},
methods: {
goDetail(e){
uni.navigateTo({
url: './detail?data=' + e.title
})
},
onrefresh(event) {
uni.showToast({
title: "refresh",
icon:"none"
});
this.refreshText = "正在刷新...";
this.refreshing = true;
setTimeout(() => {
console.log("刷新结束")
this.refreshing = false
}, 2000)
},
onpullingdown(event) {
if(this.refreshing){
return;
}
if(Math.abs(event.pullingDistance) > Math.abs(event.viewHeight)){
this.refreshText = "释放立即刷新";
}else{
this.refreshText = "下拉可以刷新";
}
},
loadMore(e) {
setTimeout(() => {
this.addData(e);
}, 1000);
},
addData(e) {
console.log("加载更多...");
if (this.newsitems[e].data.length > 30) {
this.newsitems[e].loadingText = '没有更多了';
return;
}
for (let i = 1; i <= 10; i++) {
this.newsitems[e].data.push(this['data' + Math.floor(Math.random()*5)]);
}
},
close(index1,index2){
uni.showModal({
content: '是否删除本条信息?',
success:(res) => {
if (res.confirm) {
this.newsitems[index1].data.splice(index2,1);
}
}
})
},
async changeTab(e) {
this.tabIndex = e.index;
const el = this.$refs[this.tabBars[e.index].id + e.index][0]
let elSize = await this.getElSize(el);
if (elSize.left + elSize.width > 750) {
let index = e.index - 4;
let newEl = this.$refs[this.tabBars[index].id + index][0]
dom.scrollToElement(newEl, {});
return;
}
if (elSize.left < 0) {
dom.scrollToElement(el, {});
}
},
getElSize(el) { //得到元素的size
return new Promise((res, rej) => {
const result = dom.getComponentRect(el, option => {
res(option.size);
})
})
},
randomfn() {
let ary = [];
for (let i = 0, length = this.tabBars.length; i < length; i++) {
let aryItem = {
loadingText: "加载更多...",
data: []
};
for (let j = 1; j <= 10; j++) {
aryItem.data.push(this['data' + Math.floor(Math.random()*5)]);
}
ary.push(aryItem);
}
return ary;
}
}
}
</script>
<style>
.tab-bar-item {
width: 150px;
height: 100px;
flex-direction: column;
align-items: center;
justify-content: center;
}
.tab-bar-title {
height: 100px;
line-height: 100px;
font-size: 30px;
color: #555;
}
.active {
color: #007AFF;
}
.loadmore {
height: 70px;
width: 750px;
flex-direction: column;
justify-content: center;
}
.loadmore-text {
font-size: 30px;
text-align: center;
color: #999999;
}
.refresh {
width: 750px;
height: 70px;
flex-direction: row;
align-items: center;
justify-content: center;
}
.refresh-text{
text-align: center;
font-size: 28px;
color: #999999;
}
</style>
<template>
<view class="index">
<scroll-view id="tab-bar" class="swiper-tab" scroll-x :scroll-left="scrollLeft">
<view v-for="(tab,index) in tabBars" :key="tab.id" :class="['swiper-tab-list',tabIndex==index ? 'active' : '']"
:id="tab.id" :data-current="index" @tap="tapTab">{{tab.name}}</view>
</scroll-view>
<swiper :current="tabIndex" class="swiper-box" duration="300" @change="changeTab">
<swiper-item v-for="(tab,index1) in newsitems" :key="index1">
<scroll-view class="list" scroll-y @scrolltolower="loadMore(index1)">
<block v-for="(newsitem,index2) in tab.data" :key="index2">
<media-list :data="newsitem" @close="close(index1,index2)" @click="goDetail(newsitem)"></media-list>
</block>
<view class="loadmore">
<text class="loadmore-text">{{tab.loadingText}}</text>
</view>
</scroll-view>
</swiper-item>
</swiper>
</view>
</template>
<script>
import mediaList from '@/components/tab-nvue/mediaList.vue'
export default {
components: {
mediaList
},
data() {
return {
scrollLeft: 0,
isClickChange: false,
tabIndex: 0,
newsitems: [],
data0: {
"datetime": "40分钟前",
"article_type": 0,
"title": "uni-app行业峰会频频亮相,开发者反响热烈!",
"source": "DCloud",
"comment_count": 639
},
data1: {
"datetime": "一天前",
"article_type": 1,
"title": "DCloud完成B2轮融资,uni-app震撼发布!",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 11395
},
data2: {
"datetime": "一天前",
"article_type": 2,
"title": "中国技术界小奇迹:HBuilder开发者突破200万",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/muwu.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 11395
},
data4: {
"datetime": "2小时前",
"article_type": 4,
"title": "uni-app 支持原生小程序自定义组件,更开放、更自由",
"image_url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/cbd.jpg?imageView2/3/w/200/h/100/q/90",
"source": "DCloud",
"comment_count": 69
},
data3: {
"article_type": 3,
"image_list": [{
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/cbd.jpg?imageView2/3/w/200/h/100/q/90",
"width": 563,
"height": 316
}, {
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/muwu.jpg?imageView2/3/w/200/h/100/q/90",
"width": 641,
"height": 360
}, {
"url": "https://img-cdn-qiniu.dcloud.net.cn/uniapp/images/shuijiao.jpg?imageView2/3/w/200/h/100/q/90",
"width": 640,
"height": 360
}],
"datetime": "5分钟前",
"title": "uni-app 支持使用 npm 安装第三方包,生态更趋丰富",
"source": "DCloud",
"comment_count": 11
},
tabBars: [{
name: '关注',
id: 'guanzhu'
}, {
name: '推荐',
id: 'tuijian'
}, {
name: '体育',
id: 'tiyu'
}, {
name: '热点',
id: 'redian'
}, {
name: '财经',
id: 'caijing'
}, {
name: '娱乐',
id: 'yule'
}, {
name: '军事',
id: 'junshi'
}, {
name: '历史',
id: 'lishi'
}, {
name: '本地',
id: 'bendi'
}]
}
},
onLoad: function() {
this.newsitems = this.randomfn()
},
methods: {
goDetail(e) {
uni.navigateTo({
url: '/pages/template/tabbar/detail/detail?data=' + e.title
})
},
close(index1, index2) {
uni.showModal({
content: '是否删除本条信息?',
success: (res) => {
if (res.confirm) {
this.newsitems[index1].data.splice(index2, 1);
}
}
})
},
loadMore(e) {
setTimeout(() => {
this.addData(e);
}, 1000);
},
addData(e) {
console.log("加载更多...");
if (this.newsitems[e].data.length > 30) {
this.newsitems[e].loadingText = '没有更多了';
return;
}
for (let i = 1; i <= 10; i++) {
this.newsitems[e].data.push(this['data' + Math.floor(Math.random() * 5)]);
}
},
async changeTab(e) {
let index = e.target.current;
if (this.isClickChange) {
this.tabIndex = index;
this.isClickChange = false;
return;
}
let tabBar = await this.getElSize("tab-bar"),
tabBarScrollLeft = tabBar.scrollLeft;
let width = 0;
for (let i = 0; i < index; i++) {
let result = await this.getElSize(this.tabBars[i].id);
width += result.width;
}
let winWidth = uni.getSystemInfoSync().windowWidth,
nowElement = await this.getElSize(this.tabBars[index].id),
nowWidth = nowElement.width;
if (width + nowWidth - tabBarScrollLeft > winWidth) {
this.scrollLeft = width + nowWidth - winWidth;
}
if (width < tabBarScrollLeft) {
this.scrollLeft = width;
}
this.isClickChange = false;
this.tabIndex = index; //一旦访问data就会出问题
},
getElSize(id) { //得到元素的size
return new Promise((res, rej) => {
uni.createSelectorQuery().select("#" + id).fields({
size: true,
scrollOffset: true
}, (data) => {
res(data);
}).exec();
})
},
async tapTab(e) { //点击tab-bar
if (this.tabIndex === e.target.dataset.current) {
return false;
} else {
let tabBar = await this.getElSize("tab-bar"),
tabBarScrollLeft = tabBar.scrollLeft; //点击的时候记录并设置scrollLeft
this.scrollLeft = tabBarScrollLeft;
this.isClickChange = true;
this.tabIndex = e.target.dataset.current
}
},
randomfn() {
let ary = [];
for (let i = 0, length = this.tabBars.length; i < length; i++) {
let aryItem = {
loadingText: "加载更多...",
data: []
};
for (let j = 1; j <= 10; j++) {
aryItem.data.push(this['data' + Math.floor(Math.random() * 5)]);
}
ary.push(aryItem);
}
return ary;
}
}
}
</script>
<style>
page {
display: flex;
}
.index {
display: flex;
flex: 1;
flex-direction: column;
overflow: hidden;
height: 100%;
}
.list {
width: 750upx;
height: 100%;
}
.swiper-tab {
width: 100%;
white-space: nowrap;
line-height: 100upx;
height: 100upx;
border-bottom: 1px solid #c8c7cc;
}
.swiper-tab-list {
font-size: 30upx;
width: 150upx;
display: inline-block;
text-align: center;
color: #555;
}
.active {
color: #007AFF;
}
.swiper-box {
flex: 1;
width: 100%;
height: calc(100% - 100upx);
}
.loadmore {
height: 70upx;
width: 750upx;
flex-direction: column;
justify-content: center;
}
.loadmore-text {
font-size: 30upx;
text-align: center;
color: #999999;
}
</style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册