Vue.js Vue-循环和事件处理程序的最佳实践

Vue.js Vue-循环和事件处理程序的最佳实践,vue.js,vuejs2,nuxt.js,Vue.js,Vuejs2,Nuxt.js,我很好奇在循环中包含方法是否比使用v-if更好。假设以下代码有效(它们不完整且不可用) EX:Method {{d} 导出默认值{ 数据(){ 数据:[ ..... ] }, 方法:{ 插入提示(e){ body.insertBefore(提示) } } } DOM将通过只用于显示的insertPrompt()函数进行更新 EX:V-IF //母公司 从“./child”导入子项 导出默认值{ 组成部分:{ 小孩 }, 数据(){ 数据:[ ..... ] }, } //孩子 {{d}

我很好奇在循环中包含
方法是否比使用
v-if
更好。假设以下代码有效(它们不完整且不可用)

EX:Method


{{d}
导出默认值{
数据(){
数据:[
.....
]
},
方法:{
插入提示(e){
body.insertBefore(提示)
}
}
}
DOM将通过只用于显示的
insertPrompt()
函数进行更新

EX:V-IF

//母公司


从“./child”导入子项
导出默认值{
组成部分:{
小孩
},
数据(){
数据:[
.....
]
},
}
//孩子


{{d}
从“./child”导入子项
导出默认值{
组成部分:{
小孩
},
数据(){
返回{
显示:假
}
},
道具:{
数据:{
.....
}
},
}
提示符
是一个基本模板,使用循环数据单击中的数据呈现

这两种方法可以实现相同的最终结果。我最初的想法是在一个循环中有额外的条件会对性能产生负面影响

非常感谢您的指导

我最初的想法是,在一个循环中有额外的条件会对性能产生负面影响吗

我想你可能会被《风格指南》中的以下内容所迷惑:

切勿在与
v-for
相同的元件上使用
v-if

只有在同一元素上使用
v-if
v-for
时,这才是样式问题。例如:

<div v-for="user in users" v-if="user.isActive">
<div v-for="user in users">
    <div v-if="user.isActive">
使用
v-if
不会比一种方法对性能产生更负面的影响。我假设你也必须在你的方法中做一些条件检查。请记住,即使调用方法也会对性能产生一些(非常小的)影响

一旦使用了Vue,我认为最好不要将其与JavaScript DOM方法(如
insertBefore
)混用。Vue维护一个虚拟DOM,它可以帮助它确定在组件数据更改时如何最好地更新DOM。通过使用JavaScript DOM方法,您将不再利用Vue的虚拟DOM


通过坚持Vue语法,您的代码也变得更容易理解,而且可能更易于维护。其他开发人员可能会在以后阅读您的代码或为您的代码做出贡献。

解决此问题的解决方案有很多,但我们还是坚持3个。选项2和3是更好的实践,但选项1可行,Vue是为这种方法设计的,即使核心开发人员可能会皱眉,但会坚持YRU舒适度

选项1:DOM操作

单击、异步、道具中的数据为v-if或v-show设置条件,并显示组件。注意:v-if删除了DOM元素,其中v-show隐藏了可见性,但元素仍在流中。如果删除元素并添加一个全新的init,这在反应性方面有时对您有利,但在实践中尽量不要操纵DOM,因为它总是比循环、过滤器、映射等更昂贵

选项3:Vue和网页包异步和动态组件。

当涉及到更大的应用程序时,或者如果您使用Vuex和Vue Route,其中有大量动态组件,那么有很多方法,但我会坚持使用其中一种。与选项2类似,我们使用的是component元素,但我们使用WebPack递归地查找带有关键字“module”的所有Vue文件。然后,我们动态/异步加载它们——这意味着它们只会在需要时加载,您可以在浏览器的网络控制台中看到这一点。这意味着我可以动态构建组件(工厂模式)并根据需要渲染它们。例如,如果用户添加项目,并且您必须为创建的项目动态生成和配置视图(例如,使用vue路由器)您为其传递了新项目的ID,则您需要动态加载现有组件或生成并加载工厂生成的组件

注意:如果我有许多组件,并且我不确定用户是否需要它们,我将在组件元素上使用v-if。我不想在大量组件集合上维护状态,因为我最终会占用内存,而大量的观察者/手表/动画很可能会导致CPU问题


<template >
    <div>
        <component :is="module" v-if="module"/>
    </div>
</template>

<script>
    const requireContext = require.context('./', true, /\.module\.vue$/);
    const modules = requireContext.keys()
        .map(file =>
            [file.replace(/(.*\/(.+?)\/)|(\.module.vue$)/g, ''), requireContext(file)]
        )
        .reduce((components, [name, component]) => {
            // console.error("components", components)
            components[name] = component.default || component
            return components
        }, {});

    export default {
        data() {
            return {
                module: [],
            }
        },
        props: {
            slug: {
                type: String,
                required: true
            }
        },
        computed: {
            getData() {
                return this.data;
            },
        },
        methods: {
            setModule () {
                let module = this.slug;

                if (!module || !modules[module]) {
                    module = this.defaultLayout
                }

                this.module = modules[module]
            }
        },
        mounted() {
            this.nextTick(this.setModule())
        }
    }
</script>



const requireContext=require.context('./',true,/\.module\.vue$/);
const modules=requireContext.keys()
.map(文件=>
[file.replace(/(.\/(.+?)\/)|(\.module.vue$)/g',requireContext(文件)]
)
.reduce((组件,[名称,组件])=>{
//控制台错误(“组件”,组件)
components[名称]=component.default | | component
返回组件
}, {});
导出默认值{
数据(){
返回{
模块:[],
}
},
道具:{
鼻涕虫:{
类型:字符串,
必填项:true
}
},
计算:{
getData(){
返回此.data;
},
},
方法:{
setModule(){
让module=this.slug;
如果(!模块| |!模块[模块]){
module=this.defaultLayout
}
this.module=模块[模块]
}
},
安装的(){
this.nextTick(this.setModule())
}
}

除非在循环中渲染大量的项目(大多数情况下不渲染),否则根本不需要担心性能。
<template >
    <div>
        <component :is="comp"/>
    </div>
</template>

<script>
    import ChildOne from "./ChildOne";
    import ChildTwo from "./ChildTwo";

    export default {
        components: {
            ChildOne,
            ChildTwo
        },
        props: ['slug'],
        data() {
            return {
                comp: 'ChildOne',
            }
        },
        methods: {
            setComponent () {
                // assume prop slug passed from component or router is one of the components e.g. 'ChildOne'
                this.comp = this.slug;
            }
        },
        mounted() {
            this.nextTick(this.setModule())
        }
    }
</script>


<template >
    <div>
        <component :is="module" v-if="module"/>
    </div>
</template>

<script>
    const requireContext = require.context('./', true, /\.module\.vue$/);
    const modules = requireContext.keys()
        .map(file =>
            [file.replace(/(.*\/(.+?)\/)|(\.module.vue$)/g, ''), requireContext(file)]
        )
        .reduce((components, [name, component]) => {
            // console.error("components", components)
            components[name] = component.default || component
            return components
        }, {});

    export default {
        data() {
            return {
                module: [],
            }
        },
        props: {
            slug: {
                type: String,
                required: true
            }
        },
        computed: {
            getData() {
                return this.data;
            },
        },
        methods: {
            setModule () {
                let module = this.slug;

                if (!module || !modules[module]) {
                    module = this.defaultLayout
                }

                this.module = modules[module]
            }
        },
        mounted() {
            this.nextTick(this.setModule())
        }
    }
</script>