整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

webapp调用html5+的获取定位遇到的一些问题

webapp调用html5+的获取定位遇到的一些问题及解决

最近项目需要用到获取手机自身的定位系统,一直反馈定位不好用。网络状况不好的时候定位不准确。今天难得有时间修改了一下功能。但是遇到了一些问题,我用了一些方法解决,希望看了这个文章的有更好办法的大神们,可以指点指点我。

1.定位不准

使用官方提供的getCurrentPosition,默认的坐标系是国际的坐标系,用在百度地图上会有误差。可以使用官方提供的配置解决。

如在getCurrentPosition方法的第三个参数加上

provider: "baidu",

coordsType: "bd09ll",//百度坐标系

'enableHighAccuracy': true,//开启精准定位

2.实时获取定位

使用官方提供的watchPosition方法 ,实时监控坐标的变化。

可用参数

provider: "baidu",

coordsType: "bd09ll",

'enableHighAccuracy': true,

'maximumAge': 2000,

等等 其他我暂时没有 用

3.实时获取定位的watchPosition方法出现的问题

用hbuilder 基座 调试 获取经纬度一切没问题,但是打正式app包后,发现watchPosition方法第一次监听没有问题,后面监听的经纬度全是(5e-324,5e-324)。无法正确获取定位。后来发现只要我打开监听,出去走几步就可以正常监听。正常效果和打开地图一样,地图上的标注点会和我走路的轨迹一样,一直变化。

4.解决方法。

监听发现经纬度全是(5e-324,5e-324)时候调用getCurrentPosition方法,


部分代码:

this.dwtimer=plus.geolocation.watchPosition(

position=> {

//坐标获取

//console.log(JSON.stringify(position));

let p=position;

//console.log(p.coords.latitude);

let lat=p.coords.latitude;

let lng=p.coords.longitude;

this.sb.jwdlr=lng + "," + lat;

let province=

p.address.province==undefined ? "" : p.address.province;

let city=p.address.city==undefined ? "" : p.address.city;

let district=

p.address.district==undefined ? "" : p.address.district;

let street=p.address.street==undefined ? "" : p.address.street;

let streetNum=

p.address.streetNum==undefined ? "" : p.address.streetNum;

let poiName=p.address.poiName==undefined ? "" : p.address.poiName;

this.sb.device_place=

city + "" + district + "" + street + "" + streetNum + "" + poiName;

console.log(lat);

if(lat!=5e-324&&lng!=5e-324&&lat!="5e-324"&&lng!="5e-324"){

this.center={

lng,

lat

};

this.choosedLocation={

province,

city,

district,

addr: street + streetNum,

lng,

lat

};

}else{

this.hqdw();

}





},

e=> {

console.log(e.message);

this.hqdw();

plus.nativeUI.toast("请打开GPS定位" + e.message);

},

{

provider: "baidu",

coordsType: "bd09ll",

'enableHighAccuracy': true,

'maximumAge': 2000,

}

);

型 H5 项目开发的思考

不知不觉已经是第四次接手负责每年的大型 H5 活动,这也意味着 4 年啦啊啊啊啊,哎时间过得真是太快,也是应该做一点总结了。

每年都会有大型的 H5 项目上线,这一些项目的逻辑在一般的情况下,它们的差别不会很大,但是每一次都会有不同的样式、条件和玩法。如果每一次大活动都是写死逻辑且不可复用,下一次 H5 项目过来又再写一次其实就是很没有必要的事情。

如果能把这一些做过的组件做成通用可配置的,即插即用。那么肯定是会极大的提高开发效率,同时项目的稳定性也有保证。只不过组件的代码逻辑就会比较复杂,开发难度会比较高,就单单组件内的一个按钮就需要考虑到这个按钮的颜色,大小,按钮内的字体各种样式和背景色以及这按钮是不是设计状态变化,若有还要考虑这一个状态变化的逻辑或者是一些联动的可能。所以,一个通用组件需要考虑和实现的逻辑就很多。

举个例子,比如今年的 H5 有一个 “我的奖品” 模块 ( 页面 or 弹窗 ),这个模块里面有的奖品的信息展示、时间的展示、数量的展示以及底部还有一些其他的按钮。以下是我截取两次不同的活动的“我的奖品”列表展示模块。

这两种样式的组件,大致的框架上都是一样的,点击侧边栏的 “我的奖励” 和 “我的背包”,只是展现形式和展示数据类型以及按钮的点击事件是不一样的。

所以,如果第三次 H5 ,或者以后的 H5 都写一遍这样的东西意义不大。所以,这样使用频率比较高的模块,就必须和业务方讨论。我们可以把这样的模块定出一个基本的交互和原型,统一做成一个通用列表展示组件,这个组件必须支持通用样式的展示,也需要支持特殊的样式展示,例如下面的情况

最左边的也就是正常的列表样式,右边的就是一些特殊的卡片和文字样式,所以,一个组件需要考虑的东西有很多。

这里叫列表展示组件而不叫“我的奖品组件”的原因是:我们只需要通过参数控制它需要展示什么的内容、标题是什么、按钮名称是什么、点击之后的逻辑是什么,而不是只局限于我的奖品列表,它也可以用于其他数据的展示。同时,这样的通用组件可以适用于各种 H5 。组件拿来即用或者用于一些 H5 自动生成的平台,只要根据文档传参数就可以了。

