Vue: [建议] Vue 2.0 - 请带回过滤器

创建于 2016-04-28  ·  116评论  ·  资料来源: vuejs/vue

你好,

在 Gitter 聊天中进行了热烈的讨论,论坛上有一篇很好的帖子说人们错过了 2.0 中的filter功能,实际上对于某些人来说升级是不可行的。 这似乎对社区来说不是一个积极的方向。

所以,我想提出这个建议,在 2.0 中带回过滤器,因为它们非常受欢迎,而且我同意,它们很聪明。 以下是过滤器的一些论据(来自不同的讨论,不保证正确性):

  • 它们在模板中更容易阅读

thing in things | filterBy 'foo' | orderBy 'bar' | limitBy 5

很容易阅读。 换句话说,链接过滤器有助于理解实际应该预期的内容。

  • 过滤器是全局的,这在模板/视图系统中非常有用。 Currency 是一个很好的过滤器的简单示例,可以在任何地方使用,只需调用它。
  • 没有过滤器,将会有大量的样板。
  • 过滤器让新手可以更快地学习并获得快速而良好的 Vue 获胜体验。
  • 为每个组件使用 mixin 以包含自制的“过滤器”实际上并不可行。

毋庸置疑,从工程的角度来看,删除过滤器可能存在强烈的论据,以及为什么我会建议这个线程是利弊,并投票支持或反对过滤器的回归。

斯科特

discussion

最有用的评论

这是最终决定:

  1. 将支持过滤器,但仅在文本插值内。 这将它们限制为文本格式化目的,同时将其他逻辑强制到 JavaScript 领域。
  2. Vue 2.0 将没有内置过滤器。 如果需要,社区可以创建自己的过滤器包。
  3. 过滤器语法将更改为对参数使用函数调用语法,而不是使用空格分隔。 这使它与 JavaScript 和其他流行的模板语言(Jinja2、swig、twig...)更加内联:

html {{ date | formatDate('YY-MM-DD') }}

所有116条评论

澄清最初来自 Gitter 聊天的观点: debounce不是过滤器,它只是 2.0 更改中的另一个,人们不会因为失去而感到兴奋。

@JosephSilber提供更正: debounce既是过滤器又是v-model参数。

谢谢@agc93。 我已经删除了这一点。

斯科特

在最坏的情况下,我们会想出小插件来处理这个问题。 关于过滤器,有https://www.npmjs.com/package/babel-plugin-pipe-operator
问题是如果没有 babel 编译,这将无法工作

我也对其中的一些变化不太感兴趣。 对于过滤器,注册全局 mixins似乎是一个简单的选择。 但是,我不太喜欢污染我所有组件的方法范围以执行诸如复数等超简单任务的想法。 但是,我从未使用过双向过滤器。

过滤器既方便又美观。 vue 总是做对的两件事(到目前为止)。

当我阅读关于 vue 2.0 的帖子时,我对所有新的可能性(尤其是虚拟 dom 和服务器渲染)感到兴奋,但我也对过滤器的消失感到惊讶和悲伤。

它们是我最喜欢的 vue 部分之一,不仅因为它们易于使用和链接,而且主要是因为它们易于扩展并且具有可以直接在模板中使用它们的优美语法。 特别是结合v-for循环,它们是完美的匹配。

考虑到我必须使用计算属性来替换我想要的每个道具的过滤,我担心我将来会写很多样板。 虽然 mixins 可能会缓解部分问题,但我仍然觉得使用 vue 的优雅和易用性将丢失一部分。

同意的人,可以在描述下点个赞吗? 这比用+1 17000 人发送垃圾邮件要好。 更好的是,提出一些有意义的用例。

我从未使用过双向过滤器,但我真的很想念过滤器! 我可以(有时我会)使用计算属性,但在一些简单的情况下,它是一种真正加快工作流程的便利。

考虑这个非常简单的例子

<input type="text" v-model="filter">

<ul>
    <li v-for="item in items | filterBy filter">{{ item }}</li>
</ul>

在不需要更复杂的过滤的情况下,上面的代码更容易编写。

现在将其与以下内容进行比较

<input type="text" v-model="filter">

<ul>
    <li v-for="item in filteredItems">{{ item }}</li>
</ul>
new Vue({
    el: 'body',

    data: {
        items: [],
        filter: ''
    },

    computed: {
        filteredItems() {
            var self = this
            return this.items.filter(function(item) {
                return item.indexOf(self.filter) > -1
            })
        }
    }
})

我并不是说第二个很难写,但是当你在很多地方使用它时,你会开始重复自己,只是需要一些额外的时间,你也许可以在其他一些更有用的功能上使用它!

无论哪种方式,我都会保持一个快乐的 Vue 用户,只是分享我对过滤器被弃用的看法!

过滤器可重复使用。 我可以创建函数来格式化我的数据一次,将其注册为过滤器并从所有实例中使用。 如何在 2.0 中做到这一点?

如何在 2.0 中做到这一点?

  • 米信
  • 用方法分离模块
  • 具有计算道具功能的独立模块

我刚刚在公告线程上发表了评论,所以我不会在这里复制所有内容,而是简单地链接到它:

http://archive.forum.vuejs.org/topic/3891/announcing-vue-js-2-0-public-preview/8

我完全理解从你身边拿走一些超级方便的东西的感觉。 但首先请花点时间阅读上面论坛帖子中@chrisvfritz的评论。 为了使讨论更容易,我只是在这里复制粘贴:


@theotherzach感谢您对 Vue 的热情! 我想更好地解释弃用,但首先,我应该自我介绍一下。 我是 Vue 核心团队的一员,我一直使用 Vue 来完成我的自由 UI 和数据可视化工作,我还是一名教育工作者,教人们使用 Vue 和 Rails 以及其他 Web 技术。 我经营一所代码学校,所以我几乎_每天_都帮助人们学习使用这些工具(并将它们一起使用)。

我也是在 Vue 2.0 中删除过滤器的主要支持者之一。

Vue初学者的过滤器问题

我赞成弃用过滤器的很大一部分原因实际上是_for_初学者。 在与学生一起工作时,这是不止一次出现的对话:

  • 学生:“所以过滤器基本上是一个函数?”
  • 导师:“是的!”
  • 学生:“好的,那我可以正常使用函数括号吗?”
  • 导师:“嗯,不。这是一种特殊的功能。”
  • 学生:“我可以在其他地方使用它吗?比如在计算值中?”
  • 导师:“不,你只能在模板中使用它,并且只能使用特殊的管道语法。”
  • 学生:“……为什么?”

绊倒初学者的一件大事是_exceptions_。 过滤器只是函数,_except_ 它们需要特殊的语法并且不能在任何地方使用。 而且它们使用的管道语法与可能集成到 ES7 中的管道语法不同,这意味着不久之后人们就会有两个非常相似的运算符来做非常相似的事情,但它们并不完全一样。 其中只有一个实际上是 JavaScript。

实用程序库_are_有用,但 Vue 不是其中之一

对于filterBy ,字符串和数字的转换以及其他特定过滤器,是的,它们在出现它们的应用程序中很有用。 Util 库通常很有用。 并且有许多很棒的实用程序库可供选择,但 Vue 不是实用程序库。 坦率地说,我们提供的实用程序都不是一流的。

处理货币、日期,甚至过滤数组——这些不是我们的重点。 许多应用程序不需要它们,而我处理过的大多数应用程序都_do_ 面临这些问题,需要比 Vue 当前提供的更强大的解决方案(或者_可以_提供而不引入显着的膨胀和轮子改造)。

在我的应用程序中,Accounting.js 处理货币的能力非常出色,Moment.js(如您所提到的)处理日期和时间, pluralize不能很好地处理许多复数形式,因此自定义计算值通常更可取,并且jsonJSON.stringify多一点。

计算属性的优点

使用计算属性代替过滤器还提供了一个优点,即处理后的值可以在组件中以 DRY 方式_anywhere_轻松重用。 我发现自己必须一直在我的应用程序中这样做。 计算属性还将更多实现细节移出模板,只留下对组件功能的清晰描述。 与全局定义的过滤器相比,一个优势在于,只需查看该计算机值的函数,即可准确了解和调整它的工作方式。 在数组上,链接 JavaScript 的mapfilter方法甚至提供了与管道相同的线性处理列表,但以更加声明性和易于操作的方式。

全局定义的有用性

如果您需要定义一个函数或您希望在所有组件中访问的任何其他内容, Vue.prototype.whateverIWant = mySuperCoolFunction是一个很好的方法。 就个人而言,我从来没有_想要_这样做。 我一直更喜欢将辅助方法放入模块中,并将该模块导入我需要的地方。 但仍然重要的是要注意注册全局变量 - 任何类型的 - 并没有变得更加困难。

debounce指令的情况

我不得不说,我实际上和你在一起! 我最近查看了我所有的 Vue 项目,每个在某处有input也使用了debounce 。 事实上,我过去的应用程序中只有一个_没有_使用 debounce。 虽然从技术上讲是一个实用程序 - lodash 和许多其他强大的项目提供了去抖动解决方案 - 这个问题对于 UI 开发非常普遍,对于_any_ 类型的应用程序。 编写自己的 debounce 函数也很重要,我可能想在几乎每个项目中都使用 lodash 的实现。

