简体   繁体   中英

Best practice to to set non-reactive const variables in Vue?

The situation

In my Vue app, I have a Vue component which mounts an svg, which I have defined with a few props. These are a combination of reactive and non-reactive data. The reactive data that we need is percData , which therefore sits in the data(){} object. We also have colours , width , height , and scale , which are not reactive and never will be. I don't call these in the <template> block, and I don't plan for them to change. These are currently declared with const , and are not within the export defautl{} block scope.

The question(s)

  • Where is the best place to be for these const declarations?
  • What scope are these const-declared variables currently in?
  • More generally, how does scope work for the <script> tag in Vue in a multi-component app? Is each script/component a separate scope from the global one? And where is the global scope?

My possible understanding

As per this thread and this thread , I think the best place for my const would be in a separate file, from which I would then import them in my mySvgComponent component. Is this the correct approach?

My code

<template>
    <div></div>
</template>

<script>
    import { mySvgComponent} from '../mySvgComponent'
    import { select } from 'd3'

    const [colour1, colour2, colour3, colour4] = ['#000000', '#111111', '#222222', '#3333'];
    
    const width = 135
    const height = 135
    const scale = .75

    export default {
        name:'mySvgComponent', 
        data(){ 
            return{
                percData: null
            }
        },
        props: {
            summary: Object
        },
        methods: {
            percSetup(summary) {
                return this.percData = [
                    { colour: colour1, perc: +summary.colour1Percentage.toFixed(2)},
                    { colour: colour2, perc: +summary.colour2Percentage.toFixed(2)},
                    { colour: colour3, perc: +summary.colour3Percentage.toFixed(2)},
                    { colour: colour4, perc: +summary.colour4Percentage.toFixed(2)}
                ]
            }
        },
        async mounted() {
            this.percSetup(this.$props.summary)
          
            const svg = 
                select('div')
                .append('svg')
                .call(mySvgComponent(this.percData)
                .width(width)
                .height(height)
                .scale(scale))
        }
    }
</script>
<style></style>

Related threads and why I don't think they answer my question:

  1. How to set a component non-reactive data in Vue 2? , How to make a template variable non-reactive in Vue , How could I use const in vue template? . I don't call my const variables in my <template> tag, and I don't need it to be responsive.
  2. What is the best way to create a constant, that can be accessible from entire application in VueJs? . Maybe I don't understand this fully. Why would I need to run a method() to return my const variables?

In Vue.js, you can set non-reactive (ie, constant) variables by declaring them in the data object as a function that returns an object, rather than declaring them directly as properties of the data object. This ensures that the variables are only set once during the initialisation of the component and cannot be modified later. Here's an example:

data: function () {
  return {
    nonReactiveConst: 'This is a non-reactive const variable'
  }
}

Another way to create a non-reactive variable in Vue is to use the Vue.observable() function to create an observable object, and then assign the non-reactive variable as a property of that object.

  const state = Vue.observable({
      nonReactiveConst: 'This is a non-reactive const variable'
    });

You can then access the non-reactive variable inside the component's template using state.nonReactiveConst.

It's important to note that using this method, you can still mutate properties of the object, but you can't reassign the whole object.

Vue SFC is syntax sugar, it's necessary to understand what code it's compiled to in order to use it effectively.

The result of SFC script syntax is ES module with roughly the same content as the body of <script> block, with name and render options being added by the compiler. Then general modular JavaScript practices are applicable. The constants can remain in current module if they don't take much lines and aren't reused in other modules, and can be moved to a separate module otherwise. In case the constants are supposed to be used in a template, they can be returned from data or setup function.

The result of SFC script setup syntax is ES module with the whole block being moved to generated setup function, with the exception of imports. In this case it's inefficient to declare constants in this block because they will be created on each component instantiation, this may be a reason to move them to a separate module, although this can be considered preliminary optimization.

Considering the above, the scope of Vue SFC modules works exactly like it's expected from ESM because this is what they are compiled to.

Vue composition API provides markRaw function to additionally prevent constant objects from being made reactive when they are used inside reactive ones like data , in case this is unwanted. The same is done for options API with Object.freeze in linked question .

TL;DR: the code in the question is ok, it's correct to use the constants like that in this case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM