【问题标题】:Vue: Can't set the computed propertyVue:无法设置计算属性
【发布时间】:2020-02-11 12:52:33
【问题描述】:

我需要一些关于 vue 中计算属性和 ajax 的帮助。

"filterFactories" 是工厂列表。 计算属性“filterFactories”创建了这个工厂列表。

现在,我想要一个新功能: 我有一个用于获取一些新工厂的 ajax 请求的按钮。 我想在 ajax 请求之后设置计算属性“filterFactories”。 不幸的是,什么也没有发生。 没什么区别: 1. this.filterFactories = 响应; 或者 2. window.filterFactories = 响应; 在这两种情况下 - 什么都没发生

ajax请求成功后是否可以更新“filterFactories”?

我添加了一个更大的代码片段

<div id="app">

	<div id="filter">
		<div class="row">
			<div class="col-md-12">
				<div class="input-group">
				  <span class="input-group-addon">Factory</span>
				  <input type="text" class="form-control" placeholder="Name" aria-describedby="basic-addon1" v-model="searchFactory">
				   <div class="input-group-btn">
					  <button class="btn btn-default" type="submit" v-on:click="clearSearchFactory">
						<i class="fa fa-times"></i>
					  </button>
					</div>
				</div>
			</div>
		</div>
		<div class="row">
			<div class="col-xs-12 col-md-6">
				<Multiselect 
					v-model="selectedCapabilities" 
					:options="allCapabilities"
					label="name"
					placeholder= "Select capabilities"
					track-by="id"
					:multiple="true"
				></Multiselect>
			</div>
			<div class="col-xs-12 col-md-6">
				<Multiselect 
					v-model="selectedCountries" 
					:options="allCountries"
					label="name"
					placeholder= "Select countries"
					track-by="code"
					:multiple="true"
				></Multiselect>
			</div>
		</div>
	</div>
	
	<!--Modal-->
	<div id="myModal" class="modal fade" role="dialog">
	  <div class="modal-dialog">
		<div class="modal-content">
		  <div class="modal-header">
			<button type="button" class="close" data-dismiss="modal">&times;</button>
			<h4 class="modal-title">{{this.clickedCapability.name}}</h4>
		  </div>
		    <div class="modal-body">
				<!--......-->
			</div>
		  <div class="modal-footer">
			<button type="button" class="btn btn-success" data-dismiss="modal"  @click="filterProperties">OK</button>
			<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
		  </div>
		</div>
	  </div>
	</div>
	
	
	<div class="row" style="height: 35px; margin: 10px">
		<button type="button" class="btn btn-outline-dark" v-for="cap in selectedCapabilities" @click="modalCapClicked(cap)" data-toggle="modal" data-target="#myModal"> {{ cap.name }} <i class="fa fa-cogs"></i></button>
	</div>
	
	<!--Factories-->
	<div class="row">
		<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2" id="myCard-wrapper" v-for="factory in this.filterFactories">
			<!--a list of factories-->
		</div>
	</div>

	
	
</div>

<script>


  window.app = new Vue({
    el: '#app',
	components: {
		Multiselect: window.VueMultiselect.default
	  },
     data() {
	  return {
		//Capabilities
		allCapabilities: [],						// alle Capabilities aus der Konfiguration die über das Json übermittelt wurden
		selectedCapabilities: [], 					// selektierte Capabilities
		clickedCapability: '',						// im Modalfenster geöffnete Capability

		//Countries
		selectedCountries: [], 						// selektierte Countries 
		allCountries: [],							// alle Countries aus der Json
		
		//Factories				
		searchFactory: '',							// Freitext Suchfeld für Fabriken
		factories: []								// angezeigte Fabriken
	  }
	}, 
	computed:{
		/* Filtert die Fabriken anhand der Kriterien: Suche-Input, Capabilities, Countries */
		filterFactories: function(){
			var filteredFactories = [];
			
			var allFilter = [];
			allFilter.push(this.filterFactoriesBySearchInput());
			allFilter.push(this.filterFactoriesByCaps());
			allFilter.push(this.filterFactoriesByCountries());
			
			filteredFactories = allFilter.shift().filter(function(v) {
				return allFilter.every(function(a) {
					return a.indexOf(v) !== -1;
				});
			});
			
			return filteredFactories;
		}
	},
	methods: {
		/* Filtert anhand der Suchfeld-Eingabe */
		filterFactoriesBySearchInput(){
			/*filter an return a new list of factories*/
		},
		/* Filtert anhand der Capabilities */
		filterFactoriesByCaps(){
			/*filter an return a new list of factories*/
		},
		/* Filtert anhand der Countries */
		filterFactoriesByCountries(){	
			/*filter an return a new list of factories*/
		},
		/* Setzt die aktuell im Modal-Fenster geöffnete Capability */
		modalCapClicked(cap){
			this.clickedCapability = cap;				
		}
		filterProperties(){	

			axios.post('.....................................')
			.then(function (response) {
				
				this.factories = response.data.factoriesJson;
				
			})
			.catch(function (error) {
				console.log(error);
			});
		},
		clearSearchFactory(){
			this.searchFactory = [];
		}
	},
	beforeMount(){
		axios.get('.........').then(response => {
				this.factories = response.data.elementsJson.factories;
				this.allCapabilities = response.data.elementsJson.config.capabilities;
		});
		axios.get('.......').then(response => {
				this.allCountries = response.data;
		});
	}
  })
  

</script>

【问题讨论】:

  • 对计算属性使用设置器的方式没有意义。你想在这里做什么?您的代码是如此之少,以至于我无法真正理解您对计算属性的使用。听起来它应该只是在组件数据中。
  • 你是对的,getter 和 setter 没有意义。我更新了我的代码示例。我希望它更清楚。计算属性“filterFactories”调用其他函数来过滤我的工厂集。现在我想用调用和ajax请求的新按钮更新/重置“filterFactories”。
  • 如果是这种情况,您应该将数据存储在this.factories 中,然后每次this.factories 更新时让filterFactories 过滤您的工厂。这是由 Vue 自动完成的,因此您不必担心(换句话说,this.filterFactories 将响应 this.factories 中的更改并在每次更新后者时执行过滤)。
  • 其中一个问题是您的axios.post 处理程序没有将其上下文绑定到Vue 实例(默认情况下为window),因此this.filterFactories 设置不正确window.filterFactories .一个简单的解决方案是使用箭头函数来保留正确的上下文:axios.post(...).then(response =&gt; this.filterFactories = response)
  • 感谢您的帮助。我尝试了您的方法“window.filterFactories”,但没有任何区别。

标签: javascript vue.js vuejs2 computed-properties


【解决方案1】:

Vue 对计算属性使用了一些魔法:它扫描函数代码并自动为它在代码中找到的属性创建观察者。这适用于简单的情况,但在循环、映射、reduce 等方面对我来说失败了很多次。

我根据需要使用了多种解决方法,最容易理解的是:创建一个您在计算属性中引用的人工属性,然后根据需要进行更新:

new Vue({
    data: {
        updated: 0,
    },
    computed: {
        myComputed(): {
            // ...
            // just a reference to the prop
            this.updated;
        },
    },
    methods: {
        myAjax(): {
            // ...
            // modifying the prop will trigger update of myComputed
            this.updated++;
        },
    },
});

当然,您应该使用更适合您的用例的名称,但是我有一些实例,我只是将此属性称为“updateDummy”;)

【讨论】:

  • '它会扫描函数代码,并会自动为它在代码中找到的属性创建观察者'。这不太对,没有扫描或代码分析。该函数只是运行,Vue 会跟踪在运行时读取的任何反应属性。这就是所有 get/set 属性重写的目的,以便 Vue 知道每次读取属性。您不应该遇到循环、映射、reduce 等问题。问题往往是由异步代码或非反应性属性更新引起的。
猜你喜欢
  • 2021-11-21
  • 1970-01-01
  • 2019-08-12
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多