Vuejs 计算 属性 未正确更新
Vuejs compute property doesn't get updated properly
我是 Vuejs 的新手,我正在关注他们的文档,这非常有帮助。但是,我发现很难理解计算属性实际上是如何触发的。
我正在为我的项目使用 ag-grid,我想将总行数更新到我的自定义页面大小下拉列表中。
以下是我的代码:
<template>
<div id="ag-grid-demo">
<vx-card>
<!-- TABLE ACTION ROW -->
<div class="flex flex-wrap justify-between items-center">
<!-- ITEMS PER PAGE -->
<div class="mb-4 md:mb-0 mr-4 ag-grid-table-actions-left"></div>
<!-- TABLE ACTION COL-2: SEARCH & EXPORT AS CSV -->
<div class="flex flex-wrap items-center justify-between ag-grid-table-actions-right">
<vs-button class="mb-4 md:mb-0" @click="gridApi.exportDataAsCsv()">Export as CSV</vs-button>
</div>
</div>
<ag-grid-vue
ref="agGridTable"
:gridOptions="gridOptions"
class="ag-theme-material w-100 my-4 ag-grid-table"
:columnDefs="columnDefs"
:defaultColDef="defaultColDef"
:rowModelType="rowModelType"
@grid-ready="onGridReady"
rowSelection="multiple"
colResizeDefault="shift"
:animateRows="true"
:pagination="true"
:paginationPageSize="paginationPageSize"
:cacheBlockSize="cacheBlockSize"
:enableRtl="$vs.rtl"
:modules="modules"
></ag-grid-vue>
<div class="flex flex-wrap justify-between items-center">
<!-- CUSTOM PAGESIZE DROP-DWON -->
<div class="mb-4 md:mb-0 mr-4 ag-grid-table-actions-left">
<vs-dropdown vs-trigger-click class="cursor-pointer">
<div class="p-4 border border-solid d-theme-border-grey-light rounded-full d-theme-dark-bg cursor-pointer flex items-center justify-between font-medium">
<span class="mr-2"
>{{ currentPage * paginationPageSize - (paginationPageSize - 1) }} - {{ recordCount - currentPage * paginationPageSize > 0 ? currentPage * paginationPageSize : recordCount }} of {{ recordCount }}</span>
<feather-icon icon="ChevronDownIcon" svgClasses="h-4 w-4" />
</div>
<vs-dropdown-menu>
<vs-dropdown-item @click="gridApi.paginationSetPageSize(10)">
<span>10</span>
</vs-dropdown-item>
<vs-dropdown-item @click="gridApi.paginationSetPageSize(50)">
<span>50</span>
</vs-dropdown-item>
<vs-dropdown-item @click="gridApi.paginationSetPageSize(100)">
<span>100</span>
</vs-dropdown-item>
<vs-dropdown-item @click="gridApi.paginationSetPageSize(150)">
<span>150</span>
</vs-dropdown-item>
</vs-dropdown-menu>
</vs-dropdown>
</div>
<!-- CUSTOM TABLE PAGINATION -->
<div class="flex flex-wrap items-center justify-between ag-grid-table-actions-right">
<vs-pagination :total="totalPages" :max="maxPageNumbers" v-model="currentPage" />
</div>
</div>
</vx-card>
</div>
</template>
<script>
import { AgGridVue } from "ag-grid-vue";
import { ServerSideRowModelModule } from "@ag-grid-enterprise/server-side-row-model";
import { MenuModule } from "@ag-grid-enterprise/menu";
import { ColumnsToolPanelModule } from "@ag-grid-enterprise/column-tool-panel";
import CompanyServices from "../../../_services/company.service";
import "@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss";
export default {
components: {
AgGridVue
},
data() {
return {
gridOptions: {},
maxPageNumbers: 7,
gridApi: null,
defaultColDef: {
sortable: true,
editable: false,
resizable: true,
suppressMenu: false
},
columnDefs: [
{ headerName: "Id", field: "id", filter: false },
{
headerName: "Company Name",
field: "companyName",
filter: true,
checkboxSelection: true,
headerCheckboxSelectionFilteredOnly: true
}
],
rowModelType: "serverSide",
modules: [ServerSideRowModelModule, MenuModule, ColumnsToolPanelModule],
cacheBlockSize: 10,
};
},
computed: {
paginationPageSize() {
if (this.gridApi) return this.gridApi.paginationGetPageSize();
else return 10;
},
totalPages() {
if (this.gridApi) return this.gridApi.paginationGetTotalPages();
else return 0;
},
currentPage: {
get() {
if (this.gridApi) return this.gridApi.paginationGetCurrentPage() + 1;
else return 1;
},
set(val) {
this.gridApi.paginationGoToPage(val - 1);
}
},
recordCount: function() {
if (window.recordCount === undefined) return 0;
else return window.recordCount;
}
},
methods: {
onGridReady: function(params) {
var datasource = new ServerSideDatasource();
params.api.setServerSideDatasource(datasource);
}
},
mounted() {
this.gridApi = this.gridOptions.api;
this.gridColumnApi = this.gridOptions.columnApi;
}
};
window.ServerSideDatasource = function ServerSideDatasource(server) {
return {
getRows: function(params) {
CompanyServices.list({
startRow: params.request.startRow,
endRow: params.request.endRow,
SortColumn: "CompanyName",
SortOrder: "asc"
})
.then(response => {
window.recordCount = response.data.total;
params.successCallback(response.data.rows, response.data.total);
})
.catch(error => {
params.failCallback();
});
}
};
};
</script>
我的问题是计算 属性 'recordCount' 不会随着 'window.recordCount' 的更改而更新。 'recordCount' 始终将值显示为零。
有人可以在这里阐明一下吗?
提前致谢!
这里似乎有几个问题,主要是您在 vue 实例之外设置数据和函数。
首先,你不应该在 window 上设置任何数据,Vue 有很多方法来处理你的数据并使它们对你来说都是反应性的。
首先将 window.ServerSideDataSource 函数移动到 vue 实例中。
在 Vue 中,函数放在 "methods" 下,所以在你的 onGridReady 函数之后,添加一个 ,
然后输入:
serverSideDatasource() {
return {
getRows: functions(params) {..}
}
}
请注意,我将 serverSideDatasource 以小的 s 开头,因为驼峰命名法被广泛认为是命名变量和函数时的最佳做法。
接下来,您的 window.recordCount 应该放入 Vue 的数据中。只需将其添加到 cacheBlockSize 之后并设置如下:
recordCount: 0
现在您所有的数据和方法(函数)都在 Vue 中,您可以使用 "this" 访问它们。
因此,将 "window." 替换为 "this." 所有你使用它的地方。
现在,由于您的 recordCount 从 0 开始,并且仅在您调用 getRows 时更改,因此不需要计算的 recordCount,因此将其删除。
注意:在 data 和 computed 中同时使用 属性 和 computed 调用 recordCount 会发生冲突,因此即使保留它,您也必须重命名 computed。
请告诉我这是否解决了问题,或者它对您有多大帮助:)
我是 Vuejs 的新手,我正在关注他们的文档,这非常有帮助。但是,我发现很难理解计算属性实际上是如何触发的。
我正在为我的项目使用 ag-grid,我想将总行数更新到我的自定义页面大小下拉列表中。
以下是我的代码:
<template>
<div id="ag-grid-demo">
<vx-card>
<!-- TABLE ACTION ROW -->
<div class="flex flex-wrap justify-between items-center">
<!-- ITEMS PER PAGE -->
<div class="mb-4 md:mb-0 mr-4 ag-grid-table-actions-left"></div>
<!-- TABLE ACTION COL-2: SEARCH & EXPORT AS CSV -->
<div class="flex flex-wrap items-center justify-between ag-grid-table-actions-right">
<vs-button class="mb-4 md:mb-0" @click="gridApi.exportDataAsCsv()">Export as CSV</vs-button>
</div>
</div>
<ag-grid-vue
ref="agGridTable"
:gridOptions="gridOptions"
class="ag-theme-material w-100 my-4 ag-grid-table"
:columnDefs="columnDefs"
:defaultColDef="defaultColDef"
:rowModelType="rowModelType"
@grid-ready="onGridReady"
rowSelection="multiple"
colResizeDefault="shift"
:animateRows="true"
:pagination="true"
:paginationPageSize="paginationPageSize"
:cacheBlockSize="cacheBlockSize"
:enableRtl="$vs.rtl"
:modules="modules"
></ag-grid-vue>
<div class="flex flex-wrap justify-between items-center">
<!-- CUSTOM PAGESIZE DROP-DWON -->
<div class="mb-4 md:mb-0 mr-4 ag-grid-table-actions-left">
<vs-dropdown vs-trigger-click class="cursor-pointer">
<div class="p-4 border border-solid d-theme-border-grey-light rounded-full d-theme-dark-bg cursor-pointer flex items-center justify-between font-medium">
<span class="mr-2"
>{{ currentPage * paginationPageSize - (paginationPageSize - 1) }} - {{ recordCount - currentPage * paginationPageSize > 0 ? currentPage * paginationPageSize : recordCount }} of {{ recordCount }}</span>
<feather-icon icon="ChevronDownIcon" svgClasses="h-4 w-4" />
</div>
<vs-dropdown-menu>
<vs-dropdown-item @click="gridApi.paginationSetPageSize(10)">
<span>10</span>
</vs-dropdown-item>
<vs-dropdown-item @click="gridApi.paginationSetPageSize(50)">
<span>50</span>
</vs-dropdown-item>
<vs-dropdown-item @click="gridApi.paginationSetPageSize(100)">
<span>100</span>
</vs-dropdown-item>
<vs-dropdown-item @click="gridApi.paginationSetPageSize(150)">
<span>150</span>
</vs-dropdown-item>
</vs-dropdown-menu>
</vs-dropdown>
</div>
<!-- CUSTOM TABLE PAGINATION -->
<div class="flex flex-wrap items-center justify-between ag-grid-table-actions-right">
<vs-pagination :total="totalPages" :max="maxPageNumbers" v-model="currentPage" />
</div>
</div>
</vx-card>
</div>
</template>
<script>
import { AgGridVue } from "ag-grid-vue";
import { ServerSideRowModelModule } from "@ag-grid-enterprise/server-side-row-model";
import { MenuModule } from "@ag-grid-enterprise/menu";
import { ColumnsToolPanelModule } from "@ag-grid-enterprise/column-tool-panel";
import CompanyServices from "../../../_services/company.service";
import "@/assets/scss/vuexy/extraComponents/agGridStyleOverride.scss";
export default {
components: {
AgGridVue
},
data() {
return {
gridOptions: {},
maxPageNumbers: 7,
gridApi: null,
defaultColDef: {
sortable: true,
editable: false,
resizable: true,
suppressMenu: false
},
columnDefs: [
{ headerName: "Id", field: "id", filter: false },
{
headerName: "Company Name",
field: "companyName",
filter: true,
checkboxSelection: true,
headerCheckboxSelectionFilteredOnly: true
}
],
rowModelType: "serverSide",
modules: [ServerSideRowModelModule, MenuModule, ColumnsToolPanelModule],
cacheBlockSize: 10,
};
},
computed: {
paginationPageSize() {
if (this.gridApi) return this.gridApi.paginationGetPageSize();
else return 10;
},
totalPages() {
if (this.gridApi) return this.gridApi.paginationGetTotalPages();
else return 0;
},
currentPage: {
get() {
if (this.gridApi) return this.gridApi.paginationGetCurrentPage() + 1;
else return 1;
},
set(val) {
this.gridApi.paginationGoToPage(val - 1);
}
},
recordCount: function() {
if (window.recordCount === undefined) return 0;
else return window.recordCount;
}
},
methods: {
onGridReady: function(params) {
var datasource = new ServerSideDatasource();
params.api.setServerSideDatasource(datasource);
}
},
mounted() {
this.gridApi = this.gridOptions.api;
this.gridColumnApi = this.gridOptions.columnApi;
}
};
window.ServerSideDatasource = function ServerSideDatasource(server) {
return {
getRows: function(params) {
CompanyServices.list({
startRow: params.request.startRow,
endRow: params.request.endRow,
SortColumn: "CompanyName",
SortOrder: "asc"
})
.then(response => {
window.recordCount = response.data.total;
params.successCallback(response.data.rows, response.data.total);
})
.catch(error => {
params.failCallback();
});
}
};
};
</script>
我的问题是计算 属性 'recordCount' 不会随着 'window.recordCount' 的更改而更新。 'recordCount' 始终将值显示为零。
有人可以在这里阐明一下吗? 提前致谢!
这里似乎有几个问题,主要是您在 vue 实例之外设置数据和函数。
首先,你不应该在 window 上设置任何数据,Vue 有很多方法来处理你的数据并使它们对你来说都是反应性的。
首先将 window.ServerSideDataSource 函数移动到 vue 实例中。
在 Vue 中,函数放在 "methods" 下,所以在你的 onGridReady 函数之后,添加一个 ,
然后输入:
serverSideDatasource() {
return {
getRows: functions(params) {..}
}
}
请注意,我将 serverSideDatasource 以小的 s 开头,因为驼峰命名法被广泛认为是命名变量和函数时的最佳做法。
接下来,您的 window.recordCount 应该放入 Vue 的数据中。只需将其添加到 cacheBlockSize 之后并设置如下:
recordCount: 0
现在您所有的数据和方法(函数)都在 Vue 中,您可以使用 "this" 访问它们。 因此,将 "window." 替换为 "this." 所有你使用它的地方。
现在,由于您的 recordCount 从 0 开始,并且仅在您调用 getRows 时更改,因此不需要计算的 recordCount,因此将其删除。
注意:在 data 和 computed 中同时使用 属性 和 computed 调用 recordCount 会发生冲突,因此即使保留它,您也必须重命名 computed。
请告诉我这是否解决了问题,或者它对您有多大帮助:)