通过 config 控制具体的展示名字还有按钮id的标记区分事件,data 初始化组件的列表,与业务区分开来这里就变成了一个很纯粹的列表展示组件,可以展示任意的数据,只要按照格式传参就行。这里只是写一个很简单的 DEMO ,后面会提到入参和函数绑定。

规划公共组件

拿到设计稿之后找出通用的模块,再根据类似模块之间的差异定出一个通用的规则。下面是本次大型 H5 的设计稿总览:

第一大类:分组赛,资格赛,弹窗,规则和投票等

第二大类:冲刺赛,总决赛,PK模块等

此次大型 H5 的分为了几个大阶段,分组赛,资格赛,冲刺赛和总决赛。看上去是非常多内容的,所以需要找出相似的模块,再和业务侧沟通从这几个赛段来看,可以抽离成组件的是

  1. TAB 切页组件
  2. 进度条组件
  3. 列表记录组件
  4. 时间轴组件
  5. 排行榜组件
  6. 倒计时组件
  7. 投票组件
  8. 侧边栏悬浮组件
  9. pk 模块组件
  10. 我的信息展示组件
  11. 顶部组件
  12. 吸底组件
  13. 按钮组件
  14. 主播展示组件

这里就拿一部分的组件描述一下实现思路,全部写的话就太多了,而且有些地方逻辑实现上也是比较像的。

组件的通用参数

组件传入参数

一个通用组件所需要的配置参数一般归纳为几种,最重要的是这个组件的所有需要使用的值,也就是这个初始化参数。其次,是这个组件的一些样式配置或者是全局参数辅助使用,还有一些情况需要特定的属于这个组件的 key 。当然,不是说样式和全局参等等是不重要的参数,而是根据业务的需求来定,可能样式的参数才是重点这个也是可能的,具体的还得从业务或者这个组件本身的性质考虑,只是在做组件的时候优先考虑功能的实现。以下是我封装通用组件的一个习惯,分别绑定的参数是 data, styleForm, commonStyle, global, componentKey。以下是一个组件绑定参数和方法的例子:

<template>
  <head-section
    :data="headData"
    :global="global"
    :styleForm="headConfig"
    :commonStyle="headCommonStyle"
    :componentKey="headComponentKey"
    @methods="headMethods"
  />
</template>

<script>
export default {
	data(){
		return {
			// 全局配置
			global: {},
			
			// 顶部组件配置
			headData: {},	
			headConfig: {},
			headCommonStyle: {},
			headComponentKey: {},
		}
	}
}
</script>

data 组件初始化参数

data 是这个组件传入的初始化参数或者是渲染组件的所有数据,类型是 Object 。组件可以用初始化参数通过 ajax 获取数据也可以通过 class 执行初始化逻辑或者是直接将数据绑定在这个 data 中。

