npm login
后续需要输入用户名、密码、以及一次性校验码,请使用上一步中的校验器生成;
手动或者是使用命令创建均可
mkdir jdzb-ui && cd jdzb-ui
// 如果将来 npm i jdzb-ui
npm init -y
// 如果将来 npm i @steveouyang/jdzb-ui
npm init --scope=steveouyang
配置package.json,请根据自己的项目细节自行配置
{
"name": "jdzb-ui",
"version": "1.0.0",
"description": "京东正版UI",
"main": "src/main.js",
"author": "steve ouyang",
"scripts": {
"dev": "npx rollup -wc rollup.config.dev.js",
"build": "npx rollup -c rollup.config.js"
},
"license": "ISC",
"devDependencies": {
"@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-commonjs": "^22.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.3.0",
"rollup-plugin-scss": "^3.0.0",
"rollup-plugin-vue": "^6.0.0"
}
}
── jdzb-ui
|—— node_modules
|—— lib
|—— src
|—— main.js
|—— components
|—— Elevator
|—— index.vue
|—— index.css
|—— index.js
|—— css
|── package.json
|—— rollup.config.js
|—— README.md
index.vue
<template>
<div class="elevator elevator_recommend" :class="{ elevator_fix: fix }">
<svg
class="svgcont"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
style="display: none"
>
<defs>
<symbol id="icon_timline" viewBox="0 0 16 16">
<path
d="M12.986 5.582a.505.505 0 0 0 .25-.063c.34-.188.364-.738.056-1.252-.235-.391-.59-.643-.905-.643a.511.511 0 0 0-.251.063c-.338.188-.363.738-.055 1.252.234.391.59.643.905.643m-9.975 0c.317 0 .674-.252.91-.643.31-.514.286-1.064-.056-1.253a.52.52 0 0 0-.252-.062c-.317 0-.674.252-.91.643-.31.514-.285 1.064.056 1.252.076.042.16.063.252.063m10.779.956a.372.372 0 0 0-.295-.024.387.387 0 0 0-.225.201c-.013.025-.315.609-1.062 1.191-.738.573-2.062 1.26-4.185 1.279h-.075c-2.076 0-3.384-.653-4.116-1.2-.779-.581-1.094-1.177-1.097-1.182a.395.395 0 0 0-.23-.199.371.371 0 0 0-.293.031.42.42 0 0 0-.161.549c.039.077.413.772 1.316 1.45.826.622 2.29 1.363 4.573 1.363l.089-.001c2.331-.019 3.81-.793 4.641-1.439.862-.672 1.225-1.345 1.292-1.475a.419.419 0 0 0-.172-.544m-5.848-.124c1.092 0 2.268-.218 2.268-.697S9.034 5.02 7.942 5.02c-1.071 0-2.152.216-2.152.697s1.081.697 2.152.697m4.086 4.647c-1.004.574-1.052 1.597-1.015 2.223a.098.098 0 0 1-.113.104c-.693-.096-1.161-.407-1.757-.943a1.343 1.343 0 0 0-.933-.351l-.21.003c-3.809 0-6.897-2.458-6.897-5.489 0-3.032 3.088-5.489 6.897-5.489 3.808 0 6.896 2.457 6.896 5.489 0 1.834-1.129 3.461-2.868 4.453M8 0C3.589 0 0 2.931 0 6.533c0 3.603 3.589 6.533 8 6.533l.224-.002c.102 0 .204.033.272.099 1.239 1.205 2.568 1.323 3.303 1.336a.3.3 0 0 0 .303-.342c-.087-.613-.318-1.813.477-2.263C14.722 10.684 16 8.677 16 6.533 16 2.931 12.411 0 8 0"
></path>
</symbol>
<symbol id="icon_feedback" viewBox="0 0 16 16">
<path
d="M1.4,15l0-1l14,0v1H1.4z M2.5,13H2l0-0.5c0-0.1,0-0.2,0-0.3c0-0.3,0.1-0.8,0.2-1.3c0.1-0.7,0.4-1.7,0.4-2 C2.7,8.7,2.8,8.4,3,8.3l8-8c0.3-0.3,0.8-0.3,1.1,0l2.7,2.7c0.3,0.3,0.3,0.8,0,1.1l0,0l-8,8c-0.1,0.1-0.4,0.3-0.6,0.4 c-0.7,0.2-1.4,0.3-2.1,0.4c-0.5,0.1-1,0.2-1.3,0.2C2.7,13,2.6,13,2.5,13z M11.6,1.1L3.7,9c0,0.1-0.1,0.1-0.1,0.2 c-0.1,0.2-0.3,1.1-0.4,1.9c-0.1,0.3-0.1,0.6-0.1,0.9c0.3,0,0.6-0.1,0.9-0.1c0.7-0.1,1.3-0.2,2-0.4c0,0,0.1-0.1,0.2-0.1L14,3.5 L11.6,1.1z M14.1,3.3C14.1,3.3,14.1,3.3,14.1,3.3L14.1,3.3z M11.4,0.9C11.4,0.9,11.4,0.9,11.4,0.9L11.4,0.9z"
></path>
</symbol>
</defs>
</svg>
<ul class="elevator_list">
<template
v-for="({ name, imgSrc, link, icon, floorRef }, index) in floors"
:key="index"
>
<li
v-if="name && !link"
class="elevator_item"
@click="navToFloor(floorRef)"
>
<a
class="elevator_lk"
href="javascript:void(0);"
clstag="h|keycount|core|elvt_01"
tabindex="-1"
aria-hidden="true"
>
<div>
<span class="elevator_lk_bg"></span>
<span class="elevator_lk_txt">{{ name }}</span>
</div>
</a>
</li>
<li
v-else-if="imgSrc"
class="elevator_item"
@click="navToFloor(floorRef)"
>
<a
class="elevator_lk elevator_promotional"
href="javascript:void(0);"
clstag="h|keycount|core|elvt_08"
tabindex="-1"
aria-hidden="true"
@mouseover="imgHovered = true"
@mouseout="imgHovered = false"
>
<img v-if="imgHovered" :src="imgSrc[1]" alt="" />
<img v-else :src="imgSrc[0]" alt="" />
</a>
</li>
<li v-else class="elevator_item">
<a
class="elevator_lk elevator_lk2"
:href="link"
target="_blank"
clstag="h|keycount|core|elvt_06"
><span class="elevator_lk_bg"></span>
<svg>
<use :xlink:href="icon"></use>
</svg>
<span class="elevator_lk_txt">{{ name }}</span>
</a>
</li>
</template>
</ul>
<a
class="elevator_totop"
href="javascript: void(0);"
clstag="h|keycount|core|elvt_07"
tabindex="-1"
aria-hidden="true"
@click="toTop"
>
<span class="elevator_totop_icon"></span>
<span class="elevator_totop_txt">顶部</span>
</a>
</div>
</template>
<script setup>
import { reactive, toRefs } from "vue";
/* 无法使用模块化 */
// import { yScrollTo } from "../utils/scrollUtil.js";
// import "../css/first-screen.chunk.css"
// import "../css/index.chunk.css"
let timer = null;
const yScrollTo = (y, timespan = 1000) => {
if (timer) clearInterval(timer);
let current = document.documentElement.scrollTop;
let step = (y - current) / (timespan / 40);
timer = setInterval(() => {
if (Math.abs(y - current) >= Math.abs(step)) {
current += step;
window.scrollTo(0, current);
} else {
clearInterval(timer);
timer = null;
window.scrollTo(0, y);
}
}, 40);
};
const name = "Elevator";
const { fix, floors, scrollSpeed } = defineProps({
fix: Boolean,
floors: Array,
scrollSpeed: Object,
});
const { imgHovered } = toRefs(
reactive({
imgHovered: false,
})
);
const navToFloor = (ref) => {
// console.log("navToFloor", ref);
// window.scrollTo(0,document.documentElement.scrollTop + ref.$el.getBoundingClientRect().top - 50)
yScrollTo(
document.documentElement.scrollTop +
ref.$el.getBoundingClientRect().top -
50,
scrollSpeed.toFloor || 1000
);
};
const toTop = () => {
yScrollTo(0, scrollSpeed.toTop || 500);
};
</script>
<style lang="scss" scoped>
.elevator_promotional:hover img {
z-index: 2;
}
</style>
index.css内容较多,请移步源码地址自行查阅
index.js
import Elevator from "./index.vue";
Elevator.install = function (Vue) {
Vue.component(Elevator.name, Elevator);
};
export default Elevator;
main.js
import Elevator from "./components/Elevator/index.js";
import "./components/Elevator/index.css";
// import "./css/first-screen.chunk.css"
// import "./css/index.chunk.css"
import { version } from "../package.json";
const components = [Elevator];
const install = function (Vue) {
components.forEach((component) => {
Vue.component(component.name, component);
});
};
if (typeof window !== "undefined" && window.Vue) {
install(window.Vue);
}
export { Elevator, install };
export default { version, install };
npm i
npm run build
打包成功后会在lib目录下生成bundle.js
和bundle.cjs.js
两个文件,即代码中真正使用的文件
npm publish
// 开源发布
npm publish --access=public
取消发布
npm unpublish jdzb-ui --force
npm i jdzb-ui
入口文件main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
/* 全局引入 main.js */
import JdzbUI from "jdzb_ui";
// 引入全局样式
// import "jdzb-ui/lib/first-screen.css";
createApp(App).use(store).use(router).use(JdzbUI).mount('#app')
在组件中使用自定义组件
import { Elevator } from "jdzb_ui";
在模板中部署
<!-- Elevator -->
<Elevator
:fix="fixTitleBar"
:floors="floors"
:scrollSpeed="{ toFloor: 200, toTop: 500 }"
></Elevator>
“这不需要测试,肯定是好的,不必担心”