当前位置: 代码迷 >> 综合 >> Vue开发小技巧
  详细解决方案

Vue开发小技巧

热度:32   发布时间:2024-02-01 04:28:41.0

1.事件绑定和解绑

通常,我们会在mounted中给dom绑定事件,然后在beforeDestroy中解绑。不过,有的时候,绑定和解绑写在两个不同的函数里面会觉得有些麻烦,也不利于维护。其实,可以通过$once+hook将事件绑定和解绑写在一起。

原写法:

  public mounted() {this.targetRef.addEventListener("click", this.add, false);}public beforeDestroy() {this.targetRef.removeEventListener("click", this.add);}

新写法 

  public mounted() {this.initEvent();}private initEvent() {this.targetRef.addEventListener("click", this.add, false);this.$once("hook:beforeDestroy", () => {this.targetRef.removeEventListener("click", this.add);});}

这样,同一个功能就内聚了。

类似的,清除定时器也可以这么写。

2.父组件传递事件监听和属性

在开发中,曾有一些这样的需求。我们要对某个组件做一个包装,比如给按钮包装一个指令,在不需要修改逻辑的情况下快速实现一些额外的功能。

那么,原组件可能有很多属性和事件监听,如果一个一个写是很麻烦的,那么有没有一个快速简单的方式传递所有prop和事件监听给子组件呢?

答案是有的。用v-on和v-bind实现。看下面的demo

包装的组件

<template><div class="proxy"><a-button v-bind="$attrs" v-on="$listeners" @click="testClick"></a-button></div>
</template>

使用:

    <proxy @click="bbb"></proxy>

结果是testClick和bbb的方法都会被触发。

在本人做过的项目中,曾经要给已做好的项目的一些按钮添加埋点功能,就用了这种包装button的方式快速实现,只需要替换按钮组件即可,不需要修改其他的逻辑代码。

3.自定义v-model

曾经有这么一个需求,要给select组件添加自定义的搜索框,并且,样式和组件库自带的搜索不一样。那没办法,只能自己封装了。

用v-model绑定一个属性,那么怎么穿透到子组件呢。

默认组件的v-model,是传递一个value的props,触发子组件的input事件,就会修改绑定的这个属性。看下面的demo

子组件:

  @Prop({ type: Number })public value!: number;public timer = -1;public mounted() {this.timer = window.setInterval(() => {console.log(1111);this.$emit("input", this.value + 1);}, 1e3);this.$once("hook:beforeDestroy", () => {window.clearInterval(this.timer);});}

父组件:

    <proxy v-model="count"></proxy>

这样,子组件就能修改它v-model绑定的属性了

如果想指定属性名和方法呢?可以在子组件通过model选项来控制

  @Model("myEvent")public myProp!: number;public timer = -1;public mounted() {this.timer = window.setInterval(() => {console.log(1111);this.$emit("myEvent", this.myProp + 1);}, 1e3);this.$once("hook:beforeDestroy", () => {window.clearInterval(this.timer);});}

非ts项目,写选项就行了

    model:{prop:'myProp',event:'myEvent'}

4.纯组件

函数式编程有纯函数,react用来渲染只负责渲染的组件(通俗的说就是没有逻辑的组件),其实vue也有类似的,没有额外的hook,只用于渲染的组件

在template标签里加上functional属性即可。纯组件不能有自己的方法、选项等,只有一个context会被传递进来,里面有props

看一个demo

<template functional><div>{{props.count}}</div>
</template>

5.路由参数解耦

在路由上经常需要携带参数,不管是query还是params,都需要在组件内通过路由实例去获取。

其实,我们可以将这些参数作为props传递进组件,这样在获取的时候就可以将参数解耦。

下面这些是定义在路由文件上的:

    {path: "/event",name: "event",component: () =>import(/* webpackChunkName: "event" */ "./components/event.vue"),props: (route: Route) => {const { id, name } = route.query;return {id,name,};},},

props的属性可以是布尔值、对象、函数。

如果props属性为true,那么所有params上的属性都会转换成prop属性传递给组件。如果是对象,那么只有为true的key对应的组件才会有params作为prop传递进来。

这里拿官网的例子:

    {path: '/user/:id',components: { default: User, sidebar: Sidebar },props: { default: true, sidebar: false }}

 

props为函数的话,就是上面我们写的例子。

6.响应数组的变化

我们知道,在当前版本,由于defineProperty的限制,通过数组下标修改数组的值是没办法响应的。(年底vue3应该会正式发布,到时就没这个问题了)

  public list = [1, 2, 3, 4];public editList() {this.list[1] = 3;}

在上面的方法中,editList方法的确修改了数组的值,但是页面上是不会变化的,。

有下面几种方式让页面响应

1:用$set

    // this.list[1] = 3;this.$set(this.list, 1, 3);

$set实际上是让vue重新对数组进行一次数据监听,即初始化defineProperty。

2.借用数组的方法

const methodsToPatch = ['push','pop','shift','unshift','splice','sort','reverse'
]

上面是vue的源码,vue对数组的这些方法做了代理,使用这些方法会触发数组的更新,

所以,在修改数组的值之后,我们手动调用无副作用的方法,就能触发页面的更新。无副作用的方法包括push、unshift、splice。

    this.list[1] = 3;this.list.push();this.list.unshift();this.list.splice();

7.监听子组件的生命周期

如果想监听子组件初始化或者挂载完成的事件,一般做法是给子组件绑定事件,然后子组件在对应的生命周期emit出去,触发父组件的handle。

子组件:

  public created() {this.$emit("hasCreated");}

父组件:

    <proxy @hasCreated="handler"></proxy>

这样其实很麻烦,有的时候子组件并没有额外的逻辑,是父组件需要,但是我们要在子组件一个个生命周期方法里去添加。

我们可以用更简单的方式去监听:

父组件:

    <proxy @hook:created="handler"></proxy>

hook后面的生命周期名字,想监听什么生命周期就写对应的方法名,不需要在子组件写,非常的方便

 

  相关解决方案