vueUse 是 Anthony Fu 的一个开源项目,它为 Vue 开发人员提供了大量适用于 Vue 2 和 Vue 3 的基本 Composition api 实用程序函数。
它有几十个解决方案,适用于常见的开发者用例,如跟踪Ref变化、检测元素可见性、简化常见的Vue模式、键盘/鼠标输入等。这是一个真正节省开发时间的好方法,因为你不必自己添加所有这些标准功能。
我喜欢VueUse库,因为它在决定提供哪些实用工具时真正把开发者放在第一位,而且它是一个维护良好的库,因为它与Vue的当前版本保持同步。
如果你想看到每一个实用程序的完整列表,我绝对建议你去看看官方文档。但总结一下,VueUse中有9种类型的函数。
这些类别中的大多数都包含几个不同的功能,所以VueUse对于你的使用情况来说是很灵活的,可以作为一个很好的地方来快速开始构建Vue应用程序。
在本教程中,我们将看一下5个不同的VueUse函数,这样你就可以了解在这个库中工作是多么容易。但首先,让我们将其添加到Vue项目中!
VueUse的最大特点之一是,它只用一个软件包就能同时兼容Vue 2和Vue 3!
安装VueUse有两种选择npm或CDN
npm i @vueuse/core # yarn add @vueuse/core
我建议使用NPM,因为它使用法更容易理解,但如果我们使用CDN,VueUse将在应用程序中通过 window.VueUse 访问。
对于NPM的安装,所有的功能都可以通过使用标准的对象重构从 @vueuse/core 中导入,像这样访问。
import { useRefHistory } from ‘@vueuse/core’
好了,现在我们已经安装了VueUse,让我们在应用程序中使用它!
useRefHistory 跟踪响应式数据的更改
useRefHistory 跟踪对Ref所做的每一个改变,并将其存储在一个数组中。这使我们能够轻松地为我们的应用程序提供撤销和重做功能。
让我们看一个示例,其中我们正在构建一个我们希望能够撤消的文本区域。
第一步是在不使用 VueUse 的情况下创建我们的基本组件——使用 ref、textarea 和用于撤消和重做的按钮。
<template>
<p>
<button> Undo </button>
<button> Redo </button>
</p>
<textarea v-model="text"/>
</template>
<script setup>
import { ref } from 'vue'
const text = ref('')
</script>
<style scoped>
button {
border: none;
outline: none;
margin-right: 10px;
background-color: #2ecc71;
color: white;
padding: 5px 10px;;
}
</style>
然后,让我们通过导入 useRefHistory 函数,然后从我们的文本 ref 中提取history、undo 和 redo 属性来添加 VueUse。这就像调用 useRefHistory 并传递我们的 ref 一样简单。
import { ref } from 'vue'
import { useRefHistory } from '@vueuse/core'
const text = ref('')
const { history, undo, redo } = useRefHistory(text)
每次我们的 ref 更改时,这都会触发一个观察者——更新我们刚刚创建的 history 属性。
然后,为了让我们能真正看到发生了什么,让我们打印出模板内的历史记录,同时在点击相应的按钮时调用我们的 undo 和 redo 函数。
<template>
<p>
<button @click="undo"> Undo </button>
<button @click="redo"> Redo </button>
</p>
<textarea v-model="text"/>
<ul>
<li v-for="entry in history" :key="entry.timestamp">
{{ entry }}
</li>
</ul>
</template>
<script setup>
import { ref } from 'vue'
import { useRefHistory } from '@vueuse/core'
const text = ref('')
const { history, undo, redo } = useRefHistory(text)
</script>
<style scoped>
button {
border: none;
outline: none;
margin-right: 10px;
background-color: #2ecc71;
color: white;
padding: 5px 10px;;
}
</style>
好的,让我们运行它。当我们输入时,每个字符都会触发历史数组中的一个新条目,如果我们点击undo/redo,我们会转到相应的条目。
还有不同的选项可以为此功能添加更多功能。例如,我们可以深入跟踪反应对象并限制这样的历史条目的数量。
const { history, undo, redo } = useRefHistory(text, {
deep: true,
capacity: 10,
})
有关完整的选项清单,请务必查看文档。
onClickOutside 关闭模态
onClickOutside 检测在一个元素之外的任何点击。根据我的经验,这个功能最常见的使用情况是关闭任何模式或弹出窗口。
通常情况下,我们希望我们的模态挡住网页的其他部分,以吸引用户的注意力并限制错误。然而,如果他们真的点击了模态之外的内容,我们希望它能够关闭。
只需两个步骤即可完成此操作:
这是一个使用 onClickOutside 的带有弹出窗口的简单组件。
<template>
<button @click="open = true"> Open Popup </button>
<div class="popup" v-if='open'>
<div class="popup-content" ref="popup">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Corporis aliquid autem reiciendis eius accusamus sequi, ipsam corrupti vel laboriosam necessitatibus sit natus vero sint ullam! Omnis commodi eos accusantium illum?
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { onClickOutside } from '@vueuse/core'
const open = ref(false) // state of our popup
const popup = ref() // template ref
// whenever our popup exists, and we click anything BUT it
onClickOutside(popup, () => {
open.value = false
})
</script>
<style scoped>
button {
border: none;
outline: none;
margin-right: 10px;
background-color: #2ecc71;
color: white;
padding: 5px 10px;;
}
.popup {
position: fixed;
top: ;
left: ;
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: rgba(, , , 0.1);
}
.popup-content {
min-width: 300px;
padding: 20px;
width: 30%;
background: #fff;
}
</style>
结果是这样的,我们可以用我们的按钮打开弹出窗口,然后在弹出内容窗口外点击关闭它。
useVModel 简化了 v-model 绑定
Vue 开发人员的一个常见用例是为组件创建自定义 v-model 绑定。这意味着我们的组件接受一个值作为 prop,并且每当该值被修改时,我们的组件都会向父级发出更新事件。
useVModel函数将其简化为只使用标准的 ref 语法。假设我们有一个自定义的文本输入,试图为其文本输入的值创建一个 v-model。 通常情况下,我们必须接受一个值的prop,然后emit一个变化事件来更新父组件中的数据值。
我们可以使用useVModel,把它当作一个普通的ref,而不是使用ref并调用 props.value 和 update:value。这有助于减少我们需要记住的不同语法的数量!
<template>
<div>
<input
type="text"
:value="data"
@input="update"
/>
</div>
</template>
<script>
import { useVModel } from '@vueuse/core'
export default {
props: ['data'],
setup(props, { emit }) {
const data = useVModel(props, 'data', emit)
console.log(data.value) // equal to props.data
data.value = 'name' // equal to emit('update:data', 'name')
const update = (event) => {
data.value = event.target.value
}
return {
data,
update
}
},
}
</script>
每当我们需要访问我们的值时,我们只需调用 .value,useVModel将从我们的组件props中给我们提供值。而每当我们改变对象的值时,useVModel会向父组件发出一个更新事件。
下面是一个快速的例子,说明该父级组件可能是什么样子…
<template>
<div>
<p> {{ data }} </p>
<custom-input
:data="data"
@update:data="data = $event"
/>
</div>
</template>
<script>
import CustomInput from './components/CustomInput.vue'
import { ref } from 'vue'
export default {
components: {
CustomInput,
},
setup () {
const data = ref('hello')
return {
data
}
}
}
结果看起来像这样,我们在父级中的值始终与子级中的输入保持同步。
使用IntersectionObserver 跟踪元素可见性
在确定两个元素是否重叠时,Intersection Observers 非常强大。一个很好的用例是检查元素当前是否在视口中可见。
本质上,它检查目标元素与根元素/文档相交的百分比。如果该百分比超过某个阈值,它会调用一个回调来确定目标元素是否可见。
useIntersectionObserver 提供了一个简单的语法来使用IntersectionObserver API。我们所需要做的就是为我们想要检查的元素提供一个模板ref。默认情况下,IntersectionObserver将以文档的视口为根基,阈值为0.1——所以当这个阈值在任何一个方向被越过时,我们的交集观察器将被触发。
这个例子的代码可能是这样的:我们有一个假的段落,只是在我们的视口中占据了空间,我们的目标元素,然后是一个打印语句,打印我们元素的可见性。
<template>
<p> Is target visible? {{ targetIsVisible }} </p>
<div class="container">
<div class="target" ref="target">
<h1>Hello world</h1>
</div>
</div>
</template>
<script>
import { ref } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
export default {
setup() {
const target = ref(null)
const targetIsVisible = ref(false)
const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }], observerElement) => {
targetIsVisible.value = isIntersecting
},
)
return {
target,
targetIsVisible,
}
},
}
</script>
<style scoped>
.container {
width: 80%;
margin: auto;
background-color: #fafafa;
max-height: 300px;
overflow: scroll;
}
.target {
margin-top: 500px;
background-color: #1abc9c;
color: white;
padding: 20px;
}
</style>
当我们运行并滚动它时,我们会看到它正确地更新了。
我们还可以为 Intersection Observer 指定更多选项,例如更改其根元素、边距(用于计算交点的根边界框的偏移量)和阈值级别。
const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }], observerElement) => {
targetIsVisible.value = isIntersecting
},
{
// root, rootMargin, threshold, window
// full options in the source: https://github.com/vueuse/vueuse/blob/main/packages/core/useIntersectionObserver/index.ts
threshold: 0.5,
}
)
同样重要的是,这个方法返回一个 stop 函数,我们可以调用这个函数来停止观察交叉点。如果我们只想追踪一个元素在屏幕上第一次可见的时候,这就特别有用。
在这段代码中,一旦 targetIsVisible 被设置为 true,观察者就会停止,即使我们滚动离开目标元素,我们的值也会保持为true。
const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }], observerElement) => {
targetIsVisible.value = isIntersecting
if (isIntersecting) {
stop()
}
},
)
useTransition 在值之间过渡
useTransition 是整个veuse库中我最喜欢的函数之一。它允许我们在一行内平滑地转换数值。我们有一个存储为ref的数字源和一个将在不同数值之间缓和的输出。例如,假设我们想建立一个计数器
我们可以通过三个步骤来做到这一点:
<script setup>
import { ref } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'
const source = ref(0)
const output = useTransition(source, {
duration: 3000,
transition: TransitionPresets.easeoutExpo,
})
source.value = 5000
</script>
然后,在我们的模板中,我们希望显示 output 的值,因为它可以在不同值之间平滑过渡。
<template>
<h2>
<p> Join over </p>
<p> {{ Math.round(output) }}+ </p>
<p>Developers </p>
</h2>
</template>
<script setup>
import { ref } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'
const source = ref()
const output = useTransition(source, {
duration: 3000,
transition: TransitionPresets.easeOutExpo,
})
source.value = 5000
</script>
这就是结果!
我们还可以使用 useTransition 来过渡整个数字数组,这在处理位置或颜色时很有用。 处理颜色的一个绝招是使用一个计算属性将RGB值格式化为正确的颜色语法。
<template>
<h2 :style="{ color: color } "> COLOR CHANGING </h2>
</template>
<script setup>
import { ref, computed } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'
const source = ref([, , ])
const output = useTransition(source, {
duration: 3000,
transition: TransitionPresets.easeOutExpo,
})
const color = computed(() => {
const [r, g, b] = output.value
return `rgb(${r}, ${g}, ${b})`
})
source.value = [255, , 255]
</script>
一些进一步定制的酷方法是使用任何内置的过渡预设或使用css缓动函数来定义我们自己的过渡。
在当今的专业环境中,项目经理需要戴上各种帽子,在管理团队的日常功能和理解大局策略之间切换。正因为如此,项目经理对组织变得更有价值,并且他们对技能和战略角色的需求在全球范围内不断增长。但这也提出了一个问题:如何在如此高压的环境中成为更好的项目经理?
随机产生规定范围内的整数,然后再产生相同范围内的整数,两者相同时,则暂停。所用知识:Math.random() * num: 产生从0到num的随机数,Math.floor(): 向下取整,简单的DOM操作等
我马上就要毕业了没有开发经验怎么办?我投递了 N 多公司全部没有给工作机会,有的给了面试机会也是没有下文了怎么办?我简历上什么东西都没有,要不要伪造一个工作经历呢?
项目经理这个神奇的职位,改变了我很多工作处事的方式,从前性情纯真的耿直boy,现在变成了人鬼皆爱的老油条, 以下是我当了项目经理之后明白的10件事, 如有雷同,真是太巧。
pm2 大家应该都知道,主要是用来管理 node 进程,但是同样可以用来部署前端代码。也可以手动添加 public key 到服务器上的 ~/.ssh/authorized_keys,
我不是专业的项目经理,这里不讨论大型项目管理的事情。我们比较常遇到的可能是小型的长周期项目,比如2-4个人,做半年甚至一年的项目。这种项目通常不会有专职的项目经理
通过 attachShadow 这个方法生成一个shadow root 即shadow的根节点,然后在这个根节点下面通过循环语句添加水印,利用position为absolute进行排版,使其铺满容器
我相信每个接受过老项目的程序员可能都吐槽过“前人的代码都是屎”。一个已经有些年头的项目,几乎肯定可以看到——到处拷贝来拷贝去的代码,随处可见的拼写错误,头重脚轻的函数……
近几年随着微服务化项目的崛起,逐渐成为许多公司中大型分布式系统架构的主流方式,而今天所说的 RPC 在这其中扮演着至关重要的角色。随着这段日子公司项目微服务化的演进,发现在日常开发中都在隐式或显式的使用 RPC
首先搭建vue项目,lint选择ESLint + Prettier,配置方式选择In dedicated config files。具体搭建过程这里就不赘述了,如果不熟悉的同学可以点击这里。配置 Stylelint,目前还没有stylelint选项,需要我们自己安装相关的 npm 包
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!