Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 07.06.2019, 10:26
Кандидат Javascript-наук
Отправить личное сообщение для dpts Посмотреть профиль Найти все сообщения от dpts
 
Регистрация: 12.05.2015
Сообщений: 111

Vue JS странность
Приветствую. Может кто-нибудь подскажет где собака порылась.

Имеем допустим функцию:
function test(str){
	console.log(str);
	var pattern = /^\+\d{11}$/g;
	if (str.length > 12){
		str=str.substr(0,12);
	}
	console.log(str);
	console.log(pattern.test(str));
	return pattern.test(str);
}

если ей скормить +12345678901 или +123456789011 она вернет true

Пытаюсь завернуть ее в VUE.JS:

var vm = new Vue({
	el: '#app',
	data () {
		v:'+12345678901',
		max: 12,
		pattern: /^\+\d{11}$/g
	},
	computed:{
		valid: function(){
			if (this.v.length > this.max){
				this.v = this.v.substr(0,this.max);
			}
			return this.pattern.test(this.v);
		}
	},
	watch:{
		v: function(){
			if (this.v.length > this.max){
				this.v = this.v.substr(0,this.max);
			}
		}
	}
});


если в VUE dev tools меняю v на +123456789011, последняя единица отрезается, что логично, но valid стает false.
Тут-же еще раз меняю v на +123456789011, последняя единица отрезается и valid стает true.
и так по кругу. То-есть при заворачивании функции в vue регекспов .test() начинает срабатывать через раз.

При этом, если из функции, формирующей valid убрать проверку на количество символов
if (this.v.length > this.max){
	this.v = this.v.substr(0,this.max);
}

То все срабатывает как надо, с первого раза.
Но так уж вышло, что мне эта проверка нужна именно там.

Может быть может кто-то объяснить почему так, где собака порылась и как исправить, чтобы с первого раза срабатывало?

Последний раз редактировалось dpts, 07.06.2019 в 10:39.
Ответить с цитированием
  #2 (permalink)  
Старый 16.06.2019, 00:00
Аспирант
Отправить личное сообщение для Ким чен ин Посмотреть профиль Найти все сообщения от Ким чен ин
 
Регистрация: 30.05.2018
Сообщений: 40

вообще так нельзя делать
computed для этого " this.v = this.v.substr(0,this.max);"
не предназначен, в итоге результат не правильный
вот так должно быть
computed:{
		valid: function(){
			return this.pattern.test(this.v);
		}
	},

Последний раз редактировалось Ким чен ин, 16.06.2019 в 00:28.
Ответить с цитированием
  #3 (permalink)  
Старый 16.06.2019, 04:41
Кандидат Javascript-наук
Отправить личное сообщение для dpts Посмотреть профиль Найти все сообщения от dpts
 
Регистрация: 12.05.2015
Сообщений: 111

Сообщение от Ким чен ин Посмотреть сообщение
вообще так нельзя делать...
А почему так нельзя делать?
Дело-то скорее всего не в том, что обрезка завернута в computed потому что, можно например так:
<script  type="text/javascript">
    	Vue.component('vt-input', {
    		data: function () {
				return {
					pattern: /^\+\d{11}$/g,  
					max:12,             
		                res:{
		               	    valid:Boolean,
		               	    value:String
		                }
			    }
			},
			mounted:function(){
				this.res.value = this.value.value;
			},
			props: {
				value:{
					type:Object
				}
			},
			template: `
				<div>
					<input  
						v-model="res.value"
						v-on:input="$emit(\'input\', vtReturn($event.target.value))">
				</div>
			`,
			methods:{
				vtReturn:function(str){
					if (str.length > this.max){
						this.res.value = str.substr(0,this.max);
					}
					this.res.valid = this.pattern.test(this.res.value);
					return this.res;
				}
			}
    	});
    </script>
</head>
<body>
	<div id="app">
		<vt-input v-model="inputVal"></vt-input>
	</div>
	<script  type="text/javascript">
		var vm = new Vue({
			el: '#app',
			data () {
				return {
					inputVal:{
						valid:Boolean,
						value:'+12345678901'
					}
				}
			}
		});
	</script>
</body>

С тем же результатом - проверкой срабатывающей через раз.

Последний раз редактировалось dpts, 16.06.2019 в 05:57.
Ответить с цитированием
  #4 (permalink)  
Старый 16.06.2019, 11:44
Аспирант
Отправить личное сообщение для Ким чен ин Посмотреть профиль Найти все сообщения от Ким чен ин
 
Регистрация: 30.05.2018
Сообщений: 40

потому что computed это не функция, это свойство, хоть и с возможностью вычисления но все таки свойство. А свойство не может изменять сторонние переменные. Это не предусмотрено парадигмой vue. Если написать такое например в пхп шторме, он покажет ошибку, хотя и не критическую, но укажет что это косяк. Но в данно случае да, проблема не в этом.
Думаю вот так будет правильно работать (ватч не нужен)
computed:{
		valid: function(){
                        check();
			return this.pattern.test(this.v);
		}
	},
