其他分享
首页 > 其他分享> > 十分钟让你学会Vue的这些巧妙冷技巧

十分钟让你学会Vue的这些巧妙冷技巧

作者:互联网

学习成为一个更好的Vue开发者并不总是关于那些需要花时间和精力才能掌握的大概念。掌握一些技巧和窍门,可以让我们的编程生活变得更容易--没有大量重复的工作。 在用 Vue 开发的这几年里,我学到了很多有用的技巧。有些很取巧,有些几乎每天都在用,有些则更高级--但它们都很有用。 1. 将一个 prop 限制在一个类型的列表中 {#将一个-prop-限制在一个类型的列表中 data-id="heading-0"} 使用 prop 定义中的 validator 选项,可以将一个 prop 类型限制在一组特定的值中。 export default { name: 'Image', props: { src: { type: String, }, style: { type: String, validator: s => ['square', 'rounded'].includes(s) } } }; 复制代码 <button class="button" @click="$emit('click')"> <slot> <!-- Used if no slot is provided --> Click me </slot> </button> 复制代码 <template> <button class="button" @click="$emit('click')"> <slot> <div class="formatting"> {{ text }} </div> </slot> </button> </template> 复制代码 <!-- Uses default functionality of the component --> <ButtonWithExtensionPoint text="Formatted text" /> ​ <ButtonWithExtensionPoint> <div class="different-formatting"> Do something a little different here </div> </ButtonWithExtensionPoint> 复制代码 watch { '$route.query.id'() { // ... } } 复制代码 <ComplicatedChart v-show="chartEnabled" /> 复制代码 <DataTable> <template #header="tableAttributes"> <TableHeader v-bind="tableAttributes" /> </template> </DataTable> 复制代码 <DataTable #header="tableAttributes"> <TableHeader v-bind="tableAttributes" /> </DataTable> 复制代码 const $slots = { default: <default slot>, icon: <icon slot>, button: <button slot>, }; 复制代码 <!-- Slots.vue --> <template> <div> <h2>Here are some slots</h2> <slot /> <slot name="second" /> <slot name="third" /> </div> </template> 复制代码 <template> <Slots> <template #second> This will be applied to the second slot. </template> </Slots> </template> 复制代码 ​ $slots = { second: <vnode> } 复制代码 <template> <div> <h2>A wrapped slot</h2> <div v-if="$slots.default" class="styles"> <slot /> </div> </div> </template> 复制代码 <template> <div> <h2>This is a pretty great component, amirite?</h2> <div class="default-styling"> <slot > </div> <button @click="$emit('click')">Click me!</button> </div> </template> 复制代码 <div> <h2>This is a pretty great component, amirite?</h2> <div class="default-styling"> <!-- 槽中没有内容,但这个div 仍然被渲染。糟糕 --> </div> <button @click="$emit('click')">Click me!</button> </div> 复制代码 <!-- 可惜这个事件不存在 --> <slot @change="update" /> 复制代码 export default { mounted() { // 当有变化时调用`update` const observer = new MutationObserver(this.update); ​ // 监听此组件的变化 observer.observe(this.$el, { childList: true, subtree: true }); } }; 复制代码 <style scoped> .component { background: green; } </style> 复制代码 在 Vue3 中,错误处理程序只能处理 template 和 watcher 错误,但是 Vue2的错误处理程序可以捕获几乎所有错误。这两个版本中的警告处理程序只在开发阶段有效。 ::: 例如,如果一个错误未被处理,应用程序不会直接崩溃,你可以显示一个完整的错误屏幕,让用户刷新或尝试其他东西。 像 Bugsnag 和 Rollbar 这样的错误跟踪服务,可以钩住这些处理程序来记录错误,但你也可以用它们来更优雅地处理错误,以获得更好的用户体验。 // Vue 3 const app = createApp(App); app.config.errorHandler = (err) => { alert(err); }; // Vue 2 Vue.config.errorHandler = (err) => { alert(err); }; 复制代码 我们可以为Vue中的错误和警告提供一个自定义处理程序。 25. 处理错误(和警告)的更好方法 {#处理错误和警告的更好方法 data-id="heading-28"} 现在看起来就更容易理解,而且它在做什么,一目了然。 <template> <div class="card"> <img src="imgPath" /> <h3> {{ title }} </h3> <template v-if="expanded"> <h4> {{ subheading }} </h4> <div class="card-content"> <slot /> </div> <SocialShare /> </template> </div> </template> 复制代码 我们可以使用 template 标签来分组这些元素,并将 v-if 提升到模板 template 本身。 但我们能优化它。 这有点笨拙,而且一开始并不明显,一堆这样的元素被显示和隐藏在一起。在一个更大、更复杂的组件上,这可能是一个更糟糕的情况 <template> <div class="card"> <img src="imgPath" /> <h3> {{ title }} </h3> <h4 v-if="expanded"> {{ subheading }} </h4> <div v-if="expanded" class="card-content" > <slot /> </div> <SocialShare v-if="expanded" /> </div> </template> 复制代码 在这个例子中,我们有几个元素都使用同一个v-if条件。 我喜欢用它来简化v-if逻辑,有时也用v-for。 template 标签可以在模板中的任何地方使用,以更好地组织代码。 24. template 标签的另一个用途 {#template-标签的另一个用途 data-id="heading-27"} <RouterLink :to="{ query: { dateRange: newDateRange } }"> 复制代码 为了改变它,我们使用 RouterLink 组件并更新 query。 const dateRange = this.$route.query.dateRange; 复制代码 使用 vue-router 获取查询参数是这样工作的(这也适用于大多数Vue框架,如Nuxt和Vuepress): 我们可以存储过滤器、搜索值、模态框是打开还是关闭,或者在列表的哪个位置滚动以完美地实现无限分页。 这对于应用中用户可能共享大量链接的部分来说是非常棒的,对于服务器渲染的应用,或者在两个独立的应用之间通信的信息比普通链接通常提供的更多。 someurl.com/edit?date-range=last-week 复制代码 例如,你加载一个已经选择了日期范围过滤器的页面: 我们可以在URL中存储(一点)状态,允许我们直接跳到页面上的一个特定状态。 23. 用Vue Router进行深度链接 {#用vue-router进行深度链接 data-id="heading-26"} watch( colours, () => { console.log('The list of colours has changed!'); }, { deep: true, } ); 复制代码 使用Vue 3的API会是这样的: export default { name: 'ColourChange', props: { colours: { type: Array, required: true, }, }, watch: { // 使用对象语法,而不仅仅是方法 colours: { // 这将让Vue知道要在数组内部寻找 deep: true, handler() console.log('The list of colours has changed!'); } } } } 复制代码 通常,这是因为我们试图监听数组或对象,但没有将deep设置为true 使用 watcher 最棘手的部分是,有时它似乎不能正确触发。 22. 监听数组和对象 {#监听数组和对象 data-id="heading-25"} 有时,"最好的 "解决方案最终会成为最糟糕的解决方案。 是的,我们打破了 "props down, events up"" 的规则,我们打破了封装,但是这样做更清晰,更容易理解,所以是值得的 <!-- Parent.vue --> <template> <ChildComponent ref="child" /> </template> 复制代码 // Somewhere in Parent.vue this.$refs.child.method(); 复制代码 相反,如果我们在子组件上设置一个 ref,我们可以直接调用该方法: 这可以正常工作,但只能在第一次调用时使用。如果您需要多次触发此操作,则必须进行清理并重置状态。逻辑是这样的 <template> <ChildComponent :tell-me-what-to-do="someInstructions" @something-happened="hereIWillHelpYouWithThat" /> </template> 复制代码 // Child.vue export default { props: ['trigger'], watch: { shouldCallMethod(newVal) { if (newVal) { // Call the method when the trigger is set to `true` this.method(); } } } } 复制代码 通常情况下,我们使用 props 和 events 在组件之间进行交流。props 被下发到子组件中,而events 被上发到父组件中。 有时候,"最佳实践"并不适用于你正在做的事情,你需要一个像这样的逃生口。 再解释一下这个问题。 <!-- Parent.vue --> <template> <ChildComponent ref="child" /> </template> 复制代码 // Somewhere in Parent.vue this.$refs.child.method(); 复制代码 我们可以从一个组件的外部通过给它一个 ref 用来调用一个方法。 21. 从组件外部调用一个方法 {#从组件外部调用一个方法 data-id="heading-24"} 但是这个OverflowMenu将被使用几十次,现在如果我们想更新图标或它的行为,我们可以非常容易地做到。而且,使用它也更简单了。 这似乎不值得把它做成一个可重复使用的组件,因为它只有几行。难道我们就不能在每次要使用这样的菜单时添加图标吗? 在这里,我们采用了一个菜单组件,但在触发它的按钮上添加了一个 ellipsis 图标。(省略号)的图标来触发它的打开。 <!-- OverflowMenu.vue --> <template> <Menu> <!-- 添加一个自定义按钮来触发我们的菜单 --> <template #button v-slot="bind"> <!-- 使用bind来传递click处理程序、a11y 属性等 --> <Button v-bind="bind"> <template #icon> <svg src="./ellipsis.svg" /> </template> </Button> </template> </Menu> </template> 复制代码 因为我没有到处重写这段代码,所以更新它变得更加容易,而且我可以确保每个OverflowMenu的外观和工作方式都完全一样--因为它们是一样的!"。 我经常让小的和短的组件可以重复使用。 可重复使用的组件不一定是大的或复杂的东西。 20. 可重复使用的组件并不是你所想的那样 {#可重复使用的组件并不是你所想的那样 data-id="heading-23"} 如果你需要分享样式、文件或其他任何东西,这可能会非常方便。 <template src="./template.html"></template> <script src="./script.js"></script> <style scoped src="./styles.css"></style> 复制代码 可以像常规HTML文件一样导入文件: 这是**SFC(单文件组件)**的一点已知功能。 19. 多文件单文件组件 {#多文件单文件组件 data-id="heading-22"} 这方面的其他用途包括(但不限于): 只要记住,这个元数据对组件的每个实例都是一样的,而且不是响应式的。 export default { name: 'LiveUsersWidget', columns: 3, created() { //

标签:十分钟,Vue,插槽,代码,巧妙,复制,组件,data,heading
来源: https://www.cnblogs.com/tksd/p/16344685.html