npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

unv-ui

v0.1.14

Published

unit vue2 components

Downloads

90

Readme

unv-ui

Introduce

unv-ui并不是一个严格意义上的UI组件库,它更像是一个工具库。它也包含一些公共的指令,比如v-form

它的很多组件实际上并没有任何样式,比如UvSelectUvArea只是做了数据的兼容层。

为什么要做数据兼容层组件,而不是做一个带有UI样式的完全体组件?

因为在很多toc的页面中,UI的样式是要靠自己实现的,但是很多通用的功能写到具体的组件中难以维护。

比如我想要一个省市区选择器:它可以是弹窗形式,也可以是并列三连的选择器,也可以是级联选择器。从功能上讲他们都是省市区选择器,然而他们的UI是不同的,开发者在组织代码时可能会出现areaV1.vue、areaV2.vue、areaV3.vue,但是他们的逻辑是相通的。数据兼容层组件可以让开发者更专注于实现组件的视图部分。

Links

unv-ui - npm (npmjs.com)

unv-ui - github(github.com)

Requirements

| | Minimum | | ---- | ------- | | Vue | 2.6.14 |

Install

npm install unv-ui

Quick Start

import Vue from 'vue'
import UnvUi from 'unv-ui'
Vue.use(UnvUi)

Docs

UvArea

省市区选择器,数据兼容层,你可以使用任意基于v-model的选择器组件传入到具名插槽中。

切换时,你不再需要组织代码来重置市 区的选择结果和对应的选项数组。UvArea会帮你做这些事。

你只需要关注省市区单个选择器组件的实现。

UvArea只做数据层兼容,你可以使用任何组件选择器来配合UvArea(比如el-selecta-select或自己实现的选择器)。

UvArea的行政区划数据来自@/vant/area-data

Usage

<template>
    <UvArea v-model="pca">
        <template #province="{ options }">
            <el-select v-model="pca.p">
                <el-option v-for="{ text, value } in options" :key="value" :label="text" :value="value"> </el-option>
            </el-select>
        </template>
        <template #city="{ options }">
            <el-select v-model="pca.c">
                <el-option v-for="{ text, value } in options" :key="value" :label="text" :value="value"> </el-option>
            </el-select>
        </template>
        <template #area="{ options }">
            <el-select v-model="pca.a">
                <el-option v-for="{ text, value } in options" :key="value" :label="text" :value="value"> </el-option>
            </el-select>
        </template>
    </UvArea>
</template>

<script>
export default {
    name: 'UseArea',
    data() {
        return {
            pca: {
                p: '',
                c: '',
                a: '',
            },
        };
    },
};
</script>

UvArea Slot

| name | 说明 | 参数 | | -------- | ---- | --------- | | province | 省 | {options} | | city | 市 | {options} | | area | 区 | {options} |

todo

  • 行政区划源数据支持自定义
  • 指定选项的值为选项对象的某个属性值

UvSelect

选择器,数据兼容层。

不再需要组织单选、多选的功能代码,也不需要关注选中结果的收集,UvSelect会帮你做这些事。

你只需要专注option选项组件的实现。

Usage

<template>
    <div>
        <!-- e.g.1 -->
        <div>{{ selectedValue }}</div>
        <UvSelect v-model="selectedValue">
            <SelectOption1 v-for="item in tableData" :key="item.id" :value="item.id" v-bind="item"></SelectOption1>
        </UvSelect>
        <!-- e.g.2 -->
        <div>{{ selectedValue2 }}</div>
        <UvSelect v-model="selectedValue2" multiple>
            <SelectOption2 v-for="item in tableData" :key="item.id" :value="item.id" v-bind="item"></SelectOption2>
        </UvSelect>
    </div>
</template>

<script>
import SelectOption1 from './SelectOption1.vue';
import SelectOption2 from './SelectOption2.vue';

export default {
    components: {
        SelectOption1,
        SelectOption2,
    },
    data() {
        return {
            selectedValue: '',
            selectedValue2: '',
            tableData: [
                {
                    id: 1,
                    date: '2016-05-02',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1518 弄',
                },
                {
                    id: 2,
                    date: '2016-05-04',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1517 弄',
                },
                {
                    id: 3,
                    date: '2016-05-01',
                    name: '王小虎',
                    address: '上海市普陀区金沙江路 1519 弄',
                },
            ],
        };
    },
};
</script>

SelectOption1

注意inject

<template>
    <div class="item" @click="selectAddress" :class="{ active }">
        <div>{{ date }}</div>
        <div>{{ name }}</div>
        <div>{{ address }}</div>
    </div>
</template>

<script>
export default {
    name: 'SelectOption1',
    inheritAttrs: false,
    inject: ['$Selector'],
    props: {
        value: [String, Number],
        data: Array,
        date: {},
        name: {},
        address: {},
    },
    computed: {
        active() {
            return this.$Selector.calcOptActive(this.value);
        },
    },
    methods: {
        selectAddress() {
            this.$Selector.optSelect({ value: this.value });
        },
    },
};
</script>

<style lang="scss" scoped>
.item {
    border: 1px dashed #d9d9d9;
    border-radius: 2px;
    width: 178px;
    height: 178px;
    border-radius: 6px;
    margin-left: 6px;
    &.active {
        background-color: #409eff;
    }
}
</style>

Select Attributes

| 参数 | 说明 | 类型 | 可选值 | 默认值 | | ------------- | ------------ | ------------------- | ------ | ------ | | value/v-model | 绑定值,必填 | string/number/Array | | | | multiple | 多选 | boolean | | false | | tag | 自定义标签 | string | | div |

Select Provide