methods:{
    check(){
			if (this.v.length > this.max){
				this.v = this.v.substr(0,this.max);
			}
}

Последний раз редактировалось Ким чен ин, 16.06.2019 в 12:09.
Ответить с цитированием
  #5 (permalink)  
Старый 16.06.2019, 15:50
Кандидат Javascript-наук
Отправить личное сообщение для dpts Посмотреть профиль Найти все сообщения от dpts
 
Регистрация: 12.05.2015
Сообщений: 111

Сообщение от Ким чен ин Посмотреть сообщение
потому что computed это не функция, это свойство, хоть и с возможностью вычисления но все таки свойство. А свойство не может изменять сторонние переменные. Это не предусмотрено парадигмой vue. Если написать такое например в пхп шторме, он покажет ошибку, хотя и не критическую, но укажет что это косяк. Но в данно случае да, проблема не в этом.
С противоречием парадигме VUE понял избавимся от противоречия.
Перепишем обработчики в предыдущем варианте (когда компонент с инпутом) по предложенной вами схеме:
methods:{
	vtReturn:function(str){
		this.checker(str);
		this.res.valid = this.pattern.test(this.res.value);
		return this.res;
	},
	checker:function(str){
		if (str.length > this.max){
			this.res.value = str.substr(0,this.max);
		}
    }
}

Имеем то же самое, подрезка срабатывает каждый раз при попытке дописать цифр.
Проверка срабатывает через раз.
Ответить с цитированием
  #6 (permalink)  
Старый 16.06.2019, 16:37
Аспирант
Отправить личное сообщение для Ким чен ин Посмотреть профиль Найти все сообщения от Ким чен ин
 
Регистрация: 30.05.2018
Сообщений: 40

тогда я думаю надо просто посмотреть, что каждый раз приходит сюда
console.log(this.res.value)
this.res.valid = this.pattern.test(this.res.value);

сразу ясно будет что к чему
Ответить с цитированием
  #7 (permalink)  
Старый 16.06.2019, 16:53
Кандидат Javascript-наук
Отправить личное сообщение для dpts Посмотреть профиль Найти все сообщения от dpts
 
Регистрация: 12.05.2015
Сообщений: 111

Сообщение от Ким чен ин Посмотреть сообщение
тогда я думаю надо просто посмотреть, что каждый раз приходит сюда
console.log(this.res.value)
this.res.valid = this.pattern.test(this.res.value);

сразу ясно будет что к чему
В том и дело, что в this.res.value всегда все в порядке.
А this.res.valid по кругу true - false - true - false true - false.....

Такое ощущение что this.res.valid = this.pattern.test(this.res.value); срабатывает раньше подрезки.
Ответить с цитированием
  #8 (permalink)  
Старый 16.06.2019, 18:04
Аспирант
Отправить личное сообщение для Ким чен ин Посмотреть профиль Найти все сообщения от Ким чен ин
 
Регистрация: 30.05.2018
Сообщений: 40

не может быть, это синхронный код.
Единственный вариант тогда this.pattern.test(this.res.value);
не правильно работает
Ответить с цитированием
  #9 (permalink)  
Старый 16.06.2019, 22:34
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,492

С точки зрения парадигмы всё сказали.
А теперь с технической точки зрения: computed не вычисляется каждый раз. В vue хитрая система кэширования. Если vue считает, что ничего не поменялось - оно вернёт последнее значение.
Также все свойства в data на самом деле (для реактивности) заменяются на геттеры с сеттерами, а потому this.v = 'что-то' - это не прямое назначение, а вызов vue логики. Соответственно может что-то поломаться и на этом этапе от неправильного подхода.

Короче, вместо хаков делайте по человечески и будет вам счастье.)
__________________
29375, 35

Последний раз редактировалось Aetae, 16.06.2019 в 22:41.
Ответить с цитированием
  #10 (permalink)  
Старый 17.06.2019, 09:05
Кандидат Javascript-наук
Отправить личное сообщение для dpts Посмотреть профиль Найти все сообщения от dpts
 
Регистрация: 12.05.2015
Сообщений: 111

Сообщение от Aetae Посмотреть сообщение
С точки зрения парадигмы всё сказали.
А теперь с технической точки зрения: computed не вычисляется каждый раз. В vue хитрая система кэширования. Если vue считает, что ничего не поменялось - оно вернёт последнее значение.
Также все свойства в data на самом деле (для реактивности) заменяются на геттеры с сеттерами, а потому this.v = 'что-то' - это не прямое назначение, а вызов vue логики. Соответственно может что-то поломаться и на этом этапе от неправильного подхода.

Короче, вместо хаков делайте по человечески и будет вам счастье.)
Отличный совет. Покажите пожалуйста как по человечески?
Отойдем немного от логики VUE и перепишем метод vtReturn из примера с компонентом:
vtReturn:function(str){
	var res={
		valid:Boolean,
		value:''
	};
	if (str.length > this.max){
		str = str.substr(0,this.max);
	}
	res.valid = this.pattern.test(str);
	res.value = str;
	this.res = res;
	return res;
}

Теперь он в принципе не берет ничего из data для изменения, только пишет туда уже измененное.
С тем же результатом как и раньше.

Я же спрашиваю и прошу пояснений не от того, что я сверхмастер JS, а совсем наоборот.

Последний раз редактировалось dpts, 17.06.2019 в 09:20.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
UI верстальщик. VUE + Semantic UI shelomar Работа 0 12.01.2018 15:40
Высылаемые данные для Vue JS после перезагрузки страницы pro_xaoc Библиотеки/Тулкиты/Фреймворки 1 08.11.2017 22:32
Диалог между HTML и внешним JS в контексте расширения GoogleChrome ev1lart Events/DOM/Window 0 26.04.2017 19:25
Vue js вызвать метод andrei24 Библиотеки/Тулкиты/Фреймворки 1 29.01.2017 09:52
Картинка обрабатывается js 4yBaK Общие вопросы Javascript 10 11.09.2011 09:28