首页 > 解决方案 > Vue事件表现不佳

问题描述

我的 vue 应用程序有很大的性能问题。

我有大约 50 行的表,它有一个 slot-scope="scope" 属性当我尝试在选定的行上进行一些事件时,例如打开元素 UI 选择元素整个页面冻结了很长时间。

我检查了 chrome webdev 性能选项卡,看起来网站正在执行很多函数调用:

浏览器性能测试

如果我的表中只有几行,它的工作速度很快。

这是我的组件代码:

<template>
  <div>
    <el-card>
      <div slot="header">
        Quotes
        <el-button
          type="primary"
          size="small"
          @click="exportQuotes"
          icon="el-icon-download"
          class="pull-right card-header-item">
          Export
        </el-button>
        <el-button
          type="success"
          size="small"
          @click="$router.push({name: 'quote-create'})"
          icon="el-icon-plus"
          class="pull-right card-header-item">
          Create new quote
        </el-button>
      </div>
      <el-table
        :data="quotes"
        size="small"
        style="width: 100%"
        :row-class-name="tableRowHighlight"
        v-loading="loading">
        <el-table-column prop="ref_number" label="Ref #" width="107">
          <template slot-scope="scope">
            <el-popover
              placement="bottom"
              title="Edit Ref #:"
              width="150"
              v-model="scope.row.ref_number_edit"
              @show="tmp_value = scope.row.ref_number">
              <el-form
                @submit.prevent="updateRefNumber(scope.row, tmp_value)"
                inline
                size="mini">
                <el-input
                  type="text"
                  v-model="tmp_value"
                  size="mini"
                  class="pull-left"
                  style="width: 100px;margin-right:5px">
                </el-input>
                <el-button
                  type="primary"
                  native-type="submit"
                  icon="el-icon-check"
                  size="mini"
                  @click="updateRefNumber(scope.row, tmp_value)">
                </el-button>
              </el-form>
              <span slot="reference" @click="scope.row.ref_number_edit = true">{{ scope.row.ref_number }}</span>
            </el-popover>
          </template>
        </el-table-column>
        <el-table-column prop="created_date" label="Date"></el-table-column>
        <el-table-column prop="work_type" label="Work type"></el-table-column>
        <el-table-column prop="address_state" label="State" width="40"></el-table-column>
        <el-table-column prop="customer_name" label="Customer"></el-table-column>
        <el-table-column prop="address_name" label="Site"></el-table-column>
        <el-table-column prop="po" label="PO #"></el-table-column>
        <el-table-column prop="description" label="Description"></el-table-column>
        <el-table-column prop="scope" label="Scope"></el-table-column>
        <el-table-column prop="av" label="A/V" align="center" width="40"></el-table-column>
        <el-table-column prop="si" label="S/I" align="center"></el-table-column>
        <el-table-column prop="service_provider_name" label="Service Provider"></el-table-column>
        <el-table-column prop="status" label="Status">
          <template slot-scope="scope">
            <el-popover
              placement="bottom"
              title="Edit status:"
              width="230"
              v-model="scope.row.status_edit"
              @show="tmp_value = scope.row.status">
              <el-form
                @submit.prevent="updateStatus(scope.row, tmp_value)"
                inline
                size="mini">
                <el-select
                  v-model="tmp_value"
                  size="mini"
                  style="width: 180px;margin-right:5px">
                  <el-option
                    v-for="(label, key) in statuses"
                    :key="key"
                    :label="label"
                    :value="key">
                  </el-option>
                </el-select>
                <el-button
                  type="primary"
                  native-type="submit"
                  icon="el-icon-check"
                  size="mini"
                  @click="updateStatus(scope.row, tmp_value)">
                </el-button>
              </el-form>
              <span slot="reference" @click="scope.row.status_edit = true">{{ scope.row.status }}</span>
            </el-popover>
          </template>
        </el-table-column>
        <el-table-column prop="days_to_quote" label="Days to Quote" align="center">
          <template slot-scope="scope">
            <el-popover
              placement="bottom"
              title="Edit days to quote:"
              width="150"
              v-model="scope.row.days_to_quote_edit"
              @show="tmp_value = scope.row.days_to_quote">
              <el-form
                @submit.prevent="updateDaysToQuote(scope.row, tmp_value)"
                inline
                size="mini">
                <el-input-number
                  type="text"
                  v-model="tmp_value"
                  size="mini"
                  class="pull-left"
                  style="width: 100px;margin-right:5px">
                </el-input-number>
                <el-button
                  type="primary"
                  native-type="submit"
                  icon="el-icon-check"
                  size="mini"
                  @click="updateDaysToQuote(scope.row, tmp_value)">
                </el-button>
              </el-form>
              <span slot="reference" @click="scope.row.days_to_quote_edit = true">{{ scope.row.days_to_quote }}</span>
            </el-popover>
          </template>
        </el-table-column>
        <el-table-column prop="api_cost" label="API Cost" align="right">
          <template slot-scope="scope">
            <el-popover
              placement="bottom"
              title="Edit API cost:"
              width="130"
              v-model="scope.row.api_cost_edit"
              @show="tmp_value = scope.row.api_cost">
              <el-form
                @submit.prevent="updateApiCost(scope.row, tmp_value)"
                inline
                size="mini">
                <el-input-number
                  type="text"
                  v-model="tmp_value"
                  :precision="2"
                  size="mini"
                  :controls="false"
                  class="pull-left"
                  style="width: 105px">
                </el-input-number>
                <el-button
                  type="primary"
                  native-type="submit"
                  icon="el-icon-check"
                  size="mini"
                  @click="updateApiCost(scope.row, tmp_value)">
                </el-button>
              </el-form>
              <span slot="reference" @click="scope.row.api_cost_edit = true">{{ scope.row.api_cost }}</span>
            </el-popover>
          </template>
        </el-table-column>
        <el-table-column prop="customer_cost" label="Customer Cost" align="right">
          <template slot-scope="scope">{{ scope.row.customer_cost }}</template>
        </el-table-column>
        <el-table-column prop="gpm" label="GPM" align="right">
          <template slot-scope="scope">{{ scope.row.gpm }}%</template>
        </el-table-column>
        <el-table-column prop="total_approved" label="Total Approved" align="right">
          <template slot-scope="scope">{{ scope.row.total_approved }}</template>
        </el-table-column>
        <el-table-column prop="total_approved_api" label="Total Approved API" align="right">
          <template slot-scope="scope">{{ scope.row.total_approved_api }}</template>
        </el-table-column>
        <el-table-column prop="total_rejected" label="Total Rejected" align="right">
          <template slot-scope="scope">{{ scope.row.total_rejected }}</template>
        </el-table-column>
        <el-table-column prop="margin_approved" label="Margin on Approved" align="right">
          <template slot-scope="scope">{{ scope.row.margin_approved }}</template>
        </el-table-column>
        <el-table-column prop="total_pending" label="Total Pending" align="right">
          <template slot-scope="scope">{{ scope.row.total_pending }}</template>
        </el-table-column>
        <el-table-column label="Actions" align="center" width="100" fixed="right">
          <template slot-scope="scope">
            <el-button
              type="primary"
              size="mini"
              icon="el-icon-edit"
              @click="editQuote(scope.row.id)">
            </el-button>
            <el-button
              type="danger"
              size="mini"
              icon="el-icon-delete"
              @click.prevent.stop="deleteQuote(scope.row.id, $event)">
            </el-button>
          </template>
        </el-table-column>
        <template slot="empty">
          <p>
            You don't have any saved quotes yet.<br>
          </p>
        </template>
      </el-table>

      <div class="pagination">
        <el-pagination
          background
          small
          layout="prev, pager, next"
          @current-change="changePage"
          :page-size="per_page"
          :current-page="current_page"
          :total="total">
        </el-pagination>
      </div>
    </el-card>
  </div>
