Используйте методы получения / установки в пользовательских методах Svelte
Я не могу скомпилировать мой компонент svelte при использовании пары get/set в пользовательских методах. Это не поддерживается? Или я что-то не так делаю?
Пример:
Скажем, я хотел иметь компонент, который отображает имя, и я хочу установить имя с помощью.
com.name = 'The new name';
Однако я хочу, чтобы компонент использовал имя, только если в нем нет пробелов.
<h1>Hello {{name}}!</h1>
<script>
export default {
data () {
return {
name: 'The Name',
}
},
methods: {
get displayName() {
return this.get('name');
},
set displayName(val) {
if (val.indexOf(' ') < 0) {
this.set('name', val);
}
}
}
}
</script>
Проблема в том, что когда я пытаюсь это скомпилировать, появляется дубликат ключа.
Duplicate property 'displayName'
49: return this.get('name');
50: },
51: set displayName(val) {
Вот ответ - https://svelte.technology/repl?version=1.13.2&gist=0eeab5717526694139ba73eae766bb30
Я не вижу ничего в документации об этом. Я просто не могу использовать сеттеры, но я бы хотел иметь возможность.
2 ответа
tl;dr это возможно с объектом-оберткой
Сообщение об ошибке здесь немного сбивает с толку - проблема не в дублирующем свойстве, а в том, что вы не можете иметь геттеры и сеттеры в methods
, который в любом случае является отдельным от data
объект, который заполняет внутреннее состояние компонента (вместе с данными, предоставляемыми при создании экземпляра, и любыми вычисленными значениями, которые могут там быть). Я открыл вопрос для этого здесь.
data
сам по себе также не может иметь геттеров и сеттеров - или, скорее, может, но они не будут использоваться, потому что объект, возвращенный из вашего data
функция не совпадает с внутренним объектом состояния (иначе мы все могли бы столкнуться с ошибками, связанными с мутацией).
Но на самом деле довольно легко создать объект-оболочку, который позволяет вам получать и устанавливать данные компонента:
function wrap (component) {
var wrapper = {};
var data = component.get();
Object.keys(data).forEach(key => {
Object.defineProperty(wrapper, key, {
get() {
return component.get()[key];
},
set(value) {
component.set({ obj[key]: value });
}
})
});
return wrapper;
}
var component = new Component({...});
var wrapper = wrap(component);
wrapper.name = 'Rich';
Вы могли бы даже сделать component.data = wrap(component)
если бы вы были так склонны - тогда вы могли бы манипулировать component.data.name
и так далее.
Я собрал небольшое репо, демонстрирующее этот подход - посмотрите его в действии здесь.
Изменить: как Рич Харрис указал в комментариях ниже, геттеры и сеттеры не будут работать в data
потому что Svelte внутренне копирует свойства в простой объект JS (таким образом, игнорируя методы получения и установки). Я думаю, что следующая лучшая вещь, которую вы можете сделать, это сделать метод name
это можно назвать как name()
как добытчик, и name(value)
как сеттер.
Код Svelte:
<h1>Hello {{_name}}!</h1>
<script>
export default {
data() {
return {
_name: 'The Name'
}
},
methods: {
name(value) {
if (value === void 0) return this.get('_name')
this.set('_name', value)
}
}
}
</script>
Исходное сообщение:
Ваш геттер и сеттер должны быть в вашем data
а не ваш methods
потому что они создают свойство в конце концов. Это свойство конфликтует с name
вы определили как равный 'The Name'
внутри вашего оригинала data
метод. Я бы предложил использовать "частную" собственность _name
вместо.
Код Svelte ( REPL):
<h1>Hello {{name}}!</h1>
<script>
export default {
data() {
return {
_name: 'The Name',
get name() {
return this._name
},
set name(value) {
/ /.test(this._name) || (this._name = value)
}
}
}
}
</script>