Skip to content

Vue 基础

Ref 使用

获取dom元素

通过ref 获取dom 元素

vue
<template>
  <div>
    <input ref="inputRef" />
    <button @click="getInputValue">获取input值</button>
  </div>
</template>

<script>
export default {
  name: 'App',
  components: {},
  methods: {
    getInputValue() {
      console.log(this.$refs.inputRef);
      console.log(this.$refs.inputRef.value); // value 是input DOM元素的属性
    },
  },
};
</script>
shell
> HTMLInputElement
> sdsdsd

image-20230610234701791

在线dom: ref 获取DOM元素

获取子组件实例

获取子组件实例,可以调用子组件的一些方法

children 子组件:

vue
<template>
  <div>children</div>
</template>

<script>
export default {
  name: 'children',
  methods: {
    show() {
      console.log('show');
    },
  },
};
</script>

父组件

vue

<template>
  <div id="app">
    <button @click="handleClick">父组件点击</button>
    <children ref="children" />
  </div>
</template>

<script>
import children from './components/children.vue';
export default {
  name: 'App',
  components: {
    children,
  },
  mouted() {},
  methods: {
    handleClick() {
      this.$refs.children.show();
    },
  },
};
</script>

通过ref获取子组件实例,可以调用子组件的数据和调用子组件的方法。

案例:

chidlren: 

image-20230610231617218

在线dom:vue ref 获取组件实例

Computed 和 Watch 的区别

Computed(计算属性)

  • 它支持缓存,只有依赖的数据发生了变化,才会重新计算
  • 不支持异步,当Computed中有异步操作时,无法监听数据的变化
  • computed的值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data声明过,或者父组件传递过来的props中的数据进行计算的。
  • 如果一个属性是由其他属性计算而来的,这个属性依赖其他的属性,一般会使用computed
  • 如果computed属性的属性值是函数,那么默认使用get方法,函数的返回值就是属性的属性值;在computed中,属性有一个get方法和一个set方法,当数据发生变化时,会调用set方法。

Watch(侦听器)

  • 它不支持缓存,数据变化时,它就会触发相应的操作
  • 支持异步监听
  • 监听的函数接收两个参数,第一个参数是最新的值,第二个是变化之前的值
  • 当一个属性发生变化时,就需要执行相应的操作
  • 监听数据必须是data中声明的或者父组件传递过来的props中的数据,当发生变化时,会触发其他操作,函数有两个的参数:
    • immediate:组件加载立即触发回调函数
    • deep:深度监听,发现数据内部的变化,在复杂数据类型中使用,例如数组中的对象发生变化。需要注意的是,deep无法监听到数组和对象内部的变化。

当想要执行异步或者昂贵的操作以响应不断的变化时,就需要使用watch。

总结

  • computed 计算属性 : 依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值。
  • watch 侦听器 : 更多的是观察的作用,无缓存性,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。

运用场景

  • 当需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时都要重新计算。
  • 当需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许执行异步操作 ( 访问一个 API ),限制执行该操作的频率,并在得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

Computed 和 Methods 的区别

可以将同一函数定义为一个 method 或者一个计算属性。对于最终的结果,两种方式是相同的

不同点:

  • computed: 计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值;
  • method:调用总会执行该函数。

$nextTick 原理及作用

$nextTick是Vue.js框架提供的一个实例方法,它的作用是在DOM更新周期结束后执行回调函数。以下是关于$nextTick的原理和作用的解释:

  1. 原理
    • 当Vue进行DOM更新时,实际的DOM操作是异步执行的。Vue会将DOM更新操作添加到一个队列中,而不是立即执行。
    • 在下一个DOM更新周期开始之前,Vue会清空队列,并对队列中的DOM更新操作进行批处理。这样可以提高性能,并避免频繁的DOM操作。
    • $nextTick方法利用JavaScript的事件循环机制,在DOM更新周期结束后,将回调函数推入任务队列,等待下一个事件循环时执行。
  2. 作用
    • 确保在DOM更新完成后,获取到最新的DOM结构和数据。
    • 在修改数据之后,需要基于更新后的DOM进行一些操作,如获取元素的位置、计算元素的尺寸、操作DOM等。
    • 在下一个DOM更新周期之后执行一些回调函数,以确保正确的顺序和时机。

使用$nextTick的示例代码如下:

js
// 在Vue实例中使用$nextTick
this.$nextTick(() => {
  // 回调函数中的代码在DOM更新周期之后执行
  // 这里可以操作最新的DOM结构和数据
});

注意

$nextTick是一个异步方法,回调函数的执行时机是在下一个事件循环中,而不是立即执行。因此,在使用$nextTick时,应该注意回调函数的执行顺序和时机,确保在正确的时机处理相关逻辑。

