vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue3 ref shallowRef区别

从Echarts报错中学习Vue3 ref和shallowRef区别及其组件二次封装demo

作者:水冗水孚

这篇文章主要介绍了从Echarts报错中学习Vue3 ref和shallowRef区别及其组件二次封装demo,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

报错场景

Uncaught TypeError: Cannot read properties of undefined (reading 'type') at LineView2.render (LineView.js:567:36) echarts.js:976

上述是报错信息

报错截图

报错原因分析

解决方案

如下:

思考,难道所有的变量,都要,都得,都必须通过ref或者reactive定义成响应式的吗?

原来的写法用ref存储:不建议

import * as echarts from "echarts";
const eChaDom = ref(null); // 用于初始化Echarts画布需要的dom元素
const chart = ref(null) // 用于存储Echarts
chart.value = echarts.init(eChaDom.value) // 初始化实例

解决方案一:直接使用普通变量来存储Echarts实例

import * as echarts from "echarts";
let eChaDom = document.querySelector('.eChaDom'); // 用于初始化Echarts画布需要的dom元素
let chart = null // 用于存储Echarts
chart = echarts.init(eChaDom) // 初始化实例

解决方案二:使用浅层响应式shallowRef进行存储Echarts实例

import * as echarts from "echarts";
const eChaDom = shallowRef(null); // 用于初始化Echarts画布需要的dom元素
const chart = shallowRef(null) // 用于存储Echarts
chart.value = echarts.init(eChaDom.value) // 初始化实例

解决方案三:依旧用ref但是搭配markRaw强制返回自身,不让代理克隆一份

import { ref, markRaw, shallowRef } from "vue";
import * as echarts from "echarts";
const eChaDom = ref(null); // 用于初始化Echarts画布需要的dom元素
const chart = ref(null) // 用于存储Echarts
chart.value = markRaw(echarts.init(eChaDom.value)) // 初始化实例

思考ref和shallowRef应用场景————性能优化

实际上,这也是性能优化提升的一种方式

因为ref是把一个变量递归深层次加工成响应式【耗时不少】,而shallowRef操作加工【耗时少】

我们看官方的shallowRef和markRaw这两张图,就能够理解明白了:

图:

图:

官方地址在这

小结

当然,github就这个问题,也有对应的issue。地址在这里

一句话总结,某些大一些的、不需要更改的实例化的数据对象,就不需使用ref定义成深层响应式啦(直接用普通变量存储也无妨)。若是依旧想定义成响应式的,那就使用shallowRef即可

嗯,这样记,通俗易懂

封装的Echarts组件,可复现对应报错bug

组件二次封装Echarts代码

<template>
    <div ref="eChaDom" :style="{ height: h }" />
</template>
<script setup>
import { watch, onMounted, onBeforeUnmount, ref, shallowRef } from "vue";
import * as echarts from "echarts";
import debounce from 'lodash/debounce'
const props = defineProps({
    h: {
        type: String,
        default: '360px'
    },
    options: {
        type: Object,
        default: () => ({})
    },
    theme: {
        type: String,
        default: 'dark'
    }
})
// const eChaDom = ref(null); // 这样resize有报错
// const chart = ref(null)
const eChaDom = shallowRef(null); // 这样resize就没报错了
const chart = shallowRef(null)
const init = () => {
    chart.value = echarts.init(eChaDom.value, props.theme)
    chart.value.setOption(props.options);
    window.addEventListener('resize', debounce(resizeFn, 360))
}
const resizeFn = () => {
    chart.value.resize()
}
onMounted(() => {
    init()
})
watch(
    () => props.options,
    (newOptions) => {
        chart.value.setOption(newOptions);
    },
    { deep: true }
)
onBeforeUnmount(() => {
    window.removeEventListener('resize', resizeFn)
})
</script>

使用组件

<template>
    <div class="tenBox">
        <eCha :options="options" h="600px" />
    </div>
</template>
<script setup>
import eCha from "@/components/eCha/index.vue";
const options = {
    xAxis: {
        type: 'category',
        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    },
    yAxis: {
        type: 'value'
    },
    series: [
        {
            data: [820, 932, 901, 934, 1290, 1330, 1320],
            type: 'line',
            smooth: true
        }
    ]
}

以上就是从Echarts报错中学习Vue3 ref和shallowRef区别及其组件二次封装demo的详细内容,更多关于Vue3 ref shallowRef区别的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文