前言
想必大家都看过 fullpage.JS https://github.com/alvarotrigo/fullPage.js -- 这是一款非常好用的翻页插件.
现在 vue 非常流行, 大家想不想发布一个组件给别人使用呢?
这里我们基于 vue-cli3 https://cli.vuejs.org/zh/ 快速搭建一个简单的 fullpage 组件给别人使用, 当然你也可以做你感兴趣的组件发布给别人用~
开始
准备
$ NPM i -g @vue/cli #全局 vue-cli3
通过查看 vue-cli3 官网了解, 创建一个新的普通项目.
思考
一开始要想别人如何调用我们写的组件, 通过挂载 vue 实例方法 (this.$alert) 还是注册组件. 答案自然是后者. 我们希望别人可以这么使用~
- # 一个 section 块就是一个可以滚动的块
- <v-fullpage>
- <div slot="section"></div>
- <div slot="section"></div>
- </v-fullpage>
设计组件接口, prop. 可以有滚动方向(垂直还是横向)
Property | Description | Type | Default |
---|---|---|---|
direction | 滚动方向 ('vertical'或'horizontal') | String | 'vertical' |
设计组件的回调(内部需要暴露什么方法给外部)
Name | Description |
---|---|
leaveSlide | 滑动之后,参数是当前 index |
希望可以主动调用内部方法, 禁止 / 开放滚动事件
通过 ref 调用组件内部 API
Name | Description |
---|---|
setAllowScrolling | 传入 true/false,禁止滚动 / 开放滚动事件 |
目录结构
├─ dist // 打包
├─ public
├─ src
│ ├─ assets
│ ├─ components // 存放所有 custom elements
│ ├─ fullpage.vue // 实际干活的
│ ├─ App.vue // 内部 demo, 可以引进来我们写的 fullpage 组件调试
│ └─ main.JS // 入口文件
编写
我们在 fullpage.vue 写逻辑, 模板里需要有一个 slot(放置别人的 div), 这个 div 需要有个滚动盒子包裹(可以通过 translate 移动)
- <div class="v-fullpage-container" ref='v-fullpage'
- @mousewheel='mouseWheelHandle'>
- // 监听鼠标滚轮事件
- <div class="v-slide-container" :class="direction" ref='v-slide-container' v-show='isShow'>
- <slot name='section'></slot>
- </div>
- </div>
先初始化容器宽度
- // 所有 data
- data(){
- return{
- fullpage:{
- // 当前处于第几个 div
- current:1,
- isScrolling: false,
- // 返回鼠标滚轮的垂直滚动量
- deltaY:0,
- },
- // 显示滚动盒子
- isShow:false,
- // 是否允许滚动
- isAllowScroll:true,
- API:{
- setAllowScrolling:this.setAllowScrolling
- }
- }
- },
- mounted() {
- this.initFullPage()
- // 窗口 resize 时候重新设计大小
- Windows.addEventListener('resize',this.resizeEventHandler)
- },
- beforeDestroy() {
- // 组件销毁的时候 remove 事件监听
- Windows.removeEventListener("resize", this.resizeEventHandler, false);
- },
- methods:{
- resizeEventHandler(){
- // 节流, 考虑效率
- throttle(this.initFullPage(),300)
- },
- initFullPage(){
- // 初始化容器宽高度
- this.isShow=false
- let height = this.$refs['v-fullpage'].clientHeight;
- let width=this.$refs['v-fullpage'].clientWidth;
- // 手动写容器的宽度
- this.direction=='horizontal'?this.$refs['v-slide-container'].style.width=`${width*this.$slots.section.length}px`:null;
- // 手动设置 slots 里面为 section 的样式
- this.$slots.section.forEach((item)=>{
- item.elm.style.height=`${height}px`
- item.elm.style.width=`${width}px`
- })
- // 显示滚动盒子
- this.isShow=true
- },
- }
滚轮事件
- methods:{
- next() {
- let len = this.$slots.section.length;
- if((this.fullpage.current + 1) <= len) {
- this.fullpage.current += 1;
- this.move(this.fullpage.current);
- }
- },
- pre() {
- if(this.fullpage.current -1> 0) {
- this.fullpage.current -= 1;
- this.move(this.fullpage.current);
- }
- },
- move(index) {
- // 为了防止滚动多次滚动, 需要通过一个变量来控制是否滚动
- this.fullpage.isScrolling = true;
- this.directToMove(index)
- this.$emit('leaveSlide',{currentIndex:this.fullpage.current})
- // 这里的动画是 1s 执行完, 使用 setTimeout 延迟 1s 后解锁
- setTimeout(()=>{
- this.fullpage.isScrolling = false;
- }, 1010);
- },
- directToMove(index){
- let height = this.$refs['v-fullpage'].clientHeight;
- let width=this.$refs['v-fullpage'].clientWidth;
- let $scroll = this.$refs['v-slide-container'];
- // 位移多少
- let displacement
- // 判断是垂直滚动还是横向滚动
- if(this.direction=='vertical'){
- displacement = -(index-1)*height + 'px';
- $scroll.style.transform=`translateY(${displacement})`
- }else{
- displacement = -(index-1)*width + 'px';
- $scroll.style.transform=`translateX(${displacement})`
- }
- this.fullpage.current = index
- },
- mouseWheelHandle (event) {
- if(!this.isAllowScroll){// 是否可以滚动
- return
- }
- if (this.fullpage.isScrolling) {// 加锁部分
- return false;
- }
- let e = event.originalEvent || event;
- this.fullpage.deltaY = e.deltaY;
- if (this.fullpage.deltaY> 0) {
- this.next();
- } else if (this.fullpage.deltaY <0) {
- this.pre();
- }
- },
- setAllowScrolling(isAllow){
- this.isAllowScroll=isAllow
- },
- }
写到这里基本就完成了, 我们需要打包成别人可以用的. 感谢 vue-cli3, 都封装的非常好了.
打包
在 package.JSON 的 scripts 增加一个命令, 然后执行 NPM run build:lib
- "scripts": {
- "build:lib": "vue-cli-service build --target lib --name v-fullpage ./src/components/index.js",
- },
这样我们就会打包到 dist 几个文件, 主要打包成了 umd(浏览器可以引用)和 commonjs 模块规范的包. 参考 Vue Cli3 构建目标: 库
发布
pacakage.JSON 发布到 NPM 的字段
配置 package.JSON 文件中发布到 NPM 的字段
name: 包名, 该名字是唯一的. NPM 官网搜索一下有没有, 这里我们取 v-fullpage
version: 版本号, 每次发布至 NPM 需要修改版本号
description: 描述.
main: 入口文件, import/require 的
keyword: 关键字, 以空格分离希望用户最终搜索的词.
author: 作者
private: 是否私有, 需要修改为 false 才能发布到 NPM
NPM 官网注册 NPM 账号, 有就不需要
回到我们的目录下, NPM login
发布, NPM publish
需要等一下, NPM 官网搜索
使用
- import Vue from "vue";
- import fullpage from "v-fullpage";
- Vue.use(fullpage);
- or
- <script src="vue.min.js"></script>
- <!-- must place this line after vue.js -->
- <script src="v-fullpage.umd.min.js"></script>
来源: https://juejin.im/post/5c7fc706e51d4541be21d9da