对此仍有一些内部争论,所以我们将看看它的发展方向。 但是,是的,就我个人和其他一些人而言,移除去抖动消除了v-model提供的大部分便利。

再次感谢您的热情!

说真的,我们很喜欢你对 Vue 的喜爱,并且很高兴你表达了你的担忧——尤其是以这种友善和尊重的方式! 我们在听你的。 核心团队是所有设计师、前端开发人员和数据可视化专家。 我们都在自己的工作中使用 Vue,它非常多样化,所以我们绝对致力于推出我们自己想吃的狗粮。 :-)

话不多说,让我们写代码看看如果没有过滤器,我们如何应用filterBy和reverse:

在单独的文件中编写全局纯过滤器函数以进行代码重用

//
// filters.js
//
function filterBy(list, value) {
  return list.filter(function(item) {
    return item.indexOf(value) > -1;
  });
}

function findBy(list, value) {
  return list.filter(function(item) {
    return item == value
  });
}

function reverse(value) {
  return value.split('').reverse().join('');
}

export {filterBy, reverse, findBy}

在 App.vue 模板中使用过滤器

<template>
  <div id="app">
    <h1> Reverse Demo </h1>
    <p> {{ reverse(msg) }}</p>

    <hr />

    <h1> Filter Demo </h1>
    <input v-model="userInput" />
    <h2> Prefix Matched Words: </h2>
    <ul v-for="word in filterBy(words, userInput)">
      <li>{{word}}</li>
    </ul>

    <h2> Exact Matched Words: </h2>
    <ul v-for="word in findBy(words, userInput)">
      <li>{{word}}</li>
    </ul>
  </div>

</template>

<script>
import {reverse, filterBy, findBy} from './filters.js'
export default {
  data() {
    return {
      userInput: '',
      msg: 'Hello Vue!',
      words: ['Black', 'Block', 'Blue', 'Alpha'],
    }
  },
  methods : {
    reverse,
    filterBy,
    findBy,
  },
}
</script>

在这里查看结果http://raywill.github.io/vuefilter/


如果使用过滤器,下面的 vue 代码会做同样的事情:

<template>
  <div id="app">
    <h1> Reverse Demo </h1>
    <p> {{ msg | reverse }}</p>

    <hr />

    <h1> Filter Demo </h1>
    <input v-model="userInput" />
    <h2> Prefix Matched Words: </h2>
    <ul v-for="word in words | filterBy userInput">
      <li>{{word}}</li>
    </ul>

    <h2> Exact Matched Words: </h2>
    <ul v-for="word in words | findBy userInput">
      <li>{{word}}</li>
    </ul>
  </div>

</template>

<script>
export default {
  data() {
    return {
      userInput: '',
      msg: 'Hello Vue!',
      words: ['Black', 'Block', 'Blue', 'Alpha'],
    }
  },
}

显然,在支持过滤器的情况下,我们可以编写不那么琐碎的代码。
我个人更喜欢 vue 1.0 的方式,这让编码更有趣。

至于样板问题 - 有几种方法可以处理它。

1.显式导入/导出

就像上面演示的

  1. 您无需查看 Vue 的过滤器文档即可了解其工作原理。 函数的来源和实现方式非常明确。
  2. 函数本身就是 JavaScript。 您可以更改/组合它们以适应特殊用例,这与您无法触摸的内置过滤器不同。
  3. 您可以在方法、计算属性和您编写 JavaScript 的任何地方导入和以编程方式重用这些函数。

2. 将它们附加到Vue.prototype

Vue.prototype.filters = {
  filterBy: ...,
  orderBy: ...
}
<ul v-for="word in filters.filterBy(words, userInput)">
    <li>{{word}}</li>
 </ul>

3. 发挥功能(适用于高级用户)

computed: {
  filteredThings () {
    return this.things
       .filter(contains(this.foo))
       .sort(by(thing => thing.bar))
       .slice(0, 10)
  }
}

辅助函数如下所示:

// a function that returns a predicate function for array.filter()
function contains (value) {
  return thing => thing.indexOf(value) > -1
}

function by (getValue) {
  return (a, b) => {
    return getValue(a) > getValue(b) ? 1 : -1
  }
}

同样,一个非常重要的设计考虑是内置过滤器可能很有用,但它们缺乏纯 JavaScript 的灵活性。 当内置函数不能满足您的需求时,您要么最终重新实现类似的东西(并在您的最终代码中提供,内置变得无用的死代码),要么必须等待 Vue更新它们并发布新版本。

@yyx990803我喜欢原型方法,但是需要多个过滤器的情况呢?

filterBy旁边使用orderBy很常见

<ul v-for="word in filters.orderBy(filters.filterBy(words, userInput), column, -1)">
    <li>{{word}}</li>
 </ul>

如果你也会添加limitBy呢?

<ul v-for="word in filters.limitBy(filters.orderBy(filters.filterBy(words, userInput), column, -1), limit)">
    <li>{{word}}</li>
 </ul>
这种方法是否会降低代码的可读性?

是的,至少在我看来。

我想我们可以组合像filterAndOrderBy这样的过滤器,但感觉也不对。

我愿意改变,只是想想出一个几乎同样简单的方法来处理它!

此外,能够在任何地方使用过滤器的好处也是一个非常好的点。

请注意,@vuejs/collaborators 一直在讨论提供当前集成过滤器的实用程序包的选项。 有很多资源可以为您的代码库提供实用工具。

删除核心过滤器的一件好事是,您现在可以自己自定义/实现它们。 这为您提供了更多的灵活性。

@rigor789模板表达式应该尽可能简单。 理想情况下就像<div v-for="filteredData"> </div> 。 这可以是一个计算的 prop,它可以保存创建过滤数据的逻辑。 这更具可读性,并且比以下内容更好:

<div v-for="item in filters.orderBy(filters.filterBy(words, userInput), column, -1)"> </div>
或者
div v-for="item in data | filterBy | orderBy "

分配为计算属性更可重用,甚至可以传递给子组件。 如果您想在两个地方使用过滤后的数据怎么办? 与在表达式中使用链式过滤器相比,模板具有简单的表达式更容易、更简单、更可靠且更具可读性。

对于任何跟随的人,我在这里回答了@chrisvfritz :http: //forum.vuejs.org/topic/3891/announcing-vue-js-2-0-public-preview/17

下面解决了我的一个_非常_几个全局可用的纯视图辅助函数的用例。 我撤回了对过滤器移除的担忧。 烧掉他们! 🔥 祝贺@chrisvfritz@yyx990803在互联网上改变了某人(我的)的想法!

Vue.prototype.filters = {
  filterBy: ...,
  orderBy: ...
}
<ul v-for="word in filters.filterBy(words, userInput)">
    <li>{{word}}</li>
 </ul>

我完全同意@yyx990803 ,删除过滤器并坚持使用普通的 JS 函数。

@blake-newman 这是一个很好的观点,在这一点上我基本确信,并且考虑到可读性,我认为可以实现这样的事情

computed: {
    filteredItems() {
        return f(this.items).filterBy(this.filter /* string or function*/)
                            .orderBy(this.field, -1)
                            .limitBy(10)
                            .apply()
    }
}

这是这个概念的快速jsfiddle

删除核心过滤器的一件好事是,您现在可以自己自定义/实现它们。 这为您提供了更多的灵活性。

你总是能够自己定制/实现它们。

Vue 不是实用程序库。 坦率地说,我们提供的实用程序都不是一流的。

我们关心的是删除模板中的过滤器功能。 删除内置过滤器确实很有意义——通过将它们代理到下划线/其他实用程序库,可以轻松地重新创建它们。 然后,有人甚至可以发布一个插件来重新创建所有当前的内置过滤器。

使用计算属性代替过滤器还提供了一个优点,即处理后的值可以在组件的任何地方以 DRY 方式轻松重用。

当然,如果您必须在其他地方重用它,您可以使用计算属性。 但如果你不这样做,过滤器仍然更方便。


我在上面分享的链接中还发布了一些其他观点。

为什么不支持像 ES7 提议的语法一样运行的过滤器语法? 这将允许人们继续使用他们心爱的过滤器,并使其与未来可能发生的事情保持一致。 最终当我们拥有 ES7 管道时,您可以在不更改 api 的情况下切换内部实现。

ES7 管道是否被批准或有很多变化?

理论上它可能会发生变化,但似乎......稳定?
状态:mindeavour/es-pipeline-operator#33

@JosephSilber @young-steveo @thelinuxlich我认为我们在一般管道的价值方面意见一致。 😃 2.0 中新编译器的一个优点是我们可以通过 Babel 管道生成的渲染函数代码。 这仍然需要进一步探索,但是一旦|>获得更大的发展势头并为其开发了 Babel 插件,您就可以愉快地再次使用管道链接方法 - _everywhere_ 在您的应用程序中。 作为 LiveScript 和其他函数式语言的忠实粉丝,我绝对认可它的价值

这个管道运营商甚至不在第 0 阶段

@thelinuxlich是的,我相信他们仍在等待 TC39 的冠军。 😞

@rigor789这也是我想提到的替代方案之一! JavaScript 的强大功能使您可以实现您选择的表现力,而且 imo 它比将过滤逻辑放在模板中要好。

