Используйте методы получения / установки в пользовательских методах 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>
Другие вопросы по тегам