Vue: невозможно установить вычисляемое свойство

Мне нужна помощь с вычисленными свойствами и ajax в vue.

filterFactories - это список фабрик. Вычисленное свойство filterFactories создает этот список фабрик.

Теперь мне нужна новая функция: у меня есть кнопка для запроса ajax, который получает несколько новых фабрик. Я хочу установить вычисляемое свойство filterFactories после запроса ajax. К сожалению, ничего не происходит. это не имеет значения: 1. this.filterFactories = response; или 2. window.filterFactories = response; В обоих случаях - ничего не произошло

Можно ли обновить "filterFactories" после успешного запроса ajax?

Я добавил фрагмент кода большего размера

<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>


person kevin    schedule 11.02.2020    source источник
comment
То, как вы используете сеттер для вычисленных свойств, не имеет смысла. Что ты здесь делаешь? Ваш код настолько минимален, что я не могу понять, как вы используете вычисляемое свойство. Похоже, это просто должно быть в данных компонентов.   -  person Terry    schedule 11.02.2020
comment
Вы правы, геттер и сеттер не имеют смысла. Я обновил свой пример кода. Надеюсь, это более понятно. Вычисляемое свойство filterFactories вызывает некоторую другую функцию для фильтрации моего набора фабрик. И теперь я хочу обновить / сбросить filterFactories с новой кнопкой, которая вызывает и запрос ajax.   -  person kevin    schedule 11.02.2020
comment
В этом случае вы должны хранить свои данные в this.factories, а затем позволить filterFactories фильтровать ваши фабрики каждый раз, когда this.factories обновляется. Vue делает это автоматически, поэтому вам не о чем беспокоиться (другими словами, this.filterFactories будет реагировать на изменения в this.factories и выполнять фильтрацию при каждом обновлении последнего).   -  person Terry    schedule 11.02.2020
comment
Одна из проблем заключается в том, что ваш обработчик axios.post не привязан к своему контексту к экземпляру Vue (и по умолчанию будет window), поэтому this.filterFactories неправильно устанавливает window.filterFactories. Простое решение - использовать стрелочную функцию для сохранения правильного контекста: axios.post(...).then(response => this.filterFactories = response).   -  person tony19    schedule 12.02.2020
comment
спасибо за помощь. Я пробовал ваш подход window.filterFactories, но это не имело значения.   -  person kevin    schedule 12.02.2020


Ответы (1)


Vue использует некоторую магию для вычисляемых свойств: он сканирует код функции и автоматически создает наблюдателей для свойств, которые он находит в коде. Это хорошо работает в простых ситуациях, но у меня много раз не получалось с циклами, картой, уменьшением и т. Д.

При необходимости я использую несколько обходных путей, проще всего понять следующее: создайте искусственное свойство, на которое вы ссылаетесь в вычисляемой опоре, а затем обновите по мере необходимости:

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»;)

person ZPiDER    schedule 11.02.2020
comment
'он сканирует код функции и автоматически создает наблюдателей для свойств, которые он находит в коде'. Это не совсем так, здесь нет сканирования и анализа кода. Функция просто запускается, и Vue отслеживает любые реактивные свойства, которые читаются во время ее работы. Это то, для чего все переписывание свойств _1 _ / _ 2_, чтобы Vue знал каждый раз, когда свойство читается. У вас не должно быть проблем с циклами, отображением, уменьшением и т. Д. Проблемы, как правило, вызываются либо асинхронным кодом, либо нереактивными обновлениями свойств. - person skirtle; 11.02.2020