@yyx990803在以下情况下,当更新一个用户的名称时,Vue 如何执行?

<div v-for="user in users">
  <p>{{ user.name |> capitalize }}</p>
</div>
Vue.extend({
  computed: {
    displayableUsers() {
      for (user of this.users)
        user.name = capitalize(user.name);
    },
  },
});

似乎前者只会重新渲染一个对象,而后者会重新计算整个列表?

@rpkilby似乎并不等同。 它会更像:

Vue.extend({
  methods: {
    capitalize () { ... }
  }
})
<div v-for="user in users">
  <p>{{ capitalize(user.name) }}</p>
</div>

仍然不喜欢使用方法作为过滤器的想法(直觉感觉它似乎是错误的,但无法真正解释它)。 无论哪种方式,您都讨论了其他使过滤器可用的方法,所以 +1。

此线程中的任何建议都比不上过滤器的表现力和简洁性。 它只是没有。

这让我很伤心。 就像我在论坛帖子中所说的那样:对我来说,这消除了 Vue 的很大一部分。

如果你在找我,你可以在角落里找到我在哭泣的声音😟

没办法,这种变化鼓励了良好的 Javascript 编码,处理它:)

所以我刚刚与@yyx990803进行了长时间的讨论,从用户的角度来看,我建议保留_syntax_ 支持,因为它确实感觉优雅和自然。 我的想象是这样的:

<li v-for="item in items | filterBy 'name' | orderBy 'title' 1">{{ item.name }}</li>
...
<script>
  ...
  methods: {
    filterBy (items, field) { return filtered; },
    orderBy (items, field, order) { return filtered; }
  }
  ...
</script>

我的印象是,这将接近两全其美。

但最后,我相信作为一个整体移除过滤器实际上是一件更好的事情:就像@thelinuxlich刚才所说的那样,它鼓励更好的 JavaScript 和逻辑思维。 我们不会在 Laravel 的 Blade 或任何其他框架的视图层中引入逻辑,我们也不应该在 Vue 的模板中引入逻辑。

也就是说, @JosephSilber如果你看看另一个角落,你会在那里找到我。

对我来说过滤器感觉很漂亮,语法正是过滤器语法应该是什么样子。

Vue 对我来说还有一个吸引人的地方是它附带(一些)电池。 失去这些东西中的任何一个都将是非常可悲的——在我看来,这两者都让 Vue 脱颖而出。

通读该线程,似乎最关心过滤器的事实是 Vue 具有默认过滤器,而不是真正的函数本身(或者是它吗?我仍然不确定)。

我喜欢@blake-newman 的过滤器插件思维,应该有预构建的示例。 如果其他人想出其他过滤器,它们应该是即插即用的。 那很好啊。 我绝对同意创建过滤器是用户的责任。

仍然需要的是管道和链接能力以及原始过滤器功能的全局性。 @yyx990803 涵盖了对全球性的担忧。 用管子串起来怎么样? 它有助于阅读模板并理解预期的输出。 上面讨论了管道和链接。 还能做吗? 为什么这是一件坏事? 对设计师来说,就是金子! 过滤器是设计师的工具,而不是 JS 程序员的工具。 因此,在我的书中,写出更好的 JS 的论点被搁置了,但我可以理解为什么需要它。 但是,作为一名设计师,我也想编写更好的代码,而过滤器让我可以做到,非常漂亮。 :微笑:

斯科特

这是关于链接的事情 - 过滤器主要用于两个目的:

  1. 格式化文本;
  2. 处理一个数组。

在格式化文本的情况下,90% 或更多的时间只使用一种实用方法。 在这种情况下,链接并不是真正的问题。

至于数组:我已经指出,数组处理实际上是逻辑,更适合 JavaScript。 拥有多个链式数组过滤器在简单时可能看起来不错,但当您为每个过滤器使用超过 1 个参数时可能会变得丑陋。 它还鼓励您在您确实不应该在模板中放入过多的逻辑。 它们也很不灵活(不能轻易地检索处理过的值)。 相比之下,用 ES2015 的原始示例

<div v-for="thing in things | filterBy 'foo' | orderBy 'bar' | limitBy 5">

可以写成:

computed: {
  filteredThings () {
    return this.things
      .filter(item => item.title.indexOf('foo') > -1)
      .sort((a, b) => a.bar > b.bar ? 1 : -1)
      .slice(0, 5)
  }
}

它只是 JavaScript,没有魔法,没有可供学习的替代语法和特定于过滤器的 API。 您可以访问已处理的值(智能缓存)。 如之前的评论所示,您还可以在此之上随意添加糖。 另外,您的模板看起来更干净:

<div v-for="filteredThings">

我知道这就像一个方便的东西被拿走了,但老实说,过滤器的论点现在对我来说听起来就像只是为了语法而保留语法。 在我看来,不仅仅是“因为它很优雅”来证明一个特性是合理的——它需要提供客观的价值。 inline-templates就是这种情况,但我看不到过滤器。

@ yyx990803 - 我认为你的例子说明了这个问题。 再说一次,我不是最好的 JS 程序员,但我不需要成为 JS 程序员就知道filteredThings没有说明它的真正作用。 对我来说,这是一种不好的做法。 :smile: 过滤方法是全局的这一事实也意味着我必须在文档、代码中搜索或破译输出以找出该方法的作用。 不是很优雅。 对?

那么好吧。 我们可以有一个类似“filterByOrderByAndLimit”的方法名。 论据呢?

<div v-for="filterByOrderByAndLimit(things,thing,'foo','bar',5)">

那会是正确的吗?

如果是这样,那可能是可行的。 不过,它看起来并不好。

而且,现在我只想要 filterBy 和 OrderBy。 我是否也需要一个单独的方法来做到这一点? 然后我想添加货币格式。 另一种方法? 模板中的过滤器链接使操作演示变得灵活且极具表现力。 这种担忧尚未通过方法得到妥善解决(而且我缺乏知识并不能让我更好地理解方法)。

这可能吗?

<div v-for="filterBy(things, thing, 'foo').OrderBy('bar').Limit(5)">

我同意在模板中做太多的逻辑是应该避免的。 但是,过滤器链接和在应用程序的组件/模板中的任何位置简单地弹出过滤器的能力是一个很棒的概念,并且您首先添加它是有原因的。 那是什么原因? 如果你能说出它们的名字,那么我敢打赌它们比“但它会促进不良做法”多出一英里。

任何允许灵活性的东西都可能被不当使用,就像 Vue 本身一样。 inline-template的主要论点是它很灵活,允许以不同的方式使用 Vue。 过滤器并没有太大的不同,除了它是 Vue 内部的并且不会影响 Vue 在外部的使用方式。 尽管如此,这并没有贬低它的重要性。 请记住,很多人也说过这对他们来说是不可行的升级。 就是这么重要! :微笑:

新方式只需要与旧方式相同的属性。

  • 可链式
  • 全球的
  • 添加到模板以很好地表达模板中的数据将如何被操作

(我是不是忘了什么?)

如果它可以做到这一切,那么我相信每个人都会非常满意。 我个人看不到它发生在方法上(还)。

斯科特

@smolinari

  1. 我已经明确指出,您应该在模板中减少逻辑。 不管你喜不喜欢,这都是我的看法。 显然你可以不同意,但如果你想反对推荐的最佳实践,我无法帮助你。
  2. 给定 (1) - 我已经解释了为什么链接不是问题,因为复杂的逻辑应该在 JavaScript 中完成。
  3. 我还举例说明了如何添加全局可用的方法。
  4. 请参阅@rigor789示例,了解与您想要的类似的自定义链接语法。
  5. 该框架的目标是提供_我_认为是开发前端应用程序的最佳方式,而不是取悦所有人。 所以请不要使用“如果你不把这个功能还给我,我就不会升级”——它不起作用。

你们为什么不试用这个新的 alpha 版本一周,然后提出一些非常有价值的评论(基于您的实践)? 也许尝试重构您现有的应用程序,让我们知道哪些是不可能的,哪些改进了,哪些变得更糟,这样我们就可以更好地讨论它。 这对我认为的每个人都有用。

@yyx990803 - 我同意 1。所以我们同意。 :smile: 我只是不同意这是一个适当的理由拿出一些已经获得了如此多的爱。

所以,我猜你已经决定,实用的 JS 比实用的 HTML 更好?

不升级的理由是其他人所说的。 我只是想沟通和减轻这种情况。

我自己的最后一个论点。 从用户的角度来看这个。 假设我有一个像 Laravel 之类的系统或其他一些包含 Vue 的 MVC 或 MVVM 系统,它还允许该系统的用户构建自己的组件。 过滤器实际上简化了学习曲线,它允许该系统的用户完成很多工作,而无需触及任何 JS。 我是 Vue 的粉丝,因为它确实让非 JS 程序员仍然可以完成很多工作。 这也是我不喜欢 React 和 JSX 的原因。 随着时间的推移,这种组合将比 Vue 拥有更小的用户群。 我会赌钱。