| 参数 | 说明 | | --------- | ---------------- | | $Selector | UvSelect实例对象 |

Select Methods

| 参数 | 说明 | | | ------------- | ------------------------------------------------------------ | ------------ | | optSelect | 用于修改UvSelect的值。如果multiple为true,既能用来选中也能用来取消选中某个option | {value:'xx'} | | calcOptActive | 用于表示当前option的值是否被选中 | value |

computed: {
    active() {
        return this.$Selector.calcOptActive(this.value);
    },
},
methods: {
    curOptionSelect() {
        this.$Selector.optSelect({ value: this.value });
    },
},

UvDialog

函数式弹窗,将Vue组件赋值给参数view,调用show可以拉起一个弹窗,弹窗的内容是view传入的Vue组件内容。

组织弹窗功能时,你不再需要导入一个弹窗.vue组件,在components声明然后再在template模板中使用<弹窗></弹窗>;更不需要声明一个isShow来控制弹窗的开关。

你只需要专注弹窗的内容组件实现即可,这使我们的业务代码的内聚性更高。

Usage

<template>
	<div>
		<div><button @click="showDialog">showDialog</button></div>
	</div>
</template>

<script>
import dialogContent from "./cmp/dialogContent.vue"
export default {
	name: "dialogtest",
	methods: {
		showDialog() {
			const $UvDialog = this.$UvDialog
      // 或 new UvDialog
			new $UvDialog(
				{
					view: dialogContent,
					router: this.$router,
					store: this.$store
				},
				{
					originPage: "dialogTest",
					onConfirm: (data) => {
						console.log("onConfirm", data)
					}
				}
			).show()
		}
	}
}
</script>

dialogContent

<template>
	<div class="dialog-content">
		<div>{{ originPage }}</div>
		<div>
			<div>{{ msg }}</div>
			<el-input v-model="msg" placeholder="请输入内容"></el-input>
			<div style="text-align: right">
				<el-button type="primary" @click="printRoute"> 输出$route $store </el-button>
				<el-button @click="close">取消</el-button>
				<el-button type="primary" @click="confirm">确认</el-button>
			</div>
		</div>
	</div>
</template>

<script>
export default {
	name: "dialogContent",
	data() {
		return {
			msg: "123"
		}
	},
	methods: {
		close() {
			this.$emit("hide")
		},
		printRoute() {
			console.log(this.$route)
			console.log(this.$router)
			console.log(this.$store)
		},
		confirm() {
			this.onConfirm && this.onConfirm(this.msg)
			this.close()
		}
	}
}
</script>

<style>
.dialog-content {
	width: 500px;
	height: 300px;
	background: white;
}
</style>

Parameter Type

new UvDialog({view,router,store},cfg)

| 参数 | 说明 | 类型 | 默认值 | | ------ | ------------------------------------------------------------ | ------------ | ------ | | view | 弹窗的内容组件 | VueComponent | | | router | 路由器,如果你需要在view中访问路由,那么该参数必填,router:this.$router | VueRouter | | | store | 状态管理器,如果你需要在view中访问Vuex的状态,那么该参数必填,store:this.$store | Store | | | cfg | 额外的参数,这相当于给view组件加一个mixin,你可以在view组件中通过this访问到cfg的内容,通常用来传递回调事件或者传入初始参数。 | Any | |

todo

  • 支持挂载到指定的DOM,而不是只挂载document.body
  • show支持promise
  • 略去router和store配置

UvCountDown

倒计时,基于requestAnimation

Usage

<template>
	<div>
		<el-button type="primary" @click="flag = !flag">toggle</el-button>
		<UvCountDown :value="futureDeadline" v-if="flag">
			<template #default="{ d, h, m, s }">
				{{ d }}
				{{ h }}
				{{ m }}
				{{ s }}
			</template>
		</UvCountDown>
		<keepAlive>
			<UvCountDown :value="lastDeadline" v-if="flag">
				<template #default="{ d, h, m, s }">
					{{ d }}
					{{ h }}
					{{ m }}
					{{ s }}
				</template>
			</UvCountDown>
		</keepAlive>
	</div>
</template>

<script>
export default {
	data() {
		return {
			futureDeadline: Date.now() + 1000 * 60 * 70,
			lastDeadline: Date.now() - 1000 * 60 * 60,
			flag: true
		}
	}
}
</script>

CountDown Attributes

| 参数 | 说明 | 类型 | 可选值 | 默认值 | | ----------- | ------------------------------------------------------------ | ------------------ | ---------- | ------ | | value | 确定的时间点,必填,支持Date对象/毫秒数/YYYY-MM-DD hh:mm:ss三种格式 | Date/Number/String | | | | timeIndices | 是否开启倒计时功能 | Boolean | true/false | true | | tag | 自定义标签 | string | | div |

CountDown Event

| 事件名 | 说明 | 回调参数 | | ------ | ------------------------------------------------ | -------- | | start | 开始倒计时,在mounted、activated阶段触发 | | | pause | 暂停倒计时,在deactivated、beforeDestroy阶段触发 | | | end | 倒计时结束,达到目标时间 | |

CountDown Methods

| 参数 | 说明 | | | -------------- | ---------- | ---- | | startCountDown | 开始倒计时 | | | pauseCountDown | 暂停倒计时 | |

CountDown Slot

| name | 说明 | 参数 | | ---- | ---------------------------------------------------- | -------------- | | - | 用于向视图传递数据的插槽,d-h-m-s分别表示日-时-分-秒 | { d, h, m, s } |

todo

  • 目前修改value的值会让暂停状态下的CountDown启动倒计时,这或许是个bug

todo

  • v-form
  • changelog