node.js - 组件导致 'npm run dev' 挂起

标签 node.js vue.js webpack-dev-server

我硬着头皮改用 Vue.js 的模块化方法,使用 vue-cli 和 Webpack。将我的应用程序重组为单个文件组件有一些学习曲线,但我基本上已经做到了。不过,我现在遇到了一个非常令人费解的问题。我有一个相当复杂的组件 ProductDetail,它使用了几个子组件。一旦我添加其中一个,称为 TabPage(通过包含导入行并将其添加到组件属性),编译就会挂起(如果我重新启动“npm run dev”,它同样会在启动时挂起,然后到达以下位置它正在服务页面)。其他 6 个组件根本不会导致此问题。

现在奇怪的是,TabPage这个组件实际上可以是空的,无非是一个模板输出一个空的div,问题仍然存在,所以不可能是这个组件的问题(除此之外在我切换到使用 vue-cli 之前,一切都在应用程序的版本中工作)。只有这个组件,没有其他原因导致问题。

那么是否有一些调试编译过程的方法,以便我可以准确地看到问题发生在哪里?

对于它的值(value),这是 ProductDetail 组件(删除了方法,将其全部缩小到 StackOverflow 满意的大小):

<template>
    <div class="container edit-product">
        <ul class="nav nav-tabs">
            <tab-link page="Product"></tab-link>
            <tab-link page="Pricing"></tab-link>
            <tab-link page="History"></tab-link>
            <tab-link page="Shop"></tab-link>

        </ul>

        <div class="tab-content">

            <tab-page page="Product">
                <form @submit.prevent.stop class="edit-form">
                    <div class="form-fields">
                        <common-header :product="this.product" :error="this.error"></common-header>

                        <div class="row">
                            <cell :cols="8"><text-field name="name" v-model="product.name"/></cell>
                            <cell :cols="1"><text-field name="pack" v-model.number="product.pack" format="numeric"/></cell>
                            <cell :cols="3"><text-field name="size" v-model="product.size"/></cell>
                        </div>

                        <div class="row">
                            <cell :cols="2">

                                <text-field name="code" v-model="product.code" :attrs="{maxlength: 5}">
                                    <button slot="after" type="button" class="btn btn-sm fld-btn" @click="seeExisting">Existing</button>
                                </text-field>

                            </cell>
                            <cell :cols="2">

                                <text-field name="supplierCode" v-model="product.supplierCode">
                                    <button slot="after" type="button" class="btn btn-sm fld-btn" @click="selectSupplier">Select</button>
                                </text-field>

                            </cell>
                            <cell :cols="5">

                                <text-field name="supplierName" v-model="product.supplierName" :attrs="{disabled: true}"/>

                            </cell>

                            <cell :cols="3">

                                <text-field label="Supplier's Product Code" name="supplierProdCode" v-model="product.supplierProdCode"/>

                            </cell>


                        </div>
                        <div class="row">
                            <cell :cols="6">

                                <text-field name="categorization" v-model="categorization" :attrs="{disabled: true}">
                                    <button slot="before" type="button" class="btn btn-sm fld-btn" @click="categorize">Set</button>
                                </text-field>

                            </cell>
                            <cell :cols="6">

                                <text-field name="tradeName" v-model="product.tradeName"/>

                            </cell>
                        </div>
                        <div class="row">
                            <cell :cols="12">
                                <checkbox-field inline="true" name="readyPacked" label="Ready-Packed" v-model="product.readyPacked"></checkbox-field>

                                <checkbox-field inline="true" name="shop" v-model="product.shop"></checkbox-field>

                                <checkbox-field inline="true" name="organic"  v-model="product.organic"></checkbox-field>

                                <checkbox-field inline="true" name="withSugar" v-model="product.withSugar"></checkbox-field>

                                <checkbox-field inline="true" name="stockControlled" label="Stock-controlled" v-model="product.stockControlled"></checkbox-field>

                                <checkbox-field inline="true" name="vegan" v-model="product.vegan"></checkbox-field>

                                <checkbox-field inline="true" name="fairTrade" v-model="product.fairTrade"></checkbox-field>

                                <checkbox-field inline="true" name="glutenFree" label="Gluten-free" v-model="product.glutenFree"></checkbox-field>

                            </cell>
                        </div>
                        <div class="row">
                            <cell :cols="1">
                                <text-field name="aisle" v-model="product.aisle" :attrs="{maxlength: 2}" format="uppercase"/>
                            </cell>
                            <cell :cols="1">
                                <text-field name="bay" v-model="product.bay" :attrs="{maxlength: 2}" format="uppercase"/>
                            </cell>
                            <cell :cols="1">
                                <text-field name="shelf" v-model.number="product.shelf" :attrs="{maxlength: 2}" format="integer"/>
                            </cell>
                            <cell :cols="2">
                                <text-field type="select" name="squashiness" v-model="product.squashiness" :options="['Bags','Bottles','Boxes','Sacks','Delicates','Prepacks','Split Cases']"/>
                            </cell>


                        </div>
                        <div class="row">
                            <cell :cols="2">
                                <text-field name="identifier" v-model="product.identifier" />
                            </cell>
                            <cell :cols="2">
                                <text-field name="grossWeight" after-class="input-group-addon" label="Gross Weight" v-model="product.grossWeight" format="numeric"><span slot="after">kg</span></text-field>
                            </cell>
                            <cell :cols="2">
                                <text-field name="substituteCode" v-model="product.substituteCode" />
                            </cell>
                            <cell :cols="3">
                                <text-field name="outerCaseBarcode" v-model="product.outerCaseBarcode" format="integer"/>
                            </cell>
                        </div>
                        <div class="row">
                            <cell :cols="12">
                                <text-field type="textarea" name="notes" v-model="product.notes" :attrs="{rows: 1}" />
                            </cell>
                        </div>


                    </div>

                    <div class="row">
                        <cell :cols="12">
                            <button type="button" class="btn btn-sm" @click.prevent="returnToList">Cancel</button>
                            <button type="button" class="btn btn-sm"
                                    @click.prevent="saveAndBack">Save, Back To List</button>
                            <button type="button" class="btn btn-sm btn-primary"
                                    @click.prevent="save">Save and Continue</button>
                        </cell>
                    </div>

                </form>

            </tab-page>


            <tab-page page="Pricing">
                <form class="edit-form">
                    <div class="form-fields">
                        <common-header :product="this.product" :error="this.error"></common-header>
                        <div class="row">
                            <cell :cols="8">
                                <div class="row">
                                    <cell :cols="2">
                                        <text-field type="select" name="basedOn" v-model="product.basedOn" :options="['T','B','C']" :styles="{width:'100%'}"/>
                                    </cell>
                                    <cell :cols="2"><text-field name="priceBase" v-model.number="product.priceBase" format="currency"/></cell>
                                    <cell :cols="2"><text-field name="newPriceBase" v-model.number="product.newPriceBase" format="currency"/></cell>
                                    <cell :cols="2">
                                        <text-field type="select" name="vatRating" v-model="product.vatRating" :options="[{ text: 'Zero', value: '0.00'},{text: 'Reduced', value: '5.00' },{text: 'Standard', value: '20.00'}]" @input="calcRRP"/>
                                    </cell>

                                    <cell :cols="2"><text-field name="price" label="Rainbow Price" v-model.number="product.price" format="currency" :attrs="{disabled:true}"/></cell>
                                    <cell :cols="2"><text-field name="unitPrice" label="Per unit/kg" v-model.number="product.unitPrice" format="currency" :attrs="{disabled:true}"/></cell>
                                </div>
                            </cell>

                        </div>
                        <div class="row">
                            <cell :cols="3">
                                <checkbox-field inline="true" name="hasRRP" label="Has RRP" v-model="product.hasRRP" @input="calcRRP"></checkbox-field>
                                <checkbox-field v-if="product.hasRRP" inline="true" name="useNonFoodRRP" label="Non-food RRP" v-model="product.useNonFoodRRP" @input="calcRRP"></checkbox-field>
                            </cell>

                            <cell :cols="8">
                                <div class="row">
                                    <template  v-if="product.hasRRP">
                                        <cell :cols="2"><text-field name="rrp" label="RRP" v-model.number="product.RRP" format="currency" :attrs="{disabled:true}"/></cell>
                                        <cell :cols="2" ><text-field name="manualRRP" label="Over-ride RRP" v-model.number="product.manualRRP" format="currency"/></cell>
                                    </template>
                                    <cell :cols="6"><text-field name="remark" label="Remark" v-model="product.remark" /></cell>
                                    <cell :cols="2"><button type="button" class="btn btn-sm btn-inline"
                                                            @click.prevent="recalc">Recalculate Now</button></cell>
                                </div>
                            </cell>
                        </div>

                    </div>

                    <button-bar></button-bar>

                </form>

            </tab-page>

            <tab-page page="History">
                <form class="edit-form">

                    <div class="form-fields">
                        <common-header :product="this.product" :error="this.error"></common-header>
                        <button-bar></button-bar>
                    </div>
                </form>

            </tab-page>

            <tab-page page="Shop">
                <form class="edit-form">
                    <div class="form-fields">
                        <common-header :product="this.product" :error="this.error"></common-header>
                        <template v-if="this.product.shop==true">
                            <div class="row">
                                <cell :cols="6">
                                    <button type="button" class="btn btn-sm btn-inline" @click.prevent="addShopLine">Add New</button>
                                </cell>
                                <cell :cols="6" :styles="{'text-align':'right'}">
                                    <button type="button" class="btn btn-sm btn-inline" @click.prevent="autoLabel">Auto Label</button>
                                </cell>
                            </div>
                            <div class="row">
                                <div class="col-xs-12">
                                    <table id="shop-lines">
                                        <thead>
                                        <tr>
                                            <th>Unit</th>
                                            <th class="price">Price</th>
                                            <th>Variety</th>
                                            <th class="barcode">Barcode</th>
                                            <th>Label</th>
                                            <th>&nbsp;</th>
                                        </tr>
                                        </thead>
                                        <tbody>
                                        <tr class="shop-line-row" v-for="(shopLine, index) in this.product.shopLines">
                                            <td><text-field table-cell="true" :name="'unit'+index" type="select" v-model="shopLine.unit"
                                                            :options="['2.5kg','1kg','500g','250g','125g','50g','25g','Unit (Low)','Unit (High)', 'Unit (Non-food)']" :styles="{width:'100%'}" /></td>
                                            <td class="price"><text-field table-cell="true" :name="'price'+index" v-model.number="shopLine.price" format="currency"/></td>
                                            <td><text-field table-cell="true"  :name="'variety'+index" v-model="shopLine.variety"/></td>
                                            <td class="barcode"><text-field table-cell="true" :name="'barcode'+index" v-model.number="shopLine.barcode" format="integer"/></td>
                                            <td><text-field table-cell="true" :name="'label'+index" v-model="shopLine.label"/></td>
                                            <td><button @click.prevent="removeShopLine(index)">X</button></td>

                                        </tr>
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        </template>
                        <template v-else>
                            <div class="row">
                                <cell :cols="12">
                                    <p>This product is not sold at the shop</p>
                                </cell>
                            </div>
                        </template>
                        <button-bar></button-bar>
                    </div>
                </form>

            </tab-page>
        </div>
    </div>