我也明白真正的灵活性在于 JS。 尽管如此,请不要仅仅依靠 JS 来获得 Vue 的灵活性。 请记住,并不是每个人都是杀手级 JS 程序员。 事实上,大多数人都不是。 过滤器是为这些人完成很多工作的好方法,它是进一步操作 JS 的一个很好的垫脚石。 过滤器无法完成? 深入了解 JS 方法。

行。 我够了......我已经完成了。 而且,感谢您无论如何收听。 Vue仍然很棒! :微笑:

@azamat-sharapov - 好点。

斯科特

看到有人试图为 JS 内部的不良做法辩护,这让我很难过。 真的,你不需要成为专业人士,只需做基本的功课(或者这些天不再是基本的了吗?)

我对过滤器内部方法的问题是语义。

在 oops 术语中,过滤器就像静态函数,而方法是非静态函数。

过滤器传达的语义与方法截然不同。 最大的区别是过滤器不能使用this ,但方法可以。

@yyx990803虽然使用Vue.prototype.filters可以工作,但更改Vue对我来说似乎不是一个好习惯。 我宁愿提倡创建一个包含所有过滤器的单独(全局)对象。

这看起来不像是好的做法,因为全局变量不是好的做法。 推荐的方法是显式导入辅助方法。 对于那些不想显式导入方法的人来说,附加到原型是一种解决方法。

至于语义 - 过滤器无论如何都是一个创造的概念。 在 JavaScript 中,您不会仅仅为了大写字符串而发明不同的语义——您调用了一个函数。 这就是它们的本质,JavaScript 函数。

我将再发表一条评论,试图让我的个人观点更清楚,主要是因为“试图证明 JS 内部的不良做法”评论。 我当然不想那样做。

我意识到 Vue 不仅仅是一个模板系统,但它也是一个模板系统,我担心它正试图摆脱这个角色,我觉得它不应该这样做。 因此,作为一个模板引擎/系统,将 Twig 模板引擎作为一个非常成功的例子来说明人们对模板系统的期望。 他们的文档中有一个“为模板设计者”部分和一个“为开发者”部分。 作为一个模板系统,Twig 对于模板设计者来说也很强大,因为它充满了默认行为,包括过滤器。 它允许非开发人员在不直接了解 PHP 的情况下使用模板系统做大量工作。 他们只需要了解 Twig 提供的内容以及如何使用它。 我也在 Vue 中寻找这个。 我也想在文档中看到“模板设计师的 Vue”部分。 :微笑:

此外,非常重要的是 Twig 的可扩展性。 如果库存版本中没有某些内容,则可以添加。 那是开发人员介入的时候。好处也是,扩展可以共享,这意味着它只需要完成一次。

这两个级别的设计师/开发人员的另一个好处是,您可以获得更广泛的用户群。 更广泛得多,这与 . 当默认行为还不够时,那就是当他们开始自愿学习底层语言的时候。 那是他们学习最佳实践和其他方法的时候。

如果你说 Vue 不学习 JS 就不能成为模板引擎,那么我会说,它大大降低了它的市场价值。 如果您说,您将敞开大门,让其他人将模板引擎的这些工具作为插件制作,很棒。 但是,那么每个人都会为模板系统中应该包含的内容而战。 这也是适得其反的恕我直言。

在您的学生谈论过滤器示例 Evan 中,是学习 JS 的人还是学习模板引擎的人? 如果是后者,我敢打赌对话会有所不同。

好歹。 我仍然认为 Vue 是一个成功的系统。 我希望我的想法可能会让其他人以某种方式对 Vue 的角色有不同的看法。 :微笑:

斯科特

@yyx990803如果过滤器是创造的概念,那么为什么首先创造它们?

我相信这是因为在<template>内部,所有外部变量,如$dataabc都转换为this.$datathis.abc ,因此定义了普通的 js 函数组件外部不能被引用。 引入过滤器来克服这个限制。

该限制仍然存在——我假设我是对的——要消除限制将需要开发人员明确编码this.abc以引用this.abc并访问 js 函数,因为它们将在js。

但这将是一个太强大的功能,容易被滥用,迁移旧代码会很痛苦。 当前的语法对我来说看起来比这要好得多。

我同意你的观点,过滤器基本上是 js 函数,应该导入到组件中。 我只是不喜欢它们被定义在与方法相同的位置。

大家好。 我阅读了整个线程,这就是我的想法。

  • 没有人会错过像orderBy filterBy和任何其他内置过滤器
  • 每个人都想拥有的是模板中的管道运算符
  • 核心团队表示,逻辑应该保留在 javascript 中,而不是模板中,此外还有一个带有管道运算符的 es7 功能。

作为一个快速总结,我认为在 js 实现原生管道运算符之前它可能是一个很好的解决方案,将管道运算符作为插件并保持 2.0 版本不变。 所以,用户可以做

Vue.use(require('vue-pipe'))

在我们等待新功能实现的同时,它可能会包含一些关于即将弃用或其他东西的警告。 我知道任何人都可以实现该插件,但我认为如果它由 Vue 团队提供和维护会更好,这可能吗?

我可能是错的,但我不认为 Vue 允许插件与它的编译器混淆..

@azamat-sharapov 当然不是。 我只是不认为它会与 Vue 编译器混淆:open_mouth:

@YerkoPalma我绝对 _love_ 管道操作员。 我痴迷于在函数式语言中使用它,迫不及待地想在 JavaScript 中使用它! _但是_,想象一下 Vue 从来没有过滤器。 你会要求前端框架扩展 JavaScript 的语法吗? 那是 Babel 或 compile-to-JS 语言的领域,而不是 UI 框架。 如果您喜欢使用 LiveScript 之类的语言,就像我经常做的那样,您可以。 但这里的问题不在于 Vue。 它与 JavaScript 本身有关,我们不是来解决这个问题的。

此外,如果我们能够像希望的那样通过 Babel 将 2.0 中的渲染结果通过管道传输,那么您甚至可以根据需要使用非 TC39 跟踪插件 - 在您的 JavaScript 中始终如一地使用,而不是只是在模板中。 因此,如果您只想要一个管道,那么您很可能能够拥有它。 而且您今天_可以_在 1.x 中使用它——请注意,您将在模板中使用的管道可能具有与 Babel 中的管道不同的优先级和行为。

@smolinari和其他人。 我经常听到两个短语(及其变体):

  • “考虑开发人员/用户的观点”
  • “想想初学者”

两者都暗示了一个假设——我们_不_考虑这些群体。

我之前提到过,但我想它需要重申。 核心团队中的_每个人_要么是设计师,要么是前端开发人员,要么是两者的组合。 我们每天都在自己的工作中使用这些工具。 我们也将使用 Vue 2.0。 相信我,我们 _are_ 正在考虑这一点。 😉

对于初学者,我在这里做了一个案例,但我想我会更详细地介绍。 我是一名教育工作者。 我是消除过滤器的支持者,_考虑初学者_。 我亲自教过数百人——甚至可能超过一千人——如何练习 Web 开发,通常是从零开始。 没有以前的编码经验。 我已经对中学生、高中生、大学生、专业成年人和老年人做过这件事。

从这个角度来看,我可以告诉你,虽然过滤器起初看起来像是令人兴奋的魔法,但它们最终会因为有限的便利性而引入更多复杂性,从而减慢学生的学习速度。 如果他们从未在 Angular 或 Vue 中使用过,并且这种对话被颠倒了——我们试图在 2.0 中_引入_它们——我们将很难解释为什么需要它们以及何时应该使用它们。

在讨论 2.0 中的弃用之前,我已经从我们的代码学校的课程中删除了过滤器,因为我们收集了足够的证据表明它们对初学者弊大于利。 我们希望他们获得更多通用 Vue 特性的经验,比如方法和计算属性。 我们甚至不鼓励使用过滤器,因为它们更容易发现不良做法。

希望能解决这两个抱怨。 走着瞧。 😃

但是,想象一下 Vue 从来没有过滤器。 你会要求前端框架扩展 JavaScript 的语法吗?

我当然会,因为过滤器对于 _templates_ 非常自然,就像之前提到的 Twig 中一样。 我觉得拥有一个管道运算符就像在模板中拥有胡子语法一样自然,我的意思是,胡子不是 html,也不是 javascript,你们也要删除它们吗? 管道操作员有什么不同?

“想想孩子们”的说法简直是愚蠢的。 据我所知,Vue 不是为教 JavaScript 而设计的,而是为前端开发人员完成的。 对于后者,过滤器很棒。

如果他们从未在 Angular 或 Vue 中使用过,并且这种对话被逆转了——我们试图在 2.0 中引入它们——我们将很难解释为什么需要它们以及何时应该使用它们。

我非常不同意。 自 2005 年以来,我一直在使用一个名为 Django 的 Python 框架,它的模板语言——它是大多数后来诞生的模板语言的灵感来源——从一开始就有过滤器。 在与前端开发人员一起使用它们十多年后,我开始欣赏它们的美丽和实用性。 看到这种语法消失会很伤心。