vue2新增或修改数据

给对象新增属性

在data 数据中的对象新增属性

vue
<template>
  <div>
    <ul>
      <li v-for="value in obj" :key="value"> {{ value }} </li>
    </ul>
    <button @click="addObjB">添加 obj.b</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      obj: {
        a: 'obj.a'
      }
    }
  },
  methods: {
    addObjB() {
      this.obj.b = 'obj.b'
      console.log(this.obj)
    }
  }
}
</script>

点击 button 会发现,obj.b 已经成功添加,但是视图并未刷新。这是因为在Vue实例创建时,obj.b并未声明,因此就没有被Vue转换为响应式的属性,自然就不会触发视图的更新

image-20230611225245120

在Vue 2中,如果需要将新增的属性转换为响应式属性,可以使用Vue.set方法或者this.$set方法。

示例代码如下:

js

// 使用Vue.set全局方法添加一个响应式属性
Vue.set(this.obj, 'newProperty', 'new value');

或者

javascript
// 在Vue实例中添加一个响应式属性
this.$set(this.obj, 'newProperty', 'new value');

通过使用Vue.setthis.$set方法,新增的属性将成为响应式属性,并且能够触发视图更新。

通过下标修改数组数据

在Vue 2中,通过下标直接修改数组的元素值时,Vue 无法检测到这种变化,不会触发视图的更新。这是因为Vue在处理数组时,无法拦截和追踪直接通过下标修改数组元素的操作。以下是相关情况的说明:

  1. 直接通过下标修改数组元素:
JS
// 假设 data 中有一个数组属性 arr,下标为 index
this.arr[index] = newValue;

这种方式修改数组元素的值,Vue 无法检测到变化,不会触发视图的更新。

  1. 使用 Vue.setthis.$set 修改数组元素:
js
// 假设 data 中有一个数组属性 arr,下标为 index
Vue.set(this.arr, index, newValue);
// 或者
this.$set(this.arr, index, newValue);

使用 Vue.setthis.$set 方法可以通知 Vue 数组元素的变化,Vue 能够检测到变化并触发视图的更新。

  1. 使用 splice 方法修改数组:
js
// 假设 data 中有一个数组属性 arr,下标为 index
this.arr.splice(index, 1, newValue);

使用 splice 方法可以修改数组元素的值,并且 Vue 能够检测到变化并触发视图的更新。

原因

Vue 2的响应式系统是基于ES5的Object.defineProperty实现的,它可以拦截对象属性的读取和修改操作,并在修改时触发视图的更新。然而,对于数组来说,直接通过下标修改数组元素的值并不会触发属性的修改操作,因此 Vue 2 无法检测到这种变化。

  1. 对象属性拦截:Vue 2的响应式系统通过Object.defineProperty来拦截对象属性的读取和修改操作。当访问或修改对象的属性时,Vue会触发相应的getter和setter,从而实现对变化的追踪和视图更新。
  2. 数组的局限性:由于数组的元素是通过下标来访问和修改的,而不是属性,所以无法像对象属性一样直接拦截。Vue 2无法通过Object.defineProperty对数组元素进行劫持和触发更新。
  3. Vue.set 和 this.$set 方法:为了解决直接修改数组元素无法触发视图更新的问题,Vue 提供了 Vue.set(全局方法)和 this.$set(实例方法),可以用来更新数组元素。这些方法会通过内部机制追踪数组的变化并触发视图的更新。
  4. splice 方法:另一种可以触发视图更新的方式是使用数组的 splice 方法,它会改变原数组并触发响应式系统的更新。

因此,在Vue 2中,直接通过下标修改数组元素的值无法被响应式系统追踪和触发视图更新,需要使用 Vue.setthis.$setsplice 方法来修改数组元素并确保视图能够正确更新。

vue重写数组的方法

  1. push(): 在数组末尾添加一个或多个元素,并返回新的长度。
  2. pop(): 删除数组的最后一个元素,并返回删除的元素。
  3. shift(): 删除数组的第一个元素,并返回删除的元素。
  4. unshift(): 在数组的开头添加一个或多个元素,并返回新的长度。
  5. splice(): 修改数组的内容,删除或替换现有元素,或者添加新的元素,并返回被删除的元素。
  6. sort(): 对数组进行原地排序,并返回排序后的数组。
  7. reverse(): 颠倒数组中元素的顺序,并返回颠倒后的数组。

这些重写的数组方法在内部会调用原生的数组方法,并在修改数组后触发响应式更新,通知 Vue 响应式系统进行相应的处理。这样,当使用这些重写的数组方法对数组进行操作时,Vue 2 能够检测到数组的变化并触发视图的更新。

前端知识体系 · wcrane