4

在自定义方法中使用 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) {

这是一个 REPL - https://svelte.technology/repl?version=1.13.2&gist=0eeab5717526694139ba73eae766bb30

我在文档中没有看到任何关于此的内容。我不能使用二传手,但我希望能够。

4

2 回答 2

6

tl; dr 这可以通过包装对象实现

这里的错误消息有点令人困惑——问题不是重复属性,而是你不能有 getter 和 setter in methods,在任何情况下,它都与填充组件内部状态的对象分开data(以及提供的数据)在实例化和可能存在的任何计算值)。我已经在这里打开了一个问题。

data本身也不能有 getter 和 setter——或者说可以,但它们不会被使用,因为从你的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等等。

我已经整理了一个小型 repo来演示这种方法 -在这里查看它的实际效果

于 2017-03-29T19:19:03.137 回答
2

编辑:正如 Rich Harris 在下面的评论中指出的那样,getter 和 setter 无法在其中工作,data因为 Svelte 将属性复制到内部的普通 JS 对象(因此忽略了 getter 和 setter)。我认为您可以做的下一个最好的事情是创建一个name可以像name()getter 和name(value)setter 一样调用的方法。

苗条的代码:

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

原帖:

您的 getter 和 setter 应该在 yourdata而不是 yourmethods中,因为它们最终会创建一个属性。此属性与您在原始方法中name定义为等于的冲突。我建议改用“私人”财产。'The Name'data_name

苗条代码(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>
于 2017-03-29T18:30:21.813 回答