(这是 Django 对过滤器所做的事情:https://docs.djangoproject.com/en/1.9/ref/templates/builtins/#built-in-filter-reference)

@Uninen请注意你的语气——称别人的论点愚蠢并不是参与讨论的建设性方式。

对于那些与服务器端模板语言进行类比的人 - 需要注意的一个重要方面是服务器端模板语言没有 Vue 模板所具有的灵活性(没有计算属性,有限的表达式)。 此外 - 它们是为完全不同的目的而构建的:输出静态字符串。 Vue 模板是交互式 DOM 的表示形式——有双向绑定、事件处理程序、组件 props 等等。 过滤器仅适用于 Vue 上下文中非常有限的用例:今天我认为在任何地方都允许过滤器是一个坏主意,例如 v-model、v-for 和 v-on 上的过滤器引入的复杂性比好的多。

一种可能的选择是保留过滤器,但仅用于文本插值 - 即您只能在{{ }} s 中使用它,而不是在指令中。

作为一个有趣的参考:Angular 2 仍然有过滤器(重命名为“管道”),但他们也有意删除了列表过滤器。

对不起我的语言,没有侮辱任何人的意思。

对我来说,框架的目的_是_做困难的事情,让使用这些工具的开发人员看起来很容易。 我仍然认为语法是无法被击败的,再一次,看到它消失会很伤心。

我不知道或理解很多底层机制,但从用户的角度来看,实用性胜过纯粹性:)

在相关说明中,有趣的是看到这个社区似乎有多少热情。 对我来说,Vue 是一个新鲜而令人振奋的工具,也许这就是为什么我自己必须参与绘制这个特殊的棚子 :)

对于另一个数据点,Ember 没有过滤器,也不允许组件方法,尽管它确实具有计算属性。

对于执行模板内转换的纯函数的用例,您必须注册一个把手助手/灰烬助手。
http://emberjs.com/api/classes/Ember.Helper.html

车把助手在语法上与不是车把助手的东西在语法上是不同的,这就是我提出它的原因。 它们与管道过滤器语法有共同之处。 然而,把手模板是“无逻辑的”,这意味着它们需要特殊的语法来调用模板内函数。 Vue 没有的问题。

过滤器对初学者来说很简单,通过在数组中使用漂亮的输出或过滤器\订单搜索可以看到一些魔力

 {{ article.date.created_at | moment 'MM.DD.YYYY HH:mm:ss' }}

并轻松定义它

Vue.filter('moment', (str, format) => moment(str).format(format));

在模板中很简单,很清楚,对于 2.x,您在外部模块中定义过滤器并在模板中获取

import moment from 'moment'

methods:{
   moment(date, format){
       return moment(str).format(format)
  }
}

并在模板中

 {{ moment(article.date.created_at, 'MM.DD.YYYY HH:mm:ss') }}

作为建议,为什么不将旧过滤器留在模板中,而是将过滤器移动到单独的模块中并从方法部分使用它?

所以如果你需要它,就做

npm install vue-utils

并使用 utils 包中的特定过滤器

import {moment} from 'vue-utils/date'
import {price} from 'vue-utils/numbers'

methods:{
   moment, price
}

并用作普通过滤器

 {{ article.date.created_at | moment 'MM.DD.YYYY HH:mm:ss' }}
 {{ product.price | price }}

结果它被翻译成简单的函数调用

moment(article.date.created_at, 'MM.DD.YYYY HH:mm:ss')
price(product.price)

_笔记_
对我来说,过滤器最常用于格式化数据,例如日期、数字或字符串。 对于过滤数组\对象,我认为最好使用通用 vue 模块中的计算和函数:

import _ from 'vue-utils/array'

computed:{
   ordersTable(){
         return _(this.orders)
                        .filterBy(this.filter)
                        .sortBy('date', -1)
                        .limit(10)
   }
}

好处:
初学者可以轻松使用旧的过滤器,但在模板中计算和使用漂亮的函数来格式化数据输出,程序员可以为其编写自己的函数模块并易于使用。

_为什么要分离模块?_
我认为它不需要在 Vue 的核心,但是 Vue 必须有一些开发人员模板设计器的实用程序,所以不需要一直需要 lodash、moment 或其他,只需从 npm 安装 utils 并轻松使用它,但保存旧的调用语法模板。
但是对于过滤器必须做一个重要的思考,必须有纯函数,比如 vuex 中的 getter。

它易于支持,易于用户重用扩展,并且对模板有很好的了解。

你们需要的是清晰的升级路径和学习如何模块化 Javascript 代码的愿望。

@thelinuxlich我们谈论过滤器。

 {{ article.date.created_at | moment 'MM.DD.YYYY HH:mm:ss' }}

只是语法糖

{{ moment(article.date.created_at, 'MM.DD.YYYY HH:mm:ss') }}

但是在 Vue\javascript 中完全排除初学者的过滤器是不好的。 为什么 Laravel 社区喜欢 Vue? 因为它简单而强大。

如果我们完全删除过滤器,需要为_“模板设计者”_提供替代方案,不需要知道如何对数组进行排序或过滤,只需输入代码形式的示例并获得结果。

程序员必须知道如何 _modularise_ Javascript 代码,但为小事使用它的人则不需要知道它。

如果我们谈论_“对于模板设计师”_ 可以放

<script src="vue-utils.js"></script>

和内部代码使用

Vue.use(VueUtils)

computed:{
   ordersTable(){
         return this.utils.array(this.orders)
                        .filterBy(this.filter)
                        .sortBy('date', -1)
                        .limit(10)
   }
}

从例子和自豪的自己,不需要知道 js 来过滤和排序数组,很多人想做一些事情,但是很难理解像这样的代码

computed: {
  filteredThings () {
    return this.things
      .filter(item => item.title.indexOf('foo') > -1)
      .sort((a, b) => a.bar > b.bar ? 1 : -1)
      .slice(0, 5)
  }
}

所以没有必要为这类人做复杂的事情,如果我们可以为那里提供简单的解决方案,这对开发人员有好处。

一种可能的选择是保留过滤器,但仅用于文本插值 - 即您只能在 {{ }} 中使用它,而不是在指令中。

我认为这可能是一个很好的妥协。 虽然它不会满足每个人,但它是我使用过滤器的全部,我实际上发现它们目前可以做的更多是奇怪的。

如果您想使用过滤器并通过有效地删除双向过滤器来降低复杂性,它将允许方便的文本格式。

在我看来,您的 momentjs 过滤器示例已经向模板传递了太多逻辑。

说真的,您应该将所有这些“管道之爱”指向规范存储库,直到它达到 TC39 :)

我喜欢@yyx990803@VitaliyLavrenko 的建议。 这可能是一个很好的中间立场。

斯科特

我喜欢@VitaliyLavrenko 的提议,但是当我说类似的话时,关于在插件中使用管道运算符@azamat-sharapov 说插件不应该与编译器混淆......所以我很困惑它是否可能或者如果我只是误解了评论?

@thelinuxlich

你读什么更好?

<div v-for="thing in things | filterBy 'foo' | orderBy 'bar' | limitBy 5">

或者

computed: {
  filteredThings () {
    return this.things
      .filter(item => item.title.indexOf('foo') > -1)
      .sort((a, b) => a.bar > b.bar ? 1 : -1)
      .slice(0, 5)
  }
}

以开发人员的身份思考并询问不了解 javascript 的人。

至于我,对于_不是开发人员_来说更好的是这样的:

Vue.use(VueUtils)

computed:{
   ordersTable(){
         return this.utils.array(this.orders)
                        .filterBy(this.filter)
                        .sortBy('date', -1)
                        .limit(10)
   }
}

它是中间的,像 vue-resource 一样使用,只是 common lib。


关于管道,我是语法糖

物中之物| filterBy 'foo' | orderBy 'bar' | 限制5

为了

thing in limitBy(orderBy(filterBy(things, 'foo'), 'bar'), 5)

什么容易阅读?

如果您需要将数据传递给 2 个差异模板,您为一个数据存储 2 或 3 个修改?

如果是这样的:

padLeft(capitalize(title), 10)


padRight(upper(title), 5)

我是抽象的情况,但是如果它在一两个模板中使用呢? 您需要存储 10 个或 100 个对象的数据吗? 增加内存使用量? 是的,我们可以使用辅助方法并在模板中使用它,但是对于远离 javascript 的 _“对于模板设计者”_ 来说,最好使用类似title | padLeft 10它应该被翻译成函数调用,它简单实用。

想想 diff 的人,开发人员可以轻松地以 diff 的方式做到这一点,但其他人希望做到简单。

我再说一遍,模板中过多的逻辑是一种反模式。 您应该学习 Javascript,而不是必须学习特定的 DSL(过滤器)。

@thelinuxlich只需使用 JSX,我们就可以通过 2-way binding 和其他一些东西获得 React。

但是有了 Vue,我们得到了,那些不懂 javascript,但使用 google 的人可以做一些事情,如果你不喜欢管道,就不要使用它。 我们可以添加类似的东西

Vue.config.pipeFuncCall = true

你可以打开\关闭它,但对某些人来说很容易。

_我再说一遍,Vue 不仅是 JS 开发者可以使用,它是 Vue 最强大的一面。_

标准的通用过滤器需要,但最好放在单独的库中,以便将其添加到 vue 和使用中。

或者您希望 Vue 类似于 ASM 并且只有优秀的开发人员才能使用它?

伙计们,我认为 Vue 核心团队做出的决定已经得到了很好的解释。 我们能不能一次又一次地重复同样的事情,只用一些新的、有价值的东西(如果有的话)来评论吗?

