Vue项目中常用的实用技巧汇总
目录
- 前言
- 1. 使用 $attrs 和 $listeners 进行多层级的数据和事件传递
- 2. 实现数据的双向绑定,方便维护数据
- 使用 .sync 实现 Prop 的“双向绑定”
- 使用 model 选项
- 3. 使用 Mixins
- 4. 使用动态组件去懒加载组件
- 5. 在组件作用域内的 CSS 中使用 ::v-deep修改组件样式
- 6. 使用装饰器优化代码
- 7. 利用 require.context 去获取项目目录信息
- 总结
- 引用
前言 在 Vue 项目开发中,很容易产生一些问题,比如代码重复、繁杂等,其实 Vue 项目开发中有很多技巧可以使用,本文将列出一些简单且很好用的几个技巧,帮助我们写出漂亮的代码。用到的技术栈是 Vue2.0 + TypeScript +vue-property-decorator + ElementUI。将用到以下几个技巧:
- 使用 $attrs 和 $listeners 进行多层级的数据和事件传递
- 实现数据的双向绑定,方便维护数据
- 使用 Mixins
- 使用动态组件去懒加载组件
- 在组件作用域内的 CSS 中使用 ::v-deep修改组件样式
- 使用装饰器优化代码
- 利用 require.context 去获取项目目录信息
1. 使用 $attrs 和 $listeners 进行多层级的数据和事件传递
先聊聊如何传递 Prop,可以分为静态和动态的 Prop:
了解了 Props 的传递方式,在看看官方文档是怎么定义 $attrs 的,在尤大大的文档中这样介绍了 $attrs:
$attrs:包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件
$attrs包含了传入到父作用域中没有在 props 声明的其他 props,因此我们可以用 $attrs 去代替那些父组件中不需要的而子组件需要的 props, 通过 v-bind="$attrs" 统一传递给后代。这样就避免了一个个声明然后再一个个传递。
上面这一行代码就通过 v-bind="$attrs" 的方式将本作用域中不作为 prop 的其他属性传递给了 blog-post 组件。
父组件通过 $attrs 传递给后代组件后,后代组件如果想通过触发事件来更新父组件状态该如何处理?如果一级一级地往上 emit 事件,会不会弄得代码太繁琐复杂了?在 Vue 中可以通过 $listeners 解决这个问题,先看看官方文档关于$listeners 的说明:
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。文档中说了 $listeners 包含了父作用域中的事件监听器。意思就是 $listeners 表示了父组件中的事件监听器集合,只要是触发父组件的事件,而不是自己的,就可以用一个 v-on="$listeners"表示。
{{ title }}
上面的代码示例中,中间层的组件内通过 v-bind="$attrs" 将其余的 Prop 传递给了 Child 组件,再通过 v-on="$listeners" 绑定父作用域中的事件监听器,一旦 emit 就会传给了父组件。
2. 实现数据的双向绑定,方便维护数据
有很多这样的场景,父组件需要传递数据给子组件,且在子组件触发数据更新的时候,马上反馈给父组件,父组件数据更新,单向数据流向子组件,最后子组件更新。通常情况用 props + $emit 的方式去更新状态,但是这种处理方式有点笨拙,且不易维护,所以可以通过实现数据的“双向绑定”来提高代码的可维护性。可以通过这以下方式去实现:
使用 .sync 实现 Prop 的“双向绑定”
在 v-bind prop的时候添加.sync 修饰符,赋新值的时候用this.$emit('update:propName', newValue)
如果要更新上述代码中的 title 值,只需要this.$emit('update:title', '新标题'),完成数据更新。
使用 model 选项
model 是2.2.0+ 新增的选项,一个组件上的 v-model 默认会利用名为 value的 Prop和名为 input 的事件, 而 model 选项可以规定 Prop 名称和事件名称来实现 v-model,好处是在实现 v-model 的同时也避免了 Prop 和事件名的冲突。
自定义组件的 v-model
checked {{checked}}
如果只需要一个的话,也可以直接继承
在遇到功能点多,代码量大的页面时,我们可以利用 Mixin 抽离一些功能点,通过文件去管理这些功能,这样会比较方便去管理代码。
4. 使用动态组件去懒加载组件
组件在加载都是同步的,但当页面内容很多,有些组件并不需要一开始就加载出来的比如弹窗类的组件,这些就可以用动态组件,当用户执行了某些操作后再加载出来,这样可以提高主模块加载的性能, 在 Vue 中可以使用 component 动态组件, 依 is 的值,来决定哪个组件被渲染。
主页面
示例代码中,只有当点击的时候才会去加载组件。component 还可以配合 v-show 去控制显示和隐藏,这样这个component 只会 mounted 一次,优化性能。
5. 在组件作用域内的 CSS 中使用 ::v-deep修改组件样式
有很多场景想更改 UI 组件样式,然后怕影响别人的使用,加上 scoped 后又不能生效,可以使用::v-deep 深度作用选择器去修改组件作用域内的 CSS 的样式。在 CSS 中我们可以使用 >>> 操作符,但在预处理器中的写法就要用 /deep/ 或 ::v-deep。
>>> .ivu-tabs-tabpane {background: #f1f1f1; }/deep/ .ivu-tabs-tabpane {background: #f1f1f1; }::v-deep .ivu-tabs-tabpane {background: #f1f1f1; }
::v-deep 和 /deep/ 作用是一样的,但不推荐使用 /deep/, 在 Vue3.0 中将不支持 /deep/ 这种写法。
6. 使用装饰器优化代码
装饰器增加了代码的可读性,清晰地表达了意图,而且提供一种方便的手段,增加或修改类的功能,比如给类其中的方法提供防抖的功能。
import debounce from 'lodash.debounce'; export function Debounce(delay: number, config: object = {}) {return (target: any, prop: string) => {return {value: debounce(target[prop], delay, config),}; }; }
这样的好处是使用起来非常方便,另外增加了代码的可读性。
@Debounce(300)onIdChange(val: string) {this.$emit('idchange', val); }
7. 利用 require.context 去获取项目目录信息
关于 require.context,webpack 文档是这么描述的:
可以给这个函数传入三个参数:一个要搜索的目录,一个标记表示是否还搜索其子目录, 以及一个匹配文件的正则表达式。根据这个提示,我们可以引用到一个文件夹下面的所有文件,由此可以利用获取的文件信息去做一些操作,比如在注册组件的时候,原本我们注册组件的时候需要一个个引入并且一个个注册,而且后面想加新的,又要再写上,现在可以通过 require.context 去优化这一段代码。
webpack 会在构建中解析代码中的 require.context() 。如果想引入一个文件夹下面的所有文件,或者引入能匹配一个正则表达式的所有文件,这个功能就会很有帮助
// import WmsTable from './wms-table/table/index'; import Table from './table/index.vue'; import CustomHooks from './custom-hooks/custom-hooks-actions/index'; import SFilter from './s-filter/filter-form'; import WButton from './button/index'; import CreateForm from './createForm/create-form/CreateForm.vue'; import Action from './table/action-table-column.vue'; import DetailItem from './detail-item.vue'; Vue.component('w-filter', SFilter); Vue.component('w-button', WButton); Vue.component('custom-hooks', CustomHooks); Vue.component('create-form', CreateForm); Vue.component('w-table', Table); Vue.component('w-table-action', Action); Vue.component('zonetime-date-picker', ZonetimeDatePicker); Vue.component('detail', DetailItem);
注册全局组件的时候,不需要一个一个 import,和一个个去注册,使用 require.context 可以自动导入模块,这样的好处在于,当我们新建一个组件,不用自己再去手写注册,而在一开始就帮我们自动完成。
const contexts = require.context('./', true, /\.(vue|ts)$/); export default {install (vm) {contexts.keys().forEach(component => {const componentEntity = contexts(component).default; if (componentEntity.name) {vm.component(componentEntity.name, componentEntity); }}); }};
总结
本文介绍了在 Vue 实战中经常用到的一些技巧,这些技巧的目的都是为了提升开发效率,比如简单地实现双向数据绑定和数据跨级传递等,另外也可以提高代码的可维护性、可读性,比如很实用的装饰器和利用 Mixin 拆分代码和管理功能点。
到此这篇关于Vue项目中常用的实用技巧汇总的文章就介绍到这了,更多相关Vue项目常用技巧内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
【Vue项目中常用的实用技巧汇总】
引用
- require.context
- Vue 官方文档
推荐阅读
- vue-cli|vue-cli 3.x vue.config.js 配置
- 2020-04-07vue中Axios的封装和API接口的管理
- 17|17 关山松 第二课作业#公众号项目# D20
- RxJava|RxJava 在Android项目中的使用(一)
- Hacking|Hacking with iOS: SwiftUI Edition - SnowSeeker 项目(一)
- VueX--VUE核心插件
- 靠QQ月入上万灰色暴利偏门的项目
- spring|spring boot项目启动websocket
- vue组件中为何data必须是一个函数()
- 用npm发布一个包的教程并编写一个vue的插件发布