跑马灯组件
<template>
<div>
<div class="demo" :style="{background:c}" v-for="(c,idx) in colors" :key=idx></div>
<!-- 等同于如下写法 -->
<!-- <div class="demo" style="background:black"></div>
<div class="demo" style="background:red"></div>
<div class="demo" style="background:green"></div> -->
</div>
</template>
<script>
export default {
name: 'HorseRaceLamp',
data() {
return {
colors:['black','red','green'],
timer:null
}
},
created(){
},
computed:{
},
methods:{
},
mounted() {
// 思路: 依次删除第一个 添加到最后一个
// setTimeout(() => {
// this.colors = ['red','green','black']
// }, 1000);
this.timer = setInterval(() => {
let last = this.colors.pop()
console.log(last);
this.colors.unshift(last)
}, 1000);
},
beforeDestroy() {
// 注意定时器的销毁
clearInterval(this.timer)
this.timer = null
},
}
</script>
<style lang="scss" scoped>
.demo{
width: 50px;
height: 50px;
border: 1px solid #ddd;
}
</style>
使用 效果根据项目而定
选项卡组件(1)
<template>
<div class="container">
<ul class="titles">
<li v-for="(item,idx) in titles" :key="idx"
:class="{active:idx===active}"
@click="active=idx"
>{{item}}</li>
</ul>
<div>
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: 'TabControl',
props:{
value:{
type:Number,
required:true,
default:0
}
},
data() {
return {
titles:[],
active:0
}
},
created(){
},
computed:{
},
methods:{
},
mounted() {
console.log(this.$children)
// 当前组件中的孩子组件的个数
// this.$children[2].show = true
this.$children[this.active].show = true
},
watch: {
active(idx){
this.$children.forEach((item,j)=>{
item.show = idx === j
})
// 或者写法如下
// this.$children.forEach(item=>{
// item.show = false
// })
// this.$children[idx].show = true
// 把当前的i传递给外面
this.$emit('input',idx)
}
},
}
</script>
<style lang="scss" scoped>
.container{
width: 600px;
border: 1px solid red;
}
.container .titles{
display: flex;
justify-content: center;
align-items: center;
}
.container .titles li{
flex: 1;
text-align: center;
padding: 20px;
}
.container .titles .active{
background: red;
color: #fff;
}
</style>
<template>
<div v-show="show">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'TabItem',
props:{
label:{
type:String
}
},
data() {
return {
show:false
}
},
created(){
// 当前组件中的父亲组件中的参数
console.log(this.$parent.titles)
this.$parent.titles.push(this.label)
},
computed:{
},
methods:{
},
}
</script>
<style lang="scss" scoped>
</style>
使用组件
<template>
<div>
{{index}}
<!-- 这里的style可以设置大小 会自动添加到组件样式中 -->
<TabControl v-model="index" style="width:400px">
<tabItem label="全部"></tabItem>
<tabItem label="已购买"></tabItem>
<tabItem label="未购买"></tabItem>
<tabItem label="待发货"></tabItem>
</TabControl>
</div>
</template>
<script>
import TabControl from '../../components/TabControl';
import tabItem from '../../components/TabItem';
export default {
name: 'detailsCenter',
components:{
TabControl,
tabItem
},
data() {
return {
index:0
}
},
created(){
},
computed:{
},
methods:{
},
}
</script>
<style lang="scss" scoped>
</style>
选项卡组件(2)
<template>
<div class="container">
<div class="wrapper">
<div>
{{label}}
</div>
<ul class="item-li">
<li :class="{active:idx===active}"
v-for="(item,idx) in itemCount" :key="idx"
@click="active=idx"
></li>
</ul>
<div class="flex btns">
<div class="arrow" @click="active--">←</div>
<div class="arrow" @click="active++">→</div>
</div>
</div>
<div>
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: "TabControl",
props: {
value: {
type: Number,
required: true,
default: 0,
},
label:{
type:String,
}
},
data() {
return {
titles: [],
active: 0,
itemCount:0
};
},
methods: {},
computed: {
},
created() {},
mounted() {
console.log(this.$children);
// 当前组件中的子组件的个数
this.itemCount = this.$children.length
this.$children[0].show = true
},
watch: {
active(idx){
// 下一个、上一个的切换判断
let max = this.$children.length
if(idx < 0) this.active = max - 1
else if(idx >= max) this.active = 0
this.$children.forEach((item,j)=>{
item.show = idx === j
})
// 或者写法如下
// this.$children.forEach(item=>{
// item.show = false
// })
// this.$children[idx].show = true
// 把当前的i传递给外面
this.$emit('input',idx)
}
},
};
</script>
<style lang="scss" scoped>
.flex{
display: flex;
justify-content: center;
align-items: center;
}
.container {
width: 600px;
border: 1px solid red;
}
.container .item-li {
display: flex;
justify-content: center;
align-items: center;
}
.container .item-li li {
text-align: center;
padding: 20px;
width: 20px;
height: 20px;
border-radius: 50%;
background: #ddd;
cursor: pointer;
}
.container .item-li .active {
color: red;
background: #aaa;
}
.wrapper {
width: 100%;
display: flex;
justify-content: space-between;
align-content: center;
}
.btns{
margin: 0 10px;
cursor: pointer;
}
.btns .arrow{
padding: 0 10px;
}
</style>
使用
<template>
<div>
{{index}}
<!-- 这里的style可以设置大小 会自动添加到组件样式中 -->
<tab v-model="index" label="电影" style="width:600px">
<tabItem>想见你</tabItem>
<tabItem>火影忍者</tabItem>
<tabItem>当幸福来敲门</tabItem>
<tabItem>肖克申的救赎</tabItem>
</tab>
<tab v-model="index" label="书籍" style="width:400px">
<tabItem>平凡的世界</tabItem>
<tabItem>高级编码规范</tabItem>
<tabItem>马克思理论</tabItem>
<tabItem>邓小平思想</tabItem>
</tab>
</div>
</template>
<script>
import tab from '../../components/Tab';
import tabItem from '../../components/TabItem';
export default {
name: 'detailsCenter',
components:{
tabItem,
tab
},
data() {
return {
index:0
}
},
created(){
},
computed:{
},
methods:{
},
}
</script>
<style lang="scss" scoped>
</style>
分页的下拉框组件
基于框架使用,可根据ant 或者element 中组件来封装使用
<template>
<div>
<a-popover placement="bottomLeft" trigger="click" v-model="visible">
<template slot="content">
<ul class="list">
<li v-for="(item,idx) in options" :key="idx" @click="setVal(item)">{{item.areaName}}</li>
</ul>
{{pageIndex}}
<a-pagination size="small" v-model="pageIndex" :total="total" :page-size="pageSize" />
</template>
<template slot="title">
<span>Title</span>
</template>
<div class="sb-select-pager flex">
<div>{{currentItem.areaName}}</div>
<a-icon type="down" class="select-icon" :class="{up:visible}"></a-icon>
</div>
</a-popover>
</div>
</template>
<script>
// 注意这里需要进一步根据情况封装请求接口
import {getPageData} from '../api/test'
export default {
name: 'SelectWithPager',
props:{
value:{
type:Number || String,
default:0
},
actionUrl:{
type:String,
required:true,
}
},
data() {
return {
visible:false,
currentItem:[],
options:[],
pageIndex:1,
pageSize:10,
total:0,
}
},
created(){
// 请求分页数据
this.getList()
this.currentItem = this.options.find((r)=>{
r.id === this.value
}) || {}
},
watch: {
// 当pageIndex变化时调用函数
pageIndex(){
this.getList()
}
},
computed:{
},
methods:{
setVal(val){
this.currentItem = val
console.log(val);
this.visible = false
this.$emit("change",{...this.currentItem})
this.$emit("input",val.id)
},
// 请求分页数据
async getList(){
let params = {
page : this.pageIndex,
limit: this.pageSize,
city: '',
district:'',
r: '',
lon: '',
lat:'',
tmt: '',
secondTmt: '',
dayExposure: '',
ratio: '',
// actionUrl:actionUrl
// actions-url 地址可以传递进去 方便修改地址不同,请求的数据不同
}
let {data} = await getPageData(params)
console.log(data)
// 注意这里可以将接口中的字段改为组件所需要的字段 map转换
this.options = data.advertInfoList
this.total = Number(data.total)
}
},
}
</script>
<style lang="scss" scoped>
.flex{
display: flex;
justify-content: space-evenly;
align-items: center;
}
.list li:hover{
cursor: pointer;
background: #ccc;
}
.sb-select-pager{
width: 200px;
height: 40px;
border: 1px solid #ccc;
margin: 50px;
}
.select-icon{
transition: 0.5s;
}
.up{
transform:rotate(180deg);
}
</style>
使用
<template>change
<div>
{{select}}
<!-- 这里的 action-url 是为了请求接口时的url地址 -->
<SelectWithPager @change="change" v-model="select" action-url="/aaa/bbb/ccc"></SelectWithPager>
</div>
</template>
<script>
import SelectWithPager from '../../components/SelectWithPager'
export default {
name: 'mine',
components:{
SelectWithPager
},
data() {
return {
select:2,
}
},
created(){
},
computed:{
},
methods:{
change(val){
console.log(val);
}
},
}
</script>
<style lang="scss" scoped>
</style>