如果它是 Vue 核心原则的一部分,对非 JS 开发人员来说更容易,即使它伤害了语言原则,那么我会同意你的观点,但可能并非如此。

正如我之前所说,我对不推荐使用的过滤器基本没问题,为了方便起见,我肯定会想念它们,但我非常确定可以将非常相似的过滤器系统作为插件引入。

我之前已经给出了一个概念证明示例,它可以用于计算道具以及内联

<ul>
    <li v-for="item in f(items).filterBy(foo).orderBy(bar).limitBy(5).apply()">
        {{ item.foo }}
    </li>
</ul>

另一方面,如果有人想要管道,我相信它可以做到,就像这样

<ul>
    <li v-for="item in p(items, 'filterBy foo | orderBy bar | limitBy 5')">
        {{ item.foo }}
    </li>
</ul>

或者,如果有一个钩子允许插件解析表达式,并按照他们想要的方式处理它们,这也可能是一种可能的方式,但这完全取决于实现的复杂程度,以及它会产生什么影响关于框架(性能/大小),以及@yyx990803是否真的想朝这个方向发展!

我觉得,如果我们有优雅的替代品,易于使用(插件或核心中的东西),我们会很快适应它。

@rigor789用于过滤数组并对其进行排序等,更好地使用计算,它非常干净。 但我认为以差异格式显示数据的问题:

如果我们有字段 created_at 并且需要在模板中将其呈现为 dd.mm.YYYY 或在链接中

<a href="dd">dd</a>.<a href="mm">mm</a>.<a href="YYYY">YYYY</a>

对于这个过滤器现在使用得很好,我们可以从 2.x 中获得什么替代方案?

暂时只用

 {{ date(created_at, 'dd') }}

并定义日期方法,但它会使模板变脏,如果存储额外的 3 个字段会消耗内存,如果存储 100-200 个对象会变得很重。

这是最终决定:

  1. 将支持过滤器,但仅在文本插值内。 这将它们限制为文本格式化目的,同时将其他逻辑强制到 JavaScript 领域。
  2. Vue 2.0 将没有内置过滤器。 如果需要,社区可以创建自己的过滤器包。
  3. 过滤器语法将更改为对参数使用函数调用语法,而不是使用空格分隔。 这使它与 JavaScript 和其他流行的模板语言(Jinja2、swig、twig...)更加内联:

html {{ date | formatDate('YY-MM-DD') }}

感谢您收听埃文。 这就是 Vue 的伟大之处。 它有一个伟大的领袖。 :微笑:

斯科特

@yyx990803 & @chrisvfritz

在这个讨论中似乎隐藏的一件事是双向过滤器。 双向过滤器是最难与其他提议的解决方案一起复制的过滤器。

  1. 考虑一下我在那个论坛帖子中发布的这个简单示例。 为此使用计算属性将有两个主要缺点:

    1. 您必须为每个值创建一个新的计算属性,从而产生大量样板代码。

    2. 更糟糕的是,计算属性甚至不能嵌套。 如果你有一个更复杂的对象图,你所有的计算属性都必须在顶层。 您最终会得到冗长、冗长的属性名称,需要更多的认知超载来不断跟踪哪些计算属性跟踪哪些嵌套值。

将此用例视为“微不足道”或“不太复杂”会适得其反。 我在中型和大型应用程序中都使用过它。 它创造了奇迹! 演示一定很简单,但技术很可靠。

  1. 在处理v-for中的数组时,这会进一步混淆,例如在这个例子中(同样,故意简单)。 遍历一个数组,你会发现在计算属性中没有资源。 解决此问题的唯一方法是为数组中的每个项目设置一个单独的组件,从而添加更多样板文件。

将此示例与过滤器进行比较:

``` js
从“某些货币过滤器”导入货币;
从“产品存根”导入产品;

新的 Vue({
el: 文档.body,
数据:{产品},
过滤器:{货币},
});
```

对于没有过滤器的人:

``` js
从“某些货币过滤器”导入货币;
从“产品存根”导入产品;

新的 Vue({
el: 文档.body,
数据:{产品},
组件: {
产品: {
道具:['产品'],
计算:{
价格: {
得到() {
return currency.read(this.product.price);
},
设定值) {
this.product.price = currency.write(value)
}
},
运输: {
得到() {
return currency.read(this.product.shipping);
},
设定值) {
this.product.shipping = currency.write(value)
}
},
处理:{
得到() {
return currency.read(this.product.handling);
},
设定值) {
this.product.handling = currency.write(value)
}
},
折扣: {
得到() {
return currency.read(this.product.discount);
},
设定值) {
this.product.discount = currency.write(value)
}
}
}
}
}
});
```

我知道我想写以上哪一个。

(这可以通过创建计算属性工厂来稍微清理一下,但重点仍然是这些比需要的要冗长得多)


由于核心团队似乎坚决反对过滤管道语法,是否可以为v-model指令引入filter参数?

使用filter参数,我们将能够保留上面 JS 的第一个优雅版本,并简单地重写模板以使用参数而不是魔术管道语法:

<tr v-for="product in products">
  <td><input type="text" filter="currency" v-model="product.price"></td>
  <td><input type="text" filter="currency" v-model="product.shipping"></td>
  <td><input type="text" filter="currency" v-model="product.handling"></td>
  <td><input type="text" filter="currency" v-model="product.discount"></td>
</tr>

这将在没有魔法语法的同时保持在没有太多样板的情况下轻松地来回转换输入的能力之间取得适当的平衡。

感谢您的考虑。

我已经重写了您的示例,将您的过滤器合并为自定义指令: jsfiddle
虽然不像过滤器那么简洁,但它并没有我想象的那么痛苦。 我并没有花太多时间将我们所有人都可以使用的东西拼凑在一起。

@Nirazul之前已提议为每个过滤器创建专用指令。 需要创建一个新指令来为您在应用程序中使用的每种过滤器重新实现所有v-model功能,这简直是荒谬的。

此外,您的指令甚至不像过滤器那样完全起作用; 更改值后模糊字段不会重新格式化它。 此外, v-model的作用比您在该指令中所做的要多。

该指令显然可以通过更多功能和修复进行修改,但重点仍然存在:这些都是在一些应该非常简单的开箱即用的东西之上的创可贴。

我没有在这个线程中看到任何提到自定义指令的提议。 你能指点我这个评论吗?

你可以想象,我还没有编写和测试它供你在你的应用程序中使用。 我只是想表明,现在有什么可能作为替代方案。 如果这很容易实现,那么插件可能还有空间使该过程更加自动化。
很明显,这个快速编写的指令缺乏 v-model 的全部功能。 也许一个自定义过滤器指令与参数和/或修饰符组合就足以替换过滤器。

让我们保持建设性,因为我已经尝试过解决您的问题。 抨击解决方案总是比做出贡献和前进更容易。

@JosephSilber你需要冷静一下。 “荒谬”是一个强烈的词。

嗨,是通过减少模板混乱来删除过滤器还是严重影响
2.0的技术实现? 如果是以前的视觉效果问题,让
像现在一样过滤(但使用新的 javascript 表单)
但仅限于每个表达式一个,例如 v-for="i of list | orderBy('key')", (不超过一个管道符号)
这可以使 2.0 中的过滤器处理更简单、更可预测并且视觉上最不混乱。
由于将对 {{}} 进行过滤器解析,因此在其他表达式中允许它是有意义的。
这将适应所有现有的用例/功能(如双向过滤,v-for 中的项目)。
所有者可以轻松地将多个过滤器的任何现有用法合并/升级为一个。

@tomsmithgroup您的建议(以及更多)已决定在 2.0 中保持支持。

@yyx990803@chrisvfritz很想听听您对双向过滤器的看法。

@JosephSilber因此,对于您提到的计算属性工厂,甚至没有太多样板:

import currenciesFactory from 'some-computed-currencies-factory'
import products from 'products-stub'

new Vue({
  el: 'body',
  data: { products },
  components: {
    product: {
      props: ['product'],
      computed: currenciesFactory(['price', 'shipping', 'handling', 'discount'])
    }
  }
})

尽管就个人而言,我不会为这个示例创建工厂,因为这些属性中的每一个实际上都是单独的关注点,现在只有_appear_相同。 当您删除过滤器时,一个组件的复杂程度变得更加明显。 这就是你所看到的样板。

这也是组件存在的一个重要原因。 将复杂性划分为可管理的关注点。 当我查看一个组件时,它所做的一切都需要轻松融入我的工作记忆中,否则开发会变得更慢且更容易出错。 隐藏过滤器语法背后的复杂性并不能消除这种复杂性。

为了证明这一点,让我们看看当问题满足现实世界不断变化的要求时会发生什么:假设您决定不应允许折扣大于价格 + 运输 + 处理。 或处理不应超过 X 量。 或者折扣字段应该是百分比,而不是货币。 或者,如果总额超过一定金额,则应自动应用最低折扣。

