vue3 基础-补充 ref & provide-inject

本篇主要对一些被以前内容(渲染, 传值) 等忽略的几个常用小技巧进行补充说明啦.

v-once

即对某个dom节点生效, 其会限定只会渲染一次, 不论数据是如何的变化, 演示如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <title>v-once</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    // v-once: 只能渲染一次哦
    const app = Vue.createApp({
      data () {
        return { count: 1 }
      },
      template: `
      <div @click="count += 1" v-once>
        {{count}}
      </div>
      `
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>

只要加上了这个 v-once 指令, 就只能渲染一次啦, 这在一些输入框, 密码框校验, 性能优化等都有应用哦.

ref

其主要应用在响应式数据获取的场景, 实际功能是获取 真实 dom 节点 或 组件引用的一个语法, 后面我们会细讲, 就这里先抛砖引玉一下先.

<!DOCTYPE html>
<html lang="en">

<head>
  <title>ref 获取 dom 节点</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    // ref: 获取 dom 节点
    const app = Vue.createApp({
      data () {
        return { count: 1 }
      },
      mounted () {
        this.$refs.count.innerHTML = 'youge'
      },
      template: `
      <div>
        <div ref="count">
          {{count}}
        </div>
      </div>
      `
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>

这里的 ref 其实就是对数据 count 的一个响应式包装, 使页面加载完后 (mounted) 能够获取到这个 count 相关的dom节点, 进行内容改变和响应式渲染.

但这种 DOM 操作其实非常不建议, 一个是会带来性能问题, 另一个是维护成本的问题.

ref 的另外一种用途是可以获取子组件的引用, 演示如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <title>ref 获取子组件的引用</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    // ref 获取子组件的引用
    const app = Vue.createApp({
      mounted () {
        this.$refs.mySon.sayHi()
      },
      template: `
      <div>
        <Son ref="mySon" />
      </div>
      `
    })

    app.component('Son', {
      methods: {
        sayHi () {
          console.log('hi~')
        }
      }
    })
  
    const vm = app.mount('#root')

  </script>
</body>

</html>

这里父组件在调用子组件 Son 的时候, 通过 ref 就可以将子组件包裹在 mySon 这个自定义对象中, 然后在父组件中就可以通过 this.$refs.myson.xxx 的方式来调用子组件的内容啦.

当然这种方式也是不推荐的, 就有点乱和不容易维护, 同时也会带来性能的问题哦.

provice 和 inject

这个 cp 组合主要能解决多层组件传值的问题, 跨过山和大海, 一步到位. 我们先来看如果没有它, 多层组件传值应该是这样的:

<!DOCTYPE html>
<html lang="en">

<head>
  <title>多层组件传值</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    // 多层组件传值
    const app = Vue.createApp({
      data () {
        return { count: 1 }
      },
      template: `
      <div>
        <son :count=count />
      </div>
      `
    })

    // 第一层属性传值
    app.component('son', {
      props: ['count'],
      template: `<grandson :count="count" />`
    })

    // 第二层属性传值
    app.component('grandson', {
      props: ['count'],
      template: `<div>{{count}}</div>`
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>

会发现这种嵌套传值, count 的层层传递, 如果这么一直下去有点搞死人. 因此为了解决这种场景, vue 就设计了一对 cp 的语法组合, 即可 "provide -> inject".

例如我们这里想要将父组件的数据 count 直接一步到位给到 grandson , 而不通过 son 来弄:

<!DOCTYPE html>
<html lang="en">

<head>
  <title>多层组件传值</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>

<body>
  <div id="root"></div>
  <script>
    // 多层组件传值
    const app = Vue.createApp({
      data () {
        return { count: 1 }
      },
      // 通过 provide 将 data () 中的数据传递
      provide () {
        return {
          cj: this.count
        }
      },
      template: `
      <div>
        <son />
      </div>
      `
    })

    // 中间层不用管, 让 provide 跨过山河大海
    app.component('son', {
      template: `<grandson  />`
    })

    // 哪一层需要用则 直接 inject 注入
    app.component('grandson', {
      inject: ['cj'],
      template: `<div>{{cj}}</div>`
    })

    const vm = app.mount('#root')

  </script>
</body>

</html>

其核心就是这里:

data () { return { count: 1 } },
// 通过 provide 将 data () 中的数据传递
provide () {
    return {
    cj: this.count
}

// 余下任何子或多层的组件想要用到这个 cj 数据通过 inject: ['cj'] 即可

需要注意的是这里遗留了一个响应式数据问题, 就如上写法只能 provide 一次, 后面当 data ( ) 数据变化时候, provide 是不会响应式的啦. 如果要解决就后面结合 ref, reacitve 等内容啦, 这里先这样吧.

小结

  • v-once 指令的作用是让该 dom 只能渲染一次哦
  • ref 能够获取 dom 节点和组件的引用, 同时能实现响应式数据渲染
  • provide - inject 的组合能解决多层的数据传递问题, 一步到位, 没有中间商赚差价
posted @ 2022-09-24 13:22  致于数据科学家的小陈  阅读(121)  评论(0编辑  收藏  举报