</template>

<script>
export default {
  data () {
    return {
      tmp_value: '',
      loading: false,
      per_page: null,
      current_page: null,
      total: null,
      quotes: [],
      statuses: []
    }
  },
  methods: {
    editQuote (quoteId) {
      this.$router.push({
        name: 'quote-edit',
        params: { quoteId: quoteId }
      })
    },
    viewQuote (quoteId) {
      this.$router.push({
        name: 'quote-view',
        params: { quoteId: quoteId }
      })
    },
    tableRowHighlight ({row, rowIndex}) {
      if (row.status == 'APPROVED') {
        return 'bg-success'
      } else if (row.status == 'REJECTED') {
        return 'bg-danger'
      } else {
        return ''
      }
    },
    fetchQuotes () {
      this.loading = true
      this.$http
        .get('/quotes', {
          params: { page: this.current_page }
        })
        .then(res => {
          this.loading = false
          this.statuses = res.data.statuses
          this.quotes = res.data.quotes.data
          console.log(this.quotes)
          this.current_page = res.data.quotes.current_page
          this.per_page = res.data.quotes.per_page
          this.total = res.data.quotes.total
        })
        .catch(err => {
          this.loading = false
          console.log(err)
        })
    },
    changePage (page) {
      this.current_page = page
      this.fetchQuotes()
    },
    exportQuotes () {
      window.open('/quotes/export', '_blank');
    },
    updateApiCost (quote, value) {
      this.$http
        .post('/quotes/' + quote.id + '/inline', {api_cost: value})
        .then(res => {
          quote.api_cost_edit = false
          this.fetchQuotes()
          this.$message({
            message: 'API cost has been successfuly updated.',
            type: 'success'
          })
        })
        .catch(err => {
          this.showErrorAlert(err.response.data.message)
        })
    },
    updateRefNumber (quote, value) {
      this.$http
        .post('/quotes/' + quote.id + '/inline', {ref_number: value})
        .then(res => {
          quote.ref_number_edit = false
          this.fetchQuotes()
          this.$message({
            message: 'Reference # has been successfuly updated.',
            type: 'success'
          })
        })
        .catch(err => {
          this.showErrorAlert(err.response.data.message)
        })
    },
    updateStatus (quote, value) {
      this.$http
        .post('/quotes/' + quote.id + '/inline', {status: value})
        .then(res => {
          quote.status_edit = false
          this.fetchQuotes()
          this.$message({
            message: 'Status has been successfuly updated.',
            type: 'success'
          })
        })
        .catch(err => {
          this.showErrorAlert(err.response.data.message)
        })
    },
    updateDaysToQuote (quote, value) {
      this.$http
        .post('/quotes/' + quote.id + '/inline', {days_to_quote: value})
        .then(res => {
          quote.days_to_quote_edit = false
          this.fetchQuotes()
          this.$message({
            message: 'Days to quote have been successfuly updated.',
            type: 'success'
          })
        })
        .catch(err => {
          this.showErrorAlert(err.response.data.message)
        })
    },
    deleteQuote (quoteId) {
      this.$confirm('Are you sure you want to delete this quote?', 'Warning', {
          confirmButtonText: 'OK',
          cancelButtonText: 'Cancel',
          type: 'warning'
        })
        .then(() => {
          this.$http
            .delete('/quotes/' + quoteId)
            .then(res => {
              this.fetchQuotes()
              this.$message({
                type: 'success',
                message: res.data.message
              })
            })
            .catch(err => {
              this.showErrorAlert(err.response.data.message)
            })
        })
        .catch(err => {
          console.log(err);
        })
    },
    showErrorAlert (message) {
      message = '<b>' + message + '</b><br>Please contact with administrator to fix this issue.'

      this.$alert(message, 'Error', {
        dangerouslyUseHTMLString: true,
        confirmButtonText: 'OK',
        type: 'error',
        center: true
      })
    }
  },
  mounted () {
    this.fetchQuotes()
  }
}
</script>

<style lang="scss" scoped>
.pagination {
  float: right;
  margin: 20px 0
}
</style>

希望你们能帮我找到解决办法。谢谢!

标签: javascriptperformancevue.js

解决方案


推荐阅读