</template>
<script>
    import bus from '../../bus'
    import TabPage from '../TabPage'
    import TabLink from '../TabLink'    
    import Cell from '../Cell'
    import TextField from '../TextField'
    import CheckboxField from '../CheckboxField'
    import CommonHeader from './CommonHeader'
    import ButtonBar from './ButtonBar'

    export default {

        data() {
            return {
                action:null,
                product: {},
                productCopy:{},
                page:'Product',
                error:"",
                errorField:null,
                validations:{

                }
            }
        },
         components:{
           TabPage,TabLink,Cell,TextField,CheckboxField,CommonHeader,ButtonBar

        },

        watch: {
            '$route' (to, from) {
                this.setAction();

            }
        },

        created () {
            bus.$on('SelectSupplier',  (supplier) =>{
                this.product.supplierCode=supplier.code;
                this.product.supplierName=supplier.name;
            });
            bus.$on('SelectSubcategory', (subcategory)=> {
                this.product.subcategory=subcategory.name;
                this.product.subcategoryId=subcategory.id;
                this.product.category=subcategory.categoryName;
                this.product.categoryId=subcategory.categoryId;

            });

            bus.$on("set-page", (page)=> {
                this.validatePage();
                if (this.error == "") {
                    var currentPage = this.page;
                    this.page = page;
                    bus.$emit("update-page", this.page);
                }

            });

            bus.$on("button-action", (action)=> {
                this[action]();
            });

        },


        mounted(){
            this.setAction();
            if(this.action=="edit"){
                this.buildTitle("Edit Product");
            } else if(this.action=="dupe") {
                this.buildTitle("Duplicate Product");
            } else if(this.action=="create") {
                this.buildTitle("Create Product");
            }
        },

        beforeRouteLeave (to, from, next) {
               if(_.isEqual(this.product, this.productCopy)){
                next();
            } else {
                var self=this;
                bootbox.confirm({
                    message: "Are you sure want to leave the product editor? You will lose any new or changed data",
                    buttons: {
                        confirm: {
                            label: 'Back To List',
                        },
                        cancel: {
                            label: 'Continue Editing',
                        }
                    },
                    callback: function (result) {
                        if(result){
                            next();
                        } else {
                            next(false);
                        }
                    }
                });
            }
        },
        computed: {
            fullName () {
                return this.product.name + ", " + this.product.pack + this.product["size"];
            },
            displayName () {
                if (this.product.code && this.product.code.length == 5) {
                    return this.product.code + ": " + this.fullName;
                } else {
                    return this.fullName;
                }

            },
            categorization (){
                if (this.product.category && this.product.subcategory) {
                    return this.product.category + ": " + this.product.subcategory;
                } else {
                    return "";
                }
            },
            settings(){
                return this.$store.state.settings;
            }
        },

        methods: {

//BUNCH OF METHODS REMOVED HERE TO BRING TEXT SIZE DOWN BELOW 30,000


        }
    }
</script>

这里是完全精简的 TabPage 组件,它包含在上述组件中会导致编译挂起:

<script>

export default{

    name:"tab-page",

    template:`<div>EMPTY</div>`

}


</script

我已经升级到最新的 Node (v6.9.4 LTS) 但这没有帮助。

最佳答案

谢天谢地,问题并不是什么令人不安的晦涩难懂的问题,而是我没有正确关闭脚本标签这一简单事实。我觉得很傻,但也松了一口气。感谢 Roy J 指出这一点。

关于node.js - 组件导致 'npm run dev' 挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41941254/

相关文章:

node.js - Firebase Cloud Functions - 在 Firestore 中移动数据

vue.js - vue js 中的 $emit(\'remove\' ) 是什么

css - 通过添加父类,作用域 CSS 和 "scope"之间的区别

javascript - 重写 Webpack 代理 URL

mysql - 水线 - 字段总和的位置

javascript - 带 setTimeout 的递归函数

Javascript/Node : Array empty after pushing values in forEach loop

vue.js - 如何使用 jest 使测试覆盖显示 Vue-cli 3 中的所有 vue 文件

vue.js - 在本地 Vue 应用程序中热重载本地 Vue 插件的方法?

Webpack 代理到代理