<script>
// 组件
export default {
props: {
  data: {
    type: Object,
    default: ()=> ({
    	// list:[],                example
    	// total: 10               example
    }),
   },
}
</script>

styleForm 组件的配置参数

styleForm 这个是组件的配置信息,比如这个组件的一些背景、样式信息以及一些固定的数据不会发生变化的数据。数据格式类型是 Object 。

<script>
// 组件
export default {
props: {
  styleForm: {
    type: Object,
    default: ()=> ({
    	// styles: {},                example
    	// bg: './images/xx.png'      example
    }),
   },
}
</script>

commonStyle 通用样式配置参数

commonForm 这个参数是通用的样式配置,比如,控制这个组件的宽、高以及背景色等等。这个我们在自己在独立开发的 H5 的时候,会按照这样的参数格式配置。目的是让组件更加通用,适用于不同的地方,比如一些 H5 的自动生成平台。 因为,在互联网大厂里 H5 的开发如果是比较简单的页面,是不会单独用人力去开发的,而是通过平台配置生成 H5。我们需要做的就是提供各种各样的组件,让业务同学去配置使用。所以,平台的配置是以每个功能模块划分,commonForm 可以接入他们的平台的接口数值,直接在平台上控制这个组件的宽、高、是否居中等等的基础样式。

<script>
// 组件
export default {
props: {
  commonStyle: {
    type: Object,
    default: ()=> ({
    	// width: 300,                example
    	// height: 20                 example
    }),
   },
}
</script>

global 全局属性

全局属性指的是这个项目的唯一标记,适用于项目中的任意一个地方。比如说这个项目的 id ,他可能在做上报操作或者在请求接口的时候需要带上这个参数。那么就由 global 这个参数统一接收。类型也是 Object 。

<script>
// 组件
export default {
props: {
  global: {
    type: Object,
    default: ()=> ({
    	// page_id: 111,                example
    }),
   },
}
</script>

componentKey

componentKey 是组件的标记,主要用于在做区分组件的时候,使用比如上报数据。同时也可以用于一些非常特定的逻辑,提供临时的解决方法。举个非常简单例子:业务方需要画 10 个圆且背景都是白色,突然间提出要在第 9 个圆中某个位置加上一个黑色的点,其他不变。 这样既不合理也不通用还砍不掉的需求,临时的解决方法就是通过 key 写一个 if else ,之后再说。

<script>
// 组件
export default {
props: {
  componentKey: {
    type: [String,Number],
    default: 1,                     // example
   },
}
</script>

@methods 方法绑定

在组件内通过输出按钮 id 或者事件类型,由上一层组件进行执行特定逻辑,这样的好处是通用的样式和 DOM 与 JavaScript 分离,不含有业务逻辑一下次也可以直接复用这个组件,不需要再去改。

组件

<template>
    <div class="head-section" style="padding: 0px 0px">
        <div
            class="lottery-btn"
            @click="onClickBtn('lottery', 'normal')"
        ></div>
        <div
            class="nav-btn rule-btn"
            @click="onClickBtn('rule', 'page')"
        ></div>
    </div>
</template>
<script>
export default {
  methods: {
    onClickBtn(id, type='page', eventParams={}) {
      this.$emit('methods',{
        id: type,
        value: eventParams
      });
    },
  },
}
</script>

父级组件

<script>
export default {
  methods: {
    headMethods($Event) {
      const { id, value }=$Event;
      const page=(params)=> { 
        this.goPage();
      };
      const anchor=(params)=> {
        this.goAnchor();
      };
      const clickEventMap={
        'page': page,
        'anchor': anchor,
      };
      // 区分不同事件类型 传参
      clickEventMap[id](value);
    },
    goAnchor(params) {
    	// ...
    },
    goPage(params) {
    	// ...
    }
  },
}
</script>

页面顶部组件

组件布局和实现:

组件封装思路

首先从功能上看,这个组件只能适用于独立开发的 H5 ,它不适合 H5 生成平台。或者说这样的组件在 H5 生成平台完全没有意义。因为,左边的 icon 和右边按钮列表,他们在 H5 生成平台里面,这些按钮都是靠使用者自己手动配置的地方。例如: 左边的 icon 就是使用一个按钮组件拖拽进去,再加上一个跳转事件。 右边的 btn-list 可以看成是 3 个独立按钮,也和上面一样用一个按钮组件拖拽进去,加上一个跳转事件,再连续配置 3 次。

但是,这一次是独立开发,所以只能按照可复用定制模版的思路来实现。需要考虑的地方是:

  1. 头图片支持背景配置
  2. 左边的按钮支持背景设置,文案设置和显隐设置。
  3. 右侧的按钮列表中支持单个按钮的背景设置,文案设置和显隐设置以及支持再新增加多个按钮的情况下可复用样式 。

如图:对应的每个模块使用一个 ID 作为区分,其中 btn-list 包含以 btn-x 为唯一的标记,内容就是控制这个按钮的背景,显隐和文案。

之后再通过 headData 来渲染 btn-list ,数据格式为:

<script>
export default {
  data() {
    return {
    	headData:[
    		{
    			id: 'btn-1',
    			value: {
    				url: '...'
    			}
    		},
    		{
    			id: 'btn-2',
    			value: {
    				url: '...'
    			}
    		}
    		....
    	]
    }
  },
}
</script>

它的核心思想就是通过 ID 关联数据,通过 ID 关联配置。这有点像是数据库里面的主键,可以根据这个主键可以查询或者关联查找其他的数据表。

细节实现要点

写一个通用的方法,在后面如果有新增的按钮,可以直接通过传参 (第几个按钮) 控制按钮的位置。

@function head-nav-btn-top($number) {
  $top: 15;
  $boxHeight: 46;
  @if($number==1){
    @return 385;
  }
  @return 385 + (($top + $boxHeight) * ($number -  1));
}
// .class
top: remit(head-nav-btn-top(1));
top: remit(head-nav-btn-top(2));
top: remit(head-nav-btn-top(3));

锚点跳转到参数指定位置

headMethods($Event){
  const { id, value }=$Event;
  
  if (id==='lottery-btn') {
  	const scrollTop=document.documentElement.scrollTop || document.body.scrollTop;
  	window.scrollTo(scrollTop, this.$refs[value].offsetTop);
  }
},

倒计时组件

组件布局和实现:

组件封装思路

倒计时组件在逻辑上是比较简单的,更多需要考虑倒计时的展示样式,因为在 H5 里面,每种设计的风格或者业务需求不一样,不可能一直沿用一种样式的倒计时,比如这样

所以需要考虑的点是:

  1. 倒计时的多种展示样式和展示形式,比如是否需要拼接标题和展示天数或者秒数。
  2. 倒计时在结束的时候需要执行的下一步逻辑。

细节实现要点

在计算倒计时的方法上有两种,第一种是获取本地手机时间再写一个 inteval 函数递减计算,第二种是使用 interval 每秒都向服务器进行时间获取计算出剩余时间。 这里我一般会选择后面那种,因为,首先本地时间不一定是正确的,也有可能是人为的去修改了系统的时间,其次,本地的 interval 延迟时间不一定准确。比如我们设定 1000 毫秒执行,但是由于部分手机本身的原因,这里可能存在着误差,设定的是 1000 毫秒,而在实际的执行中,它相当于 800 毫秒。那么就会导致一个问题,本地的时间越算,误差越大,如果在页面中的时间停留较短那问题不大,但是如果在页面的停留时间很长,到了最后看上就是一个大大的 BUG 。所以,每次都读取服务器时间是比较靠谱的。

实现要点:

<template>
  <div class="countdown-section">
    <div
    	v-if="styleForm.type==='normal'"
      :style="[{ 'background-image': `url(${styleForm.bgUrl})` }]"
      :class="['countdown-section-bg', `width-${styleForm.bgWidth}`]"
    >
      <div class="countdown-content">
        <p class="time-front" v-text="styleForm.timeFront"></p>
        <p class="time" v-text="countTime"></p>
        <p class="time-end" v-text="styleFrom.timeEnd"></p>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  methods: {
    countdown() {
      ...
      this.timeStr={}   //data
      this.format=['hours', 'minutes','seconds']  // props
      for(let i=0 ;i < format.length; i++ ){
      	this.timeStr=this.time[format[i]];
      }
    },
  },
}
</script>

节点样式方面:让 countdown-content 的内容居中,倒计时前后可以配置任意文案,再给 clase="time" 加上一个宽度,这样的好处是避免了在数字变化的时,因倒计时数字切换发生的抖动而影响到了整个倒计时文案的抖动问题。另一个是,在倒计时外层再包一层 v-if 样式,这个是来拓展倒计时多种样式的功能。

逻辑方面:传入一个时间格式的配置项,比如是否需要展示天数或者秒数,使用一个循环指定数据更新。最后的时间由 computed 计算属性将 day, hours minutes , seconds 计算出来。同时,倒计时为零的时候支持配置一个方法,例如,最常见的操作就是刷新当前页面或者是执行跳转。

进度条组件

组件布局和实现

组件封装思路

进度条组件和倒计时组件一样,属于逻辑比较简单而比较注重样式上的一些配置。进度条组件需要考虑的点是:

  1. 背景色支持渐变配置
  2. 进度条每个节点上面和下面的文案与样式支持配置
  3. 进度条的节点所有内容支持显隐

细节实现要点

<template>
<div class="progress-content">
  <div class="progress">
    <div class="progress-line" 
    :style="{ width: `${currentProgress}%`, backgroundImage: `linear-gradient(
    to right,
    ${styles.lineStyle.begin},
    ${styles.lineStyle.end}
    )`}"></div>
    <div class="progress-state">
    	<div v-for="(item, index) in styles.list"
    :key="`${index}buttom`"
    :style="[{ 'background-image': `url(${+index <=+current ? styles.dot.high: styles.dot.normal})` }]"
    class="state"
    >
        <div v-if="item.topText" :style="styles.top[index]" :class="['top']" v-text="item.topText"></div>
        <div v-if="item.bottomText" :style="styles.bottom[index]" class="buttom" v-text="item.bottomText"></div>
    	</div>
    </div>
  </div>
</div>
</template>

<script>
export default {
  methods: {
   
  },
}
</script>

首先,通过 props 进来的 styles参数, 获取到这个进度条的颜色,为了进度条能有更多的颜色配置,就是用渐变色来配置,只要传入一个开始和一个结束的色值。

节点的的样式和文案全部通过数组渲染,来达到通用配置的目,以下是我截取简易的配置数据

const progress={
    top: [
        {
            color: '#f5ddff',
        },
        {
            color: '#d6a5ea',
        },
				....
    ],
    bottom: [
        {
            color: '#d6a5ea',
        },
        {
            color: '#d6a5ea',
        },
        ....
    ],
    dot: {
        high: '',
        normal: '',
    },
    list: [
        {
            topText: 'Switch',
            bottomText: '0',
            hidden: false
        },
        {
            topText: '2部',
            bottomText: '10000',
            hidden: false
        },
				...
    ],
    lineStyle:{
         begin:'rgba(255, 166, 248, 1)',
         end:'rgba(255, 58, 210, 1)'   
    }
};

吸底组件

组件布局和实现:

组件封装思路

吸底部组件和顶部组件一样,它不适用于 H5 自动生成平台。吸底组件和顶部组件它们更像是一个容器,在这个容器里面配置其他的组件,所以这里还是做成一个可复用的定制模版。需要考虑的一些点:

  1. 最左边部分的头像和和昵称可以写死固定下来同时需要配置默认打底状态数据。
  2. 中间部分的票数做成可配置的情况可以展示 1 行或者 2 行以及支持显隐。
  3. 最右边部分的按钮同样支持可配置 1 个或者 2 个以及支持显隐。
  4. 可配置背景色

细节实现要点

他们的数据格式是:

<script>
export default {
  data() {
    return {
    	// 数据源绑定
    	suspensionData: {
        userSection: {
        	name: 'xxxx',
        	url: '....png',
        },
        textSection: [
          {
          	'text': `已贡献助力票数: 600`
          },
          {
          	'text': `剩余助力票数: 400`
          }
        ],
    	},
      // 数据配置样式设定
      suspensionConfig: {
      	bg: '....png',
        btn: [
          {
            'id': 'get',
            'url': '....png',
            'text': '获取助力票'
          },
          {
            'id': 'exchange',
            'url': '....png',
            'text': '兑换助力票'
          }
        ]
      },
    },
  },
}
</script>

中间的文字展示和右边的按钮使用 Array 的形式渲染

<template>
...
  <div
    v-if="btn && btn.length > 0"
    :class="['item-right, `length-${btn.length}`']"
    >
    ...
  </div>
</template>
<style lang="scss" scoped>
	... 
	.btn{
		...
		&.length-2{
			justify-content: space-between;
		}
		&.length-1{
			justify-content: space-evenly;
		}
	}
</style>

在样式上线配置好 length-x 情况下是居中还是均分的样式。中间的文字也是同样的方法,只是这里就多了一些细节的考虑,比如:字体容器的溢出处理和行间距的一些设定。

头像和昵称按理也可以做一些设定,但是这里根据实际的需求来说没有必要,所以这里就直接固定下来。

投票组件

组件布局和实现

组件封装思路

这个 H5 的投票功能相对简单,只有一个增加/减少和最大值。

在做这个组件之前,我其实更想把它做成这样的形式。如图:

它可展示图片,还可以展示选择票的类型,同时下面还可以配置拓展按钮也可以绑定执行事件,看上去非常的好。但是后来想了一下,还是觉得这样投票组件的逻辑会有点冗余,既然是一个投票组件应该不就有其他的东西。

所以我也在原来的基础上结合这个组件多加了一投票的类型选择。就是这样:

这样看上去逻辑简单,而且也确实多了是一个实用的功能。所以,这个组件需要考虑的点是:

  1. 增加/减少和最大值的计算
  2. 类型选择同时可以支持拓展以及默认隐藏使用。

细节实现要点

<template>
...
<!-- 票数编辑区域 -->
<div class="ticket-section">
  <div class="ticket-edit">
    <input class="ticket-text" v-model="ticketInfo['count']"/>
    <div :class="['ticket-add']" @click="ticketAdd()" >
  		<p class="add">+</p>
  	</div>
    <div :class="['ticket-min']" @click="ticketMins">
      <p class="min">-</p>
  	</div>
  </div>
    <div :class="['ticket-max', 'allow']">
      <p class="max" @click="ticketAdd(true)">MAX</p>
  	</div>
  </div>
  
  <!-- 类型选择区域 -->
  <div class="ticket-type-section">
    <div v-if="typeList.length > 0" class="ticket-type-content">
      <div v-for="(item,index) in typeList" :key="`type${index}`"
        class="ticket-type-item">
      <div :class="['box',item.active? 'active': '']"></div>
      <div v-text="item.text"></div>
    </div>
  </div>
</div>
...
</template>

首先用一个数组渲染类型列表,编辑区域票数区域比较重要的的就是做好数字上的校验和统一管理检验失败的提示文案。

const tipsMap={
    error: '亲!剩余助力票不足,请重新输入!',
    success: '助力成功!',
    errorNum: '必须是一个数值,注意不能有空格',
    errorMax: '亲,剩余助票不足,请重新输入',
    errorZero: '亲,剩余助票不足,请去获取哦!',
};

const validCount=(num)=> {
this.$set(this, 'showTips', false);
  const regExp=/^\+?[1-9][0-9]*$/g;
  if (+this.ticketInfo.count===0) {
   return false
  }
  if (!regExp.test(this.ticketInfo.count)) {
  	this.toast(tipsMap['errorNum'])
  	return false;
	};
  if (+this.ticketInfo.count > +this.ticketInfo.left){
  	this.toast(tipsMap['errorMax'])
  	return false;
  };
  // 检验通过
  return true;
  }
},
validCount(1000);

排行榜组件

组件布局和实现

组件封装思路

排行组件是这一个活动逻辑最复杂的一个,他除了需要支持到这个活动展示的列表数据,也需要支持到以后其他 H5 的数据展示,也就是支持拓展。 比如:在这个排行榜中,第一列是一个头像列表类型,第二列是一个文字类型,第三列也是一个头像类型,第四列是一个按钮类型。那么,在组件初始化的时候通过 config 配置定义好每一列的类型和样式。如图:

const rankConfig={
    init: [
          {
            type: 'headList',
            key: 'head',
            name: '超能',
            tips: 'live',
            style: {
              width: '25%',
              color: '#ffffff',
              background: '#c69494',
            }
          },
          {
            type: 'text',
            key: 'score',
            name: '总助力值',
            style: {
              width: '25%',
              color: '#ffffff',
              background: '#e53de7',
            }
          },
				....
    ]
};

这一段是部分配置

  1. type 是数据类型,比如 纯文字,头像或者按钮。
  2. key 是对应实际数据的 key,通过这个 key 让这一列展示这个字段的内容。
  3. name 是这一列的标题
  4. style 是这一列的具体样式配置参数。

以后无论是需要怎么样的一个排行榜,先查找文档看看是不是都有这样类型的样式,没有的话拓展,有的话只需要传入配置参数之后,再传入具体的数据就可以跑起一个排行榜的组件。

从功能上看他需要支持:

  1. 支持数据分页
  2. 支持数据展示和拓展展示的数据类型
  3. 点击事件通用配置

细节实现要点

标题部分主要代码:

<template>
...
<div v-for="(item, index) in styles.init"
     :style="item.style"
     :class="['column-item', 'column-type']"
     :key="`${index}column`">
     
	<div class="item-title">
		
    <p class="title-text" v-text="item.name"></p>
  	<slot class="title-tips" :name="`sub-${item.key}`"></slot>
  </div>
</div>
</template>

使用配置项循环列出列表的标题,里面有个 icon 的提示图标,使用插槽的方式插入,这里需要用 sub-${item.key} 作为一个区分,需要显示 tips icon 的标题才展示。这里只能用 key 作为区分不能用 type,原因是一个列表里面是有可能有相同的 type 列的。

列表的渲染,这里需要各种类型的展示再抽离成一个小组件,比如将 text ,headList 等等抽离成一个小组件,需要的时候再引用。这样做的好处出逻辑分开容易维护,小组件容易拓展,排行榜的代码也不会过多,如图:

他的核心代码如下:

<template>
...
<div
class="column"
v-for="(item, index) in info.list"
:key="`${index}rankList`"
>
  <div
  v-for="(styleItem, styleIndex) in styles.init"
  :key="`${styleIndex}rankConfig`"
  :class="'column-item'"
  >
    <HeadList
      v-if="styleItem.type==='headList'"
      @methods="onClickEvent(item.key, item)"
      ><HeadList>

    <Text v-if="styleItem.type==='text'"></Text>

    <ListBtn v-if="styleItem.type==='btn'"></ListBtn>
  </div>
</div>
</template>

第一层循环遍历所有列表数据,第二层循环遍历配置表,根据类型渲染具体内容,之后每一个块的内容都通过小组件形式引入。

I组件

element- 饿了么出品的Vue2的web UI工具套件

Vux- 基于Vue和WeUI的组件库

mint-ui- Vue 2的移动UI元素

iview- 基于 Vuejs 的开源 UI 组件库

Keen-UI- 轻量级的基本UI组件合集

vue-material- 通过Vue Material和Vue 2建立精美的app应用

muse-ui- 三端样式一致的响应式 UI 库

vuetify- 为移动而生的Vue JS 2组件框架

vonic- 快速构建移动端单页应用

eme- 优雅的Markdown编辑器

vue-multiselect- Vue.js选择框解决方案

vue-table- 简化数据表格

VueCircleMenu- 漂亮的vue圆环菜单

vue-chat- vuejs和vuex及webpack的聊天示例

radon-ui- 快速开发产品的Vue组件库

vue-waterfall- Vue.js的瀑布布局组件

vue-carbon- 基于 vue 开发MD风格的移动端

vue-beauty- 由vue和ant design创建的优美UI组件

vue-blu- 帮助你轻松创建web应用

vueAdmin- 基于vuejs2和element的简单的管理员模板

vue-syntax-highlight- Sublime Text语法高亮

vue-infinite-scroll- VueJS的无限滚动指令

Vue.Draggable- 实现拖放和视图模型数组同步

vue-awesome-swiper- vue.js触摸滑动组件

vue-calendar- 日期选择插件

bootstrap-vue- 应用于Vuejs2的Twitter的Bootstrap 4组件

vue-swipe- VueJS触摸滑块

vue-amap- 基于Vue 2和高德地图的地图组件

vue-chartjs- vue中的Chartjs的封装

vue-datepicker- 日历和日期选择组件

markcook- 好看的markdown编辑器

vue-google-maps- 带有双向数据绑定Google地图组件

vue-progressbar- vue轻量级进度条

vue-picture-input- 移动友好的图片文件输入组件

vue-infinite-loading- VueJS的无限滚动插件

vue-upload-component- Vuejs文件上传组件

vue-datetime-picker- 日期时间选择控件

vue-scroller- Vonic UI的功能性组件

vue2-calendar- 支持lunar和日期事件的日期选择器

vue-video-player- VueJS视频及直播播放器

vue-fullcalendar- 基于vue.js的全日历组件

rubik- 基于Vuejs2的开源 UI 组件库

VueStar- 带星星动画的vue点赞按钮

vue-mugen-scroll- 无限滚动组件

mint-loadmore- VueJS的双向下拉刷新组件

vue-tables-2- 显示数据的bootstrap样式网格

vue-virtual-scroller- 带任意数目数据的顺畅的滚动

DataVisualization- 数据可视化

vue-quill-editor- 基于Quill适用于Vue2的富文本编辑器

Vueditor- 所见即所得的编辑器

vue-html5-editor- html5所见即所得编辑器

vue-msgbox- vuejs的消息框

vue-slider- vue 滑动组件

vue-core-image-upload- 轻量级的vue上传插件

vue-slide- vue轻量级滑动组件

vue-lazyload-img- 移动优化的vue图片懒加载插件

vue-drag-and-drop-list- 创建排序列表的Vue指令

vue-progressive-image- Vue的渐进图像加载插件

vuwe- 基于微信WeUI所开发的专用于Vue2的组件库

vue-dropzone- 用于文件上传的Vue组件

vue-charts- 轻松渲染一个图表

vue-swiper- 易于使用的滑块组件

vue-images- 显示一组图片的lightbox组件

vue-carousel-3d- VueJS的3D轮播组件

vue-region-picker- 选择中国的省份市和地区

vue-typer- 模拟用户输入选择和删除文本的Vue组件

vue-impression- 移动Vuejs2 UI元素

vue-datatable- 使用Vuejs创建的DataTableView

vue-instant- 轻松创建自动提示的自定义搜索控件

vue-dragging- 使元素可以拖拽

vue-slider-component- 在vue1和vue2中使用滑块

vue2-loading-bar- 最简单的仿Youtube加载条视图

vue-datepicker- 漂亮的Vue日期选择器组件

vue-video- Vue.js的HTML5视频播放器

vue-toast-mobile- VueJS的toast插件

vue-image-crop-upload- vue图片剪裁上传组件

vue-tooltip- 带绑定信息提示的提示工具

vue-highcharts- HighCharts组件

vue-touch-ripple- vuejs的触摸ripple组件

coffeebreak- 实时编辑CSS组件工具

vue-datasource- 创建VueJS动态表格

vue2-timepicker- 下拉时间选择器

vue-date-picker- VueJS日期选择器组件

vue-scrollbar- 最简单的滚动区域组件

vue-quill- vue组件构建quill编辑器

vue-google-signin-button- 导入谷歌登录按钮

vue-svgicon- 创建svg图标组件的工具

vue-float-label- VueJS浮动标签模式

vue-baidu-map- 基于 Vue 2的百度地图组件库

vue-social-sharing- 社交分享组件

vue2-editor- HTML编辑器

vue-tagsinput- 基于VueJS的标签组件

vue-easy-slider- Vue 2.x的滑块组件

datepicker- 基于flatpickr的时间选择组件

vue-chart- 强大的高速的vue图表解析

vue-music-master- vue手机端网页音乐播放器

handsontable- 网页表格组件

vue-simplemde- VueJS的Markdown编辑器组件

vue-popup-mixin- 用于管理弹出框的遮盖层

cubeex- 包含一套完整的移动UI

vue-fullcalendar- vue FullCalendar封装

vue-material-design- Vue MD风格组件

vue-morris- Vuejs组件封装Morrisjs库

we-vue- Vue2及weui1开发的组件

vue-image-clip- 基于vue的图像剪辑组件

vue-bootstrap-table- 可排序可检索的表格

vue-radial-progress- Vue.js放射性进度条组件

vue-slick- 实现流畅轮播框的vue组件

vue-pull-to-refresh- Vue2的上拉下拉

vue-form-2- 全面的HTML表单管理的解决方案

vue-side-nav- 响应式的侧边导航

mint-indicator- VueJS移动加载指示器插件

chartjs- Vue Bulma的chartjs组件

vue-scroll- vue滚动

vue-ripple- 制作谷歌MD风格涟漪效果的Vue组件

vue-touch-keyboard- VueJS虚拟键盘组件

vue-chartkick- VueJS一行代码实现优美图表

vue-ztree- 用 vue 写的树层级组件

vue-m-carousel- vue 移动端轮播组件

vue-datepicker-simple- 基于vue的日期选择器

vue-tabs- 多tab页轻型框架

vue-verify-pop- 带气泡提示的vue校验插件

vue-parallax- 整洁的视觉效果

vue-img-loader- 图片加载UI组件

vue-typewriter- vue组件类型

vue-smoothscroll- smoothscroll的VueJS版本

vue-city- 城市选择器

vue-tree- vue树视图组件

vue-ios-alertview- iOS7+ 风格的alertview服务

dd-vue-component- 订单来了的公共组件库

paco-ui-vue- PACOUI的vue组件

vue-cmap- Vue China map可视化组件

vue-button- Vue按钮组件

开发框架

vue.js- 流行的轻量高效的前端组件化方案

vue-admin- Vue管理面板框架

electron-vue- Electron及VueJS快速启动样板

vue-2.0-boilerplate- Vue2单页应用样板?

vue-spa-template- 前后端分离后的单页应用开发

Framework7-Vue- VueJS与Framework7结合

vue-bulma- 轻量级高性能MVVM Admin UI框架

vue-webgulp- 仿VueJS Vue loader示例

vue-element-starter- vue启动页

实用库

vuex- 专为 Vue.js 应用程序开发的状态管理模式

vuelidate- 简单轻量级的基于模块的Vue.js验证

qingcheng- qingcheng主题

vue-desktop- 创建管理面板网站的UI库

vue-meta- 管理app的meta信息

vue-axios- 将axios整合到VueJS的封装

vue-svg-icon- vue2的可变彩色svg图标方案

avoriaz- VueJS测试实用工具库

vue-framework7- 结合VueJS使用的Framework7组件

vue-bootstrap-modal- vue的Bootstrap样式组件

vuep- 用实时编辑和预览来渲染Vue组件

vue-online- reactive的在线和离线组件

vue-lazy-render- 用于Vue组件的延迟渲染

vue-password-strength-meter- 交互式密码强度计

element-admin- 支持 vuecli 的 Element UI 的后台模板

vue-electron- 将选择的API封装到Vue对象中的插件

cleave- 基于cleave.js的Cleave组件

vue-events- 简化事件的VueJS插件

vue-shortkey- 应用于Vue.js的Vue-ShortKey 插件

vue-cordova- Cordova的VueJS插件

vue-router-transition- 页面过渡插件

vue-gesture- VueJS的手势事件插件

http-vue-loader- 从html及js环境加载vue文件

vue-qart- 用于qartjs的Vue2指令

vuemit- 处理VueJS事件

vue-websocket- VueJS的Websocket插件

vue-local-storage- 具有类型支持的Vuejs本地储存插件

lazy-vue- 懒加载图片

vue-bus- VueJS的事件总线

vue-reactive-storage- vue插件的Reactive层

vue-notifications- 非阻塞通知库

vue-lazy-component- 懒加载组件或者元素的Vue指令

v-media-query- vue中添加用于配合媒体查询的方法

vue-observe-visibility- 当元素在页面上可见或隐藏时检测

vue-ts-loader- 在Vue装载机检查脚本

vue-pagination-2- 简单通用的分页组件

vuex-i18n- 定位插件

Vue.resize- 检测HTML调整大小事件的vue指令

vuex-shared-mutations- 分享某种Vuex mutations

vue-file-base64- 将文件转换为Base64的vue组件

modal- Vue Bulma的modal组件

Famous-Vue- Famous库的vue组件

leo-vue-validator- 异步的表单验证组件

Vue-Easy-Validator- 简单的表单验证

vue-truncate-filter- 截断字符串的VueJS过滤器

vue-zoombox- 一个高级zoombox

vue-input-autosize- 基于内容自动调整文本输入的大小

vue-lazyloadImg- 图片懒加载插件

服务端

nuxt.js- 用于服务器渲染Vue app的最小化框架

express-vue- 简单的使用服务器端渲染vue.js

vue-ssr- 非常简单的VueJS服务器端渲染模板

vue-ssr- 结合Express使用Vue2服务端渲染

vue-easy-renderer- Nodejs服务端渲染

辅助工具

DejaVue- Vuejs可视化及压力测试

vue-play- 展示Vue组件的最小化框架

vscode-VueHelper- 目前vscode最好的vue代码提示插件

vue-generate-component- 轻松生成Vue js组件的CLI工具

vue-multipage-cli- 简单的多页CLI

VuejsStarterKit- vuejs starter套件

应用实例

koel- 基于网络的个人音频流媒体服务

pagekit- 轻量级的CMS建站系统

vuedo- 博客平台

jackblog-vue- 个人博客系统

vue-cnode- 重写vue版cnode社区

CMS-of-Blog- 博客内容管理器

rss-reader- 简单的rss阅读器

vue-ghpages-blog- 依赖GitHub Pages无需本地生成的静态博客

swoole-vue-webim- Web版的聊天应用

vue-dashing-js- nuvo-dashing-js的fork

fewords- 功能极其简单的笔记本

vue-blog- 使用Vue2.0 和Vuex的vue-blog

Demo示例

Vue-cnodejs- 基于vue重写Cnodejs.org的webapp

NeteaseCloudWebApp- 高仿网易云音乐的webapp

vue-zhihu-daily- 知乎日报 with Vuejs

vue-wechat- vue.js开发微信app界面

vue2-demo- 从零构建vue2 + vue-router + vuex 开发环境

eleme- 高仿饿了么app商家详情

vue-demo- vue简易留言板

maizuo- vue/vuex/redux仿卖座网

spa-starter-kit- 单页应用启动套件

vue-music- Vue 音乐搜索播放

douban- 模仿豆瓣前端

vue-Meizi- vue最新实战项目

zhihudaily-vue- 知乎日报web版

vue-demo-kugou- vuejs仿写酷狗音乐webapp

VueDemo_Sell_Eleme- Vue2高仿饿了么外卖平台

vue2.0-taopiaopiao- vue2.0与express构建淘票票页面

vue-leancloud-blog- 一个前后端完全分离的单页应用

node-vue-server-webpack- Node.js+Vue.js+webpack快速开发框架

mi-by-vue- VueJS仿小米官网

vue-fis3- 流行开源工具集成demo

vue2.x-douban- Vue2实现简易豆瓣电影webApp

vue-demo-maizuo- 使用Vue2全家桶仿制卖座电影

vue-zhihudaily- 知乎日报 Web 版本

vue-adminLte-vue-router- vue和adminLte整合应用

vue-axios-github- 登录拦截登出功能

Zhihu-Daily-Vue.js- Vuejs单页网页应用

hello-vue-django- 使用带有Django的vuejs的样板项目

vue-cnode- vue单页应用demo

x-blog- 开源的个人blog项目

vue-express-mongodb- 简单的前后端分离案例

websocket_chat- 基于vue和websocket的多人在线聊天室

photoShare- 基于图片分享的社交平台

vue-zhihudaily-2.0- 使用Vue2.0+vue-router+vuex创建的zhihudaily

notepad- 本地存储的记事本

vueBlog- 前后端分离博客

vue-ruby-china- VueJS框架搭建的rubychina平台

Zhihu_Daily- 基于Vue和Nodejs的Web单页应用

vue-koa-demo- 使用Vue2和Koa1的全栈demo

vue2.x-Cnode- 基于vue全家桶的Cnode社区

life-app-vue- 使用vue2完成多功能集合到小webapp

github-explorer- 寻找最有趣的GitHub库

vue-trip- vue2做的出行webapp

vue-ssr-boilerplate- 精简版的ofvue-hackernews-2

vue-bushishiren- 不是诗人应用

houtai- 基于vue和Element的后台管理系统

ios7-vue- 使用vue2.0 vue-router vuex模拟ios7

Framework7-VueJS- 使用移动框架的示例

cnode-vue- 基于vue和vue-router构建的cnodejs web网站SPA

vue-cli-multipage-bootstrap- 将vue官方在线示例整合到组件中

vue-cnode- 用 Vue 做的 CNode 官网

HyaReader- 移动友好的阅读器

zhihu-daily- 轻松查看知乎日报内容

seeMusic- 跨平台云音乐播放器

vue-cnode- 使用cNode社区提供的接口

zhihu-daily-vue- 知乎日报

sls-vuex2-demo- vuex2商城购物车demo

vue-dropload- 用以测试下拉加载与简单路由

vue-cnode-mobile- 搭建cnode社区

Vuejs-SalePlatform- vuejs搭建的售卖平台demo

v-notes- 简单美观的记事本

vue-starter- VueJs项目的简单启动页

vue-memo- 用 vue写的记事本应用