您可能想通过额外的选项和条件逻辑使过滤器更复杂。 当您更新过滤器的 API 和内部逻辑时,您现在必须考虑您的更改可能如何影响使用过滤器的其他任何东西 - 甚至可能在当前组件之外,如果这是一个共享过滤器。 所以现在你的情况是,对你的应用程序进行更改开始让人望而生畏。 这一切都是因为共享的两个过滤器允许您将内部组件状态委托给组件外部,违反了组件边界,增加了耦合,并隐藏了您每次处理组件时仍需要考虑的复杂性。

通过使用单独定义的计算属性或绑定道具将事物分解为多个单独的不太复杂的组件,您通常会更新一行以适应不断变化的需求。 没有额外的选项或条件。 无需重构来满足缩放复杂性。 您不必考虑组件之外的任何事情 _或者甚至是单个属性之外的任何事情。 您的应用程序从一开始就很容易思考和更新。

我认为在这种情况下,过滤器最初之所以诱人,是因为它们是一种易于获得的复制治疗方法。 但是当它是偶然的时,重复并不是样板(即代码恰好是相同的,在现实世界的问题不可避免地开始出现之前)。

我不能说它比 Sandi Metz 更好:

重复比错误的抽象要便宜得多

@chrisvfritz过滤器与业务需求完全无关。 过滤器只是格式化数据。 而已。 他们不以任何方式、形状或形式操纵它。 filter="currency"在概念上与number参数相同。 业务需求显然不应该在过滤器中处理。

假设您决定折扣不应大于价格+运费+手续费。 或处理不应超过 X 量。

然后,您将使用一些适当的验证模块,例如vue-validator 。 无论如何,货币过滤器将保持不变,仅显示基础价值。

折扣字段应该是百分比,而不是货币。

那么显然它的类型不再是货币。 与当用户名要求发生变化时将type="text"换成type="email"没有什么不同。 甚至当字段不再是数字时删除number参数。

如果总额超过一定金额,则应自动应用最低折扣。

同样,将应用最小值,但货币过滤器将保持不变。 您仍然希望将其显示为货币。

当您更新过滤器的 API 和内部逻辑时,您现在必须考虑您的更改可能会如何影响使用过滤器的任何其他内容 [...] 双过滤器允许您将内部组件状态委托给组件外部

不。您_从不_将任何逻辑或状态放入过滤器本身。 过滤器是严格用于格式化值的幂等函数。 理想情况下,它甚至不应该在 VM 的上下文中执行; 它应该没有this可以从中提取其他数据。

重复比错误的抽象要便宜得多

...当,正如你所说,你正在抽象现在恰好是相同的代码。 另一方面,过滤器是格式化值的简单幂等函数。 它们根本不是抽象的。


tl; dr过滤器不是抽象的,它们不能代替明确的业务需求。 过滤器从来没有任何内部逻辑,也不应该。 它们在概念上类似于 HTML 的type属性和v-modelnumber参数。

双向过滤器当然是一种抽象。 v-model上的双向过滤器的当前行为隐藏了很多魔法 - 特别是它允许输入的 DOM 值与底层模型暂时不同步,并且仅在您“同步”它们时模糊领域。 顺便说一句@JosephSilber这种行为是根据您的要求专门实施的,所以我可以理解您为什么对此如此强烈。

但是,我看到的双向过滤器最大的问题是底层逻辑是一个黑盒子,用户除了提出功能请求之外没有其他方法可以进一步定制它。 对我来说,更好的选择是提供适当的构建块来自己实现这种行为。 让我向您展示如何在 2.0 中实现这一点:

https://jsfiddle.net/yyx990803/5bnu6xb6/

这里我们有一个基本的CustomInput组件,它实现了当前双向过滤器的“out-of-sync-until-blur”行为。 由于 2.0 的变化,您可以直接在自定义组件上使用v-model ,只要该组件接受value prop 并 $emit input事件即可。 此外,它还对change事件的值进行格式化,这在目前的双向过滤器中是不可能的。 您可以进一步调整此组件以获得您想要的任何所需行为,而不受框架如何实现双向过滤器的约束。

基本组件不实现解析/格式化逻辑 - 您使用parseformat方法对其进行扩展,以获得针对特定用例定制的自定义输入组件。 在这种情况下,一个CurrencyInput组件。

基础组件比双向过滤器更复杂,因为我们现在自己实现了之前的魔法行为。 但是,您只需要定义一次此组件。 作为回报,您可以完全控制它的行为方式,以防您以后想更改它。 我相信这是一个值得的权衡。

这是我们应该如何更多地考虑组件的示例,因为它是可重用性的统一抽象,可为您提供最大的控制权。 另请参阅 2.0 select2 示例- 以前在 1.0 中,这是作为指令实现的,但现在它是具有相同v-model接口的组件。

对我来说,更好的选择是提供适当的构建块来自己实现这种行为。

这很棒,而且绝对是 Vue 所需要的,但是我很想读这个

对我来说,更好的选择是为从 Vue 开始提供适当的构建块,并自己使用新的过滤行为扩展 Vue。

换句话说,货币输入组件和许多其他默认过滤组件不能成为 Vue 的一部分吗? 因为,每个人都会在某个时候使用货币,对吧? 为什么要让其他人一次又一次地做同样的工作? 货币格式足够标准,使其成为 Vue 自己的过滤组件工具包的一部分,它们也是其他人学习创建自己的过滤组件的一个很好的基本示例。

而且.....示例中只缺少一个完成的货币输入组件,那就是 i18n 功能,我相信 Vue 也应该包含它。 货币数字格式应根据个人(查看者)选择的区域设置而改变。 我的意思是语言环境数据,即 . “DE_de”用于格式化货币和其他数字,如本区域设置资源管理器中所示(源于标准)。 将其添加到 Vue 中,您就可以在 Vue 中内置一个很棒的货币/数字格式化组件系统,使用 Vue 的 1000 名其他开发人员不需要自己创建,而是可以在他们获得 Vue 时立即使用. 这使得 Vue 成为一个强大的模板系统!

如果使用这个“i18n 格式化组件”不能像 1.0 那样以可链接方式用作过滤器,它应该是可插入的。 那也很好。 这就是 Aurelia 正在做的事情这也是 Twig 对其扩展所做的事情。 货币输入组件仍然可以是<currency-input>

这个 i18n 和其他标准模板过滤器真的需要成为其他人不需要不断复制的东西,如果他们不需要的话。 如果你教我怎么做这样的插件,我什至会为你做 i18n 插件。 我对这个整体很感兴趣!:smile:

斯科特

因为,每个人都会在某个时候使用货币,对吧?

不是真的,不。 一方面,我从来没有真正使用过它 :) 这同样适用于所有其他内置过滤器——其中一些对我们中的一些人有用,而另一些则无用。 当我们讨论这个话题时,大多数时候我想使用内置过滤器,但我最终还是编写了自己的版本,渲染了内置版本的死代码。

一个 i18n 功能,我相信 Vue 也应该包含它。

这又是非常值得商榷的。 全面的 i18n 支持可能非常复杂,而且 IMO 不属于 Vue,尤其是当大多数用户无论如何都不需要它时。

现在,我想提出这一点:每次我们尝试在 Vue 和另一个模板/框架之间进行比较时,都需要牢记一件关键的事情:与 Django/Laravel/Twig 不同,Vue 本质上是一个客户端库,因此需要尽可能的轻量级。 保持它足够简单——当然同时保留所有 _core_ 特性——而不是仅仅为了所谓的“有用”或“优雅”而添加“特性”和“实用程序”会更有意义。 如果您想要核心功能以外的任何东西,更首选的方法是使用插件甚至开发自己的插件。 以这个为例:对于一个常见的 SPA,i18n/currency 是否比路由器或状态管理器更重要? 我不这么认为。 然而,vue-router 和 vuex 不属于 Vue,但有自己的存储库。 换句话说, Vue 是渐进的

如果你教我怎么做这样的插件,我什至会为你做 i18n 插件。 我对这个整体很感兴趣!

我相信这是一种更明智的方法,感谢您的关注:)

如果在某些领域需要使用 i18n)))我想我可以进入代码并手动更改一些东西的一些名称,为了美观。
例如:就在几个小时前,我用了 butstrap.datepikker - 我不连接,i18n 尽管有这样的可能性。 快60秒。 “手动”替换了星期和月份的名称,一切都 - 好的! ))

@phanan - 你的论点是我提到“插件”的原因。 我同意,不是每个人都想要货币或 i18n 功能,而那些不希望他们的应用程序轻便的人,但作为一个模板系统,我相信(这在很大程度上是我个人的看法)Vue 也应该有这样的标准功能可用也。 更重要的是,我担心的是,不应该每个人都必须重新发明 i18n 或货币过滤器组件轮子。 换句话说,就像 Vue-Router 和 Vuex 可以添加到 Vue 一样,大量标准过滤器(如货币和 i18n)也可以。

哦,有趣的是,Angular 似乎内置了 i18n。

https://docs.angularjs.org/guide/i18n

Angular 支持 i18n/l10n 的日期、数字和货币过滤器。

Ember 和 React 似乎走的是“让开发世界自己做”的路线。
有趣的视频。
https://www.youtube.com/watch?v=Sla-DkvmIHY

也许 Vue 只需要与 FormatJS 集成? Vue国际? :微笑:

编辑:不可能那么简单,不是吗? https://github.com/learningequality/vue-intl/blob/master/index.js

斯科特

Angular 似乎内置了 i18n。

Angular 还附带 ng-router,据我所知,ng-community 避开了 ng-router,转而使用 ui-router。

现在,如果 Angular 团队将 ng-router 替换为 ui-router,它将导致重大更改和痛苦。

如果他们试图改进 ng-router,他们就是在浪费时间,因为已经存在更好的解决方案(ui-router)。

如果 Vue 开始在其核心中支持 i18n、货币等,那么同样的情况也会发生在 vue 上。

我确实发现内置过滤器很方便,但在这件事上我同意 vuejs 团队的观点。

然后我们都同意过滤器不在 Vue 核心中。 实际上,我也是组件化的粉丝。 但是,Vue 不能也提供过滤器作为核心插件吗? 喜欢 Vuex 和 Vue-Router?

斯科特

但是,Vue 不能也提供过滤器作为核心插件吗? 喜欢 Vuex 和 Vue-Router?

这正是@blake-newman 之前分享的内容。

嗨:最后的决定页面表明只允许过滤文本
显示 {{}}(v-文本)
不适用于其他表达式,例如 v-for="item of list | sortBy"
还是我误会了?
我的意思是继续使用 1.0 中的过滤器,但只限制一个过滤器
每个表达式

2016 年 5 月 1 日星期日晚上 10:24,Phan An [email protected]写道:

@tomsmithgroup https://github.com/tomsmithgroup你的建议
(不仅如此)已经决定
https://github.com/vuejs/vue/issues/2756#issuecomment -215868244 到
在 2.0 中仍然受支持。


你收到这个是因为你被提到了。
直接回复此邮件或在 GitHub 上查看
https://github.com/vuejs/vue/issues/2756#issuecomment -216093937

@yyx990803我可以从您的回复中得出结论,2.0 将不支持双向过滤器吗?

@fnlctrl这是正确的。 只需构建您自己的组件。

我会跑题:那些双向过滤器在生产中真的有用吗?
我的意思是,让用户在输入中输入任何内容然后在它模糊后重新格式化它真的可以吗?
我的业务团队总是要求我们的输入像这样:你不能输入任何错误。 所以即使现在使用Vue我们使用 jquery.inputmask 来达到这个目的,因为即时双向更改已被弃用(我真的很想念那个......)
我的意思是,这些双向过滤器真的有问题还是人们只是想多了? :)

@fullfs为方便起见,我们的生产应用程序(大量<input> s)中广泛使用了双向过滤器,但正如我现在所看到的,为什么要实时过滤值而不是在它们之前过滤一次发布到服务器? 重构代码需要一些时间,但我想我不会错过它们 :D

如果您希望对 UI 进行乐观更新(恕我直言,这是当今的常态,尤其是对于移动设备),您需要在输入时实际正确格式化输入。

斯科特

2 路过滤器在 vue 中非常好用。 您始终可以构建自己的定制组件,有或没有可用的过滤器,但这需要时间。 该库应该提供灵活性,但也应该提供一种更快、更方便的方式来做事。 包含 2-way 过滤器不会阻止人们在必要时构建自己的组件,但是当现有功能满足需求时(大多数情况下)会允许更快的开发。 它始终是 API 表面和便利性之间的折衷。 必须找到平衡点,而 Vue 已经有了一个很好的平衡点。 摆脱过滤器似乎是从正确的平衡点倒退了一步。 库变得更小,但使用它的每个项目的代码库和样板都变得更大。

如果过滤器真的要被弃用,也许最好提供一种替代方法,能够以一种简单的方式为 v-model 指令指定解析器和格式化程序。 使用过滤器可以编写@yyx990803提供的示例的这一部分:

const CurrencyInput = CustomInput.extend({
  methods: {
    parse(val) {
      var number = +val.replace(/[^\d.]/g, '')
      return isNaN(number) ? 0 : number
    },
    format(val) {
      return '$' + Number(val).toFixed(2)
    }
  }
})

如果没有 2 路过滤器,也必须编写

const CustomInput = Vue.extend({
  template: `
    <input type="text"
      @focus="onFocus"
      @blur="onBlur"
      @input="onInput"
      @change="setDisplayValue">
  `,
  props: ['value'],
  watch: {
    value() {
      if (!this.focused) {
        this.setDisplayValue()
      }
    }
  },
  ready() {
    this.setDisplayValue()
  },
  methods: {
    onInput() {
      this.$emit('input', {
        target: {
          value: this.parse(this.$el.value)
        }
      })
    },
    onFocus() {
      this.focused = true
    },
    onBlur() {
      this.focused = false
      this.setDisplayValue()
    },
    setDisplayValue() {
      this.$el.value = this.format(this.value)
    }
  }
})

因此,灵活性更高,但相同结果的代码也更多。

@aristidesfl - 过滤器没有被弃用。 我们部分地赢得了这场战斗。 哈哈! 它们将仅限于用于文本插值。 见这里: https :

斯科特

谢谢@smolinari 。 我特别指的是2路过滤器。

请回来! 我们需要它,我同意你所说的一切。 但这很容易,我们是懒惰的用户,我们只想要一个懒惰、简单的方法。 就像保命一样。

可能应该有一种方法来添加自定义 v-model 修饰符(http://rc.vuejs.org/guide/forms.html#Modifiers)

它们像双向过滤器一样工作。

@ecmel同意。 这是要走的路。

然后打开一个功能请求问题:)

@ecmel一个类似的想法,虽然被描述为类型修饰符,但在这里进行了讨论。

@rpkilby该讨论也已结束,也许我们应该为自定义 v-model 修改器打开一个新的讨论。

不再能够这样做:

<span :title="item.Modified | date('dd-mmmm-yyyy H:MM:ss')">{{item.Modified | date('dd-mmmm-yyyy')}}</span>

将过滤器限制为{{ }}似乎很奇怪,很多时候你想在属性绑定中使用过滤器(不传递道具),我们不能再在属性中使用{{ }}

将过滤器限制为{{ }}似乎很奇怪,很多时候您想在属性绑定中使用过滤器(不传递道具),我们不能再在属性中使用{{ }}

它们被删除是因为它们可以很容易地被计算属性和方法替换,而它们本身具有更有限的 API,不可能缓存结果。

所以:

  • 少一个 API
  • 在模板和 JS 代码中使用相同的方法,无需在应用程序代码中重复使用过滤器行为。
  • 计算的道具可以被缓存
  • 更灵活,因为它只是 JS

前面的伪代码:

<!-- method, suitable in v-if  -->
<span :title=" date(item.Modified, 'dd-mmmm-yyyy H:MM:ss')>

<!-- computed prop, more suitable for single values -->
<span :title="formattedModified">
<script>
computed: {
  formattedModified () { return date(this.item.Modified, 'dd-mmmm-yyyy H:MM:ss') }
}
</script>

对不起,我只是“新人”。
但是从 Angular 1 开始没有过滤器感觉真的很奇怪和违反直觉,为什么让每个开发人员开发自己的过滤器集并自己设置计算条目等比内置它更好?
现在被认为是通过元素中的对象过滤非常大的数组的最佳实践。 使用 Angular,这只是一行代码。 可以为搜索输入过滤一个数组,它会做所有的魔法,这应该是一个框架的功能。

现在被认为是过滤一个非常大的数组的最佳实践

什么是真正的大数组? 从理论上讲,计算属性对过滤也有好处。

https://jsfiddle.net/sat25z51/3/

为什么让每个开发人员开发自己的一组过滤器并自己设置计算条目等比内置它更好?

我以前也是这么想的(以及为什么我开始这个话题),但是因为我已经知道自己创建这些过滤器基本上是小菜一碟,而且每个开发人员可能想要的东西太多了作为一个过滤器(或计算属性),我开始意识到没有内置过滤器并不是什么大不了的事。

斯科特

在我的情况下,它等于 Firebase 数据库提供的 json 中 > 10.000 行。
我明白你为什么会这样想,并决定放弃该功能,但这对开发人员来说是一个额外的麻烦。

我将小提琴分叉以符合我的数据结构:
https://jsfiddle.net/nw5yhLwv/
所以我需要在我的对象中手动编码搜索字符串?

我不明白你的问题。 对不起。 小提琴看起来像我发布的那个。

斯科特

计算与过滤器

why not both

过滤器可能对性能不利,因为它们是为每个渲染计算的(就像方法一样),并且计算的属性很容易做到,并且只在必要时重新计算,否则结果会被缓存,这意味着 Vue 可以飞。

哦。 我们两者都有。 😄

斯科特

嘿,我做了一些摆弄,现在我明白了,这是一个很棒的概念! 😄

我现在将锁定这个线程,因为关于这个问题的讨论已经结束了——Vue 2.0 已经发布了几个月,关于过滤器下降的批评已经基本平息。

此线程中的进一步讨论没有成效。 如果您认为需要讨论的主题有新的角度,请打开一个新问题。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

paulpflug picture paulpflug  ·  3评论

gkiely picture gkiely  ·  3评论

julianxhokaxhiu picture julianxhokaxhiu  ·  3评论

robertleeplummerjr picture robertleeplummerjr  ·  3评论

loki0609 picture loki0609  ·  3评论