vuejs / vue

This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
http://v2.vuejs.org
MIT License
207.66k stars 33.66k forks source link

[Suggestion] Vue 2.0 - Bring back filters please #2756

Closed smolinari closed 8 years ago

smolinari commented 8 years ago

Hi,

There was a hot discussion in the Gitter chat and there is a nice post on the forum about people missing the filter feature in 2.0 and it actually being a no-go to upgrading for some. This isn't a positive direction for the community it seems.

So, I'd like to put up this suggestion to bring back filters in 2.0, because they are so loved and, I would agree, smart. Here are some of the arguments for filters (gathered from the different discussions and no guarantee for correctness):

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

is simply easy to read. In other words, chaining filters helps make sense of what should actually be expected.

Needless to say, there are probably strong arguments for removing filter from an engineering perspective and why I would suggest this thread be a pros and cons and voting for or against the return of filters.

Scott

agc93 commented 8 years ago

Clarifying a point that originally came from the Gitter chat: debounce is not a filter, and was just another of the 2.0 changes that people weren't thrilled about losing.

Correction courtesy of @JosephSilber : debounce is both a filter and a v-model param.

smolinari commented 8 years ago

Thanks @agc93. I've removed that point.

Scott

posva commented 8 years ago

In the worst case we'll come up with tiny plugins to deal with this. About filters, there's https://www.npmjs.com/package/babel-plugin-pipe-operator The problem is this won't work without babel compilation

nirazul commented 8 years ago

I'm not all too stoked about some of the changes either. For filters, there seems to be an easy alternative by registering global mixins. However I'm not too fond of the idea of polluting all of my components' methods scopes for ultra-simple tasks like pluralize and so forth. I've never used two-way filters, however.

Filters were just convenient and beautiful. The two things that vue always did right (so far).

nilssolanki commented 8 years ago

When I read the post on vue 2.0, I was stoked about all the new possibilities (especially the virtual dom and the server rendering), but I was also surprised and a little sad to that the filters are gone.

They were one of my favorite parts of vue, not only because they were easily usable and chainable, but mainly because they were easily extensible and had a beautiful syntax to use them in the template directly. Especially in combination with v-for loops, they were a perfect match.

Thinking that I'll have to use computed properties to replace the filtering for each and every prop I want, I'm worried that I'll be writing a lot of boilerplate in the future. While mixins might mitigate a part of the problem, I still feel like a part of the elegance and ease of using vue is going to be missing.

azamat-sharapov commented 8 years ago

Everybody who agrees with it, can you please just click thumbs up under description? it's better than spamming 17 thousand people with +1. Even better, come up with some meaningful use cases.

rigor789 commented 8 years ago

I've never used two-way filters, but I would really miss the filters! I can (and sometimes I do) use computed properties, but in some simple cases, it is a convenience that really speeds up the workflow.

Consider this very simple example

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

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

The above is so much easier to write in cases where it's not required to have some more complex filtering.

Now compare it to the following

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

I'm not saying the second one is hard to write, but when you use it in many places, you will start repeating yourself, and it just takes some extra time you could perhaps use on some other, more useful features!

Either way I will stay a happy Vue user, just sharing my opinion on the filters being deprecated!

OEvgeny commented 8 years ago

Filters are reusable. I can create function to format my data once, register it as a filter and just use from all instances. How can I do it in 2.0?

azamat-sharapov commented 8 years ago

How can I do it in 2.0?

  • Mixin
  • Separate module with method
  • Separate module with computed prop function
JosephSilber commented 8 years ago

I just left a comment on the announcement thread, so instead of duplicating it all here I'll simply link to it:

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

yyx990803 commented 8 years ago

I totally understand the feeling of something super convenient being taken away from you. But first please take a moment to read @chrisvfritz 's comment in the forum thread above. To make discussion easier I'm just copy pasting it here:


@theotherzach Thanks for your passion for Vue! I'd like to explain the deprecation a bit better, but first, I should introduce myself. I'm a member of the Vue core team, I use Vue all the time for my freelance UI and data visualization work, and I'm also an educator that teaches people to use Vue and Rails, among other web technologies. I run a code school, so I help people learn to use these tools (and use them together) almost every day.

I was also one of the big proponents for removing filters in Vue 2.0.

The problem with filters for beginners to Vue

A big part of the reason I was in favor of deprecating filters was actually for beginners. When working with students, this is a conversation that's come up more than once:

One of the big things that trips up beginners is exceptions. Filters are just functions, except they require a special syntax and can't be used everywhere. And they use a pipe syntax that's different from the pipe syntax that may be integrated into ES7, meaning it won't be long until people have two very similar operators to do something very similar, but they're not quite the same. And only one of them is actually JavaScript.

Util libraries are useful, but Vue isn't one

In the case of filterBy, transforms for strings and numbers, and other specific filters, yes, they are useful in applications where they come up. Util libraries in general are useful. And there are dozens of great util libraries to choose from, but Vue isn't a utility library. And frankly, none of the utilities we've offered have been best-in-class.

Handling currencies, dates, or even filtering arrays - these aren't our focus. Many apps don't require them and most of the apps that I've worked on that do face these problems require a more robust solution than Vue currently offers (or could offer without introducing significant bloat and wheel reinvention).

In my apps, Accounting.js has handled currency superbly, Moment.js (as you mentioned) handles dates and times, pluralize doesn't handle many pluralizations well, so a custom computed value is often more desirable, and json is little more than JSON.stringify.

The advantages of computed properties

Using computed properties in place of filters also offers the advantage that the processed value can be easily reused in a DRY way anywhere in the component. I find myself having to do this in my apps all the time. The computed property also moves more implementation details out of the template, leaving only a clean description of what the component does. And an advantage over globally defined filters is that one need only look at the function for that computer value to see and tweak exactly how it's working. On arrays, chaining JavaScript's map and filter methods even provides the same linear list of processing that pipes do, but in an even more declarative and easily manipulated way.

The usefulness of globally defined whatever

If you need to define a function or anything else that you want accessible in all of your components, Vue.prototype.whateverIWant = mySuperCoolFunction is a great way to do it. Personally, I've never wanted to do it. I've always preferred to put a helper method into a module and import that module where I need it. But it's still important to note that registering globals - of any kind - isn't made any harder.

The case of the debounce directive

I have to say, I'm actually with you on this one! I recently looked over all my Vue projects and every single one that had an input somewhere also used debounce. In fact, only one of my past applications didn't use debounce. While technically a utility - lodash and many other robust projects offer debounce solutions - this problem is pretty universal to UI development, for any kind of app. Writing your own debounce function is also non-trivial enough that I'd probably want to use lodash's implementation for nearly every project.

There remains some internal debate over this, so we'll see where it goes. But yes, for me personally and it seems also some others, removing debounce removes most of the convenience offered by v-model.

Again, thanks for your passion!

Seriously, we love how much you love Vue and are really glad you're voicing your concerns - and especially in such a kind and respectful way! We're hearing you. The core team is all designers, front-end developers, and data visualization specialists. We all use Vue for our own work, which is pretty diverse, so we're definitely dedicated to pushing out dogfood we'll want to eat ourselves. :-)

raywill commented 8 years ago

Talk is cheap, let's code to see if without filter, how we apply filterBy and reverse:

write global pure filter functions in a seperate file for code reuse

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

use filters in App.vue template

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

see the result here http://raywill.github.io/vuefilter/


If filter used, following vue code would do the same:

<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'],
    }
  },
}

Apparently, with filter supported we could write less trivial code.
Personally I prefer the vue 1.0 way, which makes coding more enjoyable.

yyx990803 commented 8 years ago

As for the boilerplate concerns - there are several ways to deal with it.

1. Explicitly import/export

Like @raywill demonstrated above. It's a bit more verbose, but the benefits is that:

  1. You don't have to lookup Vue's filter documentation to understand how it works. It's super explicit where the functions are coming from and how they are implemented.
  2. The functions themselves are just JavaScript. You can alter/compose them to fit special uses cases unlike built-in filters which you cannot touch.
  3. You can import and programmatically reuse these functions in methods, computed properties and anywhere you write JavaScript.

2. Attach them to Vue.prototype

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

3. Go functional (for advanced users)

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

Where the helper functions look like:

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

Again, a very important design consideration is that built-in filters can be useful, but they lack the flexibility of pure JavaScript. When a built-in function doesn't suit your needs, you either end up re-implementing something similar (and shipping both in your final code, where the built-in becomes useless, dead code), or have to wait for Vue to update them and release a new version.

rigor789 commented 8 years ago

@yyx990803 I like the prototype approach, but how about cases where you need multiple filters?

It's pretty common to use orderBy along filterBy

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

How about cases where you would add a limitBy too?

<ul v-for="word in filters.limitBy(filters.orderBy(filters.filterBy(words, userInput), column, -1), limit)">
    <li>{{word}}</li>
 </ul>
Does this approach make the code less readable?

Yes, at least in my opinion.

I guess we could have combined filters like filterAndOrderBy but that doesn't feel right either.

I'm open to changes, just want to come up with an almost as easy way to handle it!

Also, the benefit of being able to use the filters anywhere is a really good point too.

blake-newman commented 8 years ago

Just to note, the @vuejs/collaborators have been discussing an option to provide a utilities package of the current integrated filters. There is plenty of resources out there that will provide you with utility tools for your code base.

One good thing about removing the core filters, is that you can now customise/implement them yourself. Which gives you lots more flexibility.

blake-newman commented 8 years ago

@rigor789 template expressions should be as simple as possible. Ideally just like <div v-for="filteredData"> </div>. This can be a computed prop, that can hold the logic for creating the filtered data. This is way more readable, and is better than something like:

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

It is much more reusable to assign as a computed property, and can even be passed down to child components. What if you wanted to use the filtered data in two places? It's easier, simpler, reliable and more readable for templates to have simple expressions, compared to having chained filters in expressions.

JosephSilber commented 8 years ago

For anyone following along, I answered @chrisvfritz here: http://forum.vuejs.org/topic/3891/announcing-vue-js-2-0-public-preview/17

theotherzach commented 8 years ago

The following solves my use case of a very few globally available pure view helper functions. I withdraw my filter removal concerns. Burn 'em! πŸ”₯ Congratulations to @chrisvfritz and @yyx990803 for changing somebody's mind (mine) on the Internet!

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

I totally agree with @yyx990803 , remove filters and stick to plain JS functions.

rigor789 commented 8 years ago

@blake-newman That's a very good point, I'm mostly convinced at this point, and thinking about readibility, I think something like this can be achieved

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

Here is a quick jsfiddle of the concept

JosephSilber commented 8 years ago

One good thing about removing the core filters, is that you can now customise/implement them yourself. Which gives you lots more flexibility.

You were always able to customize/implement them yourself.

Vue isn't a utility library. And frankly, none of the utilities we've offered have been best-in-class.

What we're concerned about is removing the filter functionality in the templates. Removing the built-in filters does make a lot of sense – they can be easily recreated by proxying them to underscore/other util libraries. Then, someone could even release a single plugin that recreates all the current built-in filters.

Using computed properties in place of filters also offers the advantage that the processed value can be easily reused in a DRY way anywhere in the component.

Of course you can use computed properties if you have to reuse it elsewhere. But if you don't, a filter is still much more convenient.


There are some other points I posted in that link I shared above.

young-steveo commented 8 years ago

Why not support a syntax for filters that operates like the ES7 proposed syntax? That would allow people to keep using their beloved filters, and bring it in line with what the future may hold. Eventually when we have ES7 pipes, you can switch the internal implementation without changing the api.

thelinuxlich commented 8 years ago

Are ES7 pipes approved or subject to a lot of changes?

rpkilby commented 8 years ago

It's theoretically subject to change, but seems... stable? Status: mindeavor/es-pipeline-operator#33

chrisvfritz commented 8 years ago

@JosephSilber @young-steveo @thelinuxlich I think we're on the same page regarding the value of pipes in general. πŸ˜ƒ One advantage of the new compiler in 2.0 is we can pipe the generated render function code through Babel. This still needs to be further explored, but it's not inconceivable that once |> gains more momentum and a Babel plugin for it is developed, you could happily chain methods with pipes again - everywhere in your app. As a huge fan of LiveScript and other functional languages, I definitely recognize the value!

thelinuxlich commented 8 years ago

this pipeline operator is not even in stage 0

chrisvfritz commented 8 years ago

@thelinuxlich Yes, I believe they're still waiting for a champion on TC39. 😞

yyx990803 commented 8 years ago

@rigor789 that's one of the alternatives I wanted to mention too! The power of JavaScript allows you to achieve expressiveness of your choice, and imo it's better than putting the filtering logic inside templates.

rpkilby commented 8 years ago

@yyx990803 How does Vue perform in the following cases, when one user's name is updated?

<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);
    },
  },
});

It seems like the former would only re-render the one object, while the latter would recompute the entire list?

yyx990803 commented 8 years ago

@rpkilby that doesn't seem to be the equivalent. It'd be more like:

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

Still don't like the idea of using methods as filters (as a gut feeling it just seems wrong, but can't really explain it). Either way you discussed other methods of making filters available, so +1.

JosephSilber commented 8 years ago

Nothing suggested in this thread comes even close to the expressiveness and succinctness of filters. It just doesn't.

And that makes me real sad. Like I said in the forum thread: to me, this removes a big chunk of what makes Vue Vue.

If you're looking for me, you can find me in the corner sobbing audibly 😟

thelinuxlich commented 8 years ago

No way, this change encourages good Javascript coding, deal with it :)

phanan commented 8 years ago

So I've just had a long discussion with @yyx990803, where I – from a user's perspective – suggested to keep the syntax support, because it does feel elegant and natural. My imagination was something like this:

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

I was under the impression that this would approach the best of both worlds.

In the end though, I'm convinced that removing filters as a whole is actually a better thing: like @thelinuxlich just said, it encourages better JavaScript and logic thinking. We don't introduce logic in Laravel's Blade or any other framework's view layer, and we shouldn't in Vue's templates.

That said, @JosephSilber if you look at the other corner, you'll find me there.

Uninen commented 8 years ago

For me filters feel are very beautiful, the syntax is exactly what a filter syntax should look like.

Also one attractive thing about Vue for me is that it comes with (some) batteries included. It would be really sad to lose either of these things -- both which, in my opinion, make Vue stand out.

smolinari commented 8 years ago

Reading through the thread, it seems most of the concern with filters was the fact Vue had default filters, and not really the function itself (or is it? I still am not sure).

I like the filter plug-in thinking from @blake-newman and there should be prebuilt examples. If other people come up with other filters, they should be plug and play. That would be great. I absolutely agree that creating filters is a userland responsibility.

What is still wanted is the pipe and chaining abilities and the globalness of the original filter feature. The concerns about globalness were covered by @yyx990803. How about the chaining with the pipe? It helps a ton in reading the templates and understanding what is to be expected as an output. The pipe and chaining was discussed above. Can it still be done? Why is it a bad thing at all? For the designer, it is gold! The filter is a designer's tool, not the JS programmer's. So, the argument of writing better JS falls off the board, in my book, but I can understand why it would be wanted. But, as a designer, I want to write better code too, and filters allows me to, beautifully. :smile:

Scott

yyx990803 commented 8 years ago

Here's the thing regarding chaining - filters are primarily used for two purposes:

  1. formatting text;
  2. processing an array.

In the case of formatting text, 90% or more of the time only a single utility method is used. Chaining is not really that much of a problem in this case.

As for arrays: I have already pointed out that array processing is in fact logic and is better suited in JavaScript. Having multiple chained array filters may look okay when it's simple, but can get ugly when you use more than 1 arguments for each. It is also encouraging you to put too much logic in your template when you really shouldn't. They are also inflexible (cannot easily retrive the processed value). In comparison, with ES2015 the original example

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

can be written as:

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

It's just JavaScript, it has no magic, no alternative syntax and filter-specific API to learn. And you can access the processed value (which is intelligently cached). You are also free to add sugar on top of this as shown in previous comments. Plus, your template looks cleaner:

<div v-for="filteredThings">

I know this is like a handy thing being taken away, but honestly, the arguments for filters right now sounds to me like just trying to keep the syntax for the syntax's sake. In my opinion, it takes more than just "because it's elegant" to justify a feature - it needs to provide objective value. This was the case for inline-templates, but I don't see it for filters.

smolinari commented 8 years ago

@yyx990803 - Your example exemplifies the issue, I think. Again, I'm not the best JS programmer, but I don't need to be a JS programmer to know filteredThings says nothing about what it really does. To me, that is a bad practice. :smile: The fact the filtering method is global also means I must go searching in docs, the code or decipher the output to find out what the method does. Not really elegant. Right?

So, ok. we could have a method name like `filterByOrderByAndLimit'. What about the arguments?

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

Would that be correct?

If it is, that might be feasible. Still, it doesn't look good.

And, now I want only filterBy and OrderBy. Do I need a separate method to do that too? And then I want to add currency formatting. Another method? The filter chaining in the templates makes manipulating the presentation flexible and very expressive. This concern has yet to be properly addressed with methods (and my lack of knowledge isn't allowing me to understand methods can be better).

Can this be possible?

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

I agree that doing too much logic in a template is something to avoid. But, filter chaining and the ability to simply pop in a filter anywhere in an app's components/ templates is a fantastic concept and there was a reason why you added it to begin with. What was that reason or reasons? If you can name them, then I will bet money they outweigh "but it promotes bad practices" by a mile.

Anything that allows flexibility can be used improperly, just like Vue itself. The main argument for inline-template was it was flexible and allowed Vue to be used in different ways. Filters isn't much different, other than it is Vue internal and doesn't affect how Vue might be used externally. Still, that doesn't devalue its importance. Remember, a lot of people have also said this would be a no-go for them to upgrade. It is that important! :smile:

The new way just needs the same attributes the old way had.

(did I forget anything?)

If it can do all that, then I am sure everyone will be pretty much satisfied. I personally can't see it happening with methods (yet).

Scott

yyx990803 commented 8 years ago

@smolinari

  1. I've clearly stated that you should put less logic in your templates. This is my opinion whether you like it or not. Obviously you are free to disagree, but I can't help you if you want to work against recommended best practice.
  2. Given (1) - I've explained why chaining is not an issue because complex logic should be done in JavaScript.
  3. I've also given examples of how you can add globally available methods.
  4. See @rigor789 's example on a custom chaining syntax similar to what you want.
  5. The goal of the framework is to provide what I believe is the best way to develop front end applications, not to please everyone. So please don't use "I will not upgrade if you don't give me this feature back" - it doesn't work.
azamat-sharapov commented 8 years ago

Why don't you guys try this new alpha release for a week and then come with some really valuable comments (based on your practice)? Maybe try to refactor your existing app and let us know what was impossible, what was improved, what got worse, so we can discuss it better. That would be useful for everybody I think.

smolinari commented 8 years ago

@yyx990803 - I agreed to 1. So we agree. :smile: I just don't agree it being a proper reason for taking out something which had gained so much love.

So, I guess you've decided over time that pragmatic JS is better than pragmatic HTML?

The argument of a no-go for not upgrading is what others have said. I am just trying to communicate and mitigate that.

One last argument from myself. Look at this from the user's user's eyes. Say I have a system like Laravel or some other MVC or MVVM system that incorporates Vue, which also allows the user of that system to build their own components. The filter, as it was, simplifies the learning curve and it allows the users of that system to get a lot done, without touching any JS. I am a fan of Vue, because it did allow non-JS programmers to still get a lot done. This is the same reason why I don't like React and JSX. That combination will have a lot smaller user base over Vue as time goes on. I'll bet money on it.

I also understand that the real flexibility lies in JS. Still, please don't rely solely on JS for the flexibility in Vue. Keep it in mind, not everyone is a killer JS programmer. In fact, most people aren't. The filter was a nice way to get a lot done for those people and it was a nice stepping stone towards further JS manipulation. Filters can't get it done? Go deeper to JS methods.

Ok. Enough from me..... I am done. And, thanks for listening at any rate. Vue is still awesome! :smile:

@azamat-sharapov - good point.

Scott

thelinuxlich commented 8 years ago

Seeing people trying to justify bad practices inside JS makes me sad. Really, you don't need to be a pro, just do the basic homework(or isn't it basic anymore these days?)

prog-rajkamal commented 8 years ago

The problem I have with filters-inside-methods is of semantics.

In oops term, filters are like static functions while methods are non-static function.

Filters convey extremely different semantics than methods. the biggest difference being that filters can not use this, but methods can.

@yyx990803 while using Vue.prototype.filters can work but changing Vue does not look like good practice to me. I would rather advocate creating a separate (global) object which will contain all filters.

yyx990803 commented 8 years ago

It doesn't look like good practice because globals is not good practice. The recommended approach is explicitly importing helper methods. Attaching to prototype is a workaround for those who do not want to explicitly import methods.

As for semantics - filters are a coined concept anyway. In JavaScript you wouldn't invent a different semantics just to uppercase a string - you call a function. And that's what they are, JavaScript functions.

smolinari commented 8 years ago

I am going to make one more comment to try and make my personal point clearer, mainly because of the "trying to justify bad practices inside JS " comment. I am certainly not trying to do that.

I realize Vue is more than just a templating system, but, it is a templating system too and I am afraid it is trying to move away from that role, which I feel it shouldn't. So as a templating engine/system, take the Twig templating engine as a very successful example of what one could expect from a templating system. They have a "For the template designers" section and a "For the developers" section in their docs. As a templating system, Twig is powerful for the template designer too, because it is chock full of default behaviors, including filters. It allows non-developers to do a ton with the template system, without directly knowing PHP. They just have to learn what Twig has to offer and how to use it. I am looking for this in Vue too. I'd like to see a "Vue for template designers" section in the docs too. :smile:

Also, very important is the extensibility of Twig. If something isn't available in the stock version, it can be added. That is when the developer steps in. The nice thing is too, extensions can be shared, which means, it only has to be done once.

The other nice thing about these two levels designer/ developer is, you get a much broader base of users. Much, much broader and this is the same with . And when the behavior defaults aren't enough, that is when they start to learn, willingly, the underlying language. And that is when they learn best practices and the rest.

If you are saying, Vue can't be a template engine without having to learn JS, then I'd say, it is lowering its market value considerably. If you say, you will leave the door open to let others make those tools for the templating engine as plug-ins, great. But, then everybody will be fighting for what should be in the templating system. That is also counterproductive IMHO.

In your student talking about filters example Evan, was it someone learning JS or someone learning a template engine? If it was the latter, I bet the conversation would go differently.

At any rate. I still think Vue is a winning system. I hope my thoughts might make others think differently about Vue's roles in some way. :smile:

Scott

prog-rajkamal commented 8 years ago

@yyx990803 if filters are coined concept, then why were they coined in first place?

I believe its because inside <template> all external variables like $data or abc are converted to this.$data and this.abc and hence plain js functions defined outside the component can't be referenced. Filters were introduced to overcome this limitation.

That limitation still exists ---I am assuming I am right--- to remove the limitation would require devs to explicitly code this.abc for referencing this.abc and access js functions as they would be referenced in js.

But that will be too powerful feature, prone to abuse and migrating old code will be a pain. the current syntax looks way better than that to me.

I agree with you that filters are basically js functions and should be imported to component. I just don't like that they are defined in same place as methods.

YerkoPalma commented 8 years ago

Hi everyone. I read the whole thread and this is what I think.

Having that as a quick summary what I think it could be a good solution until js implement a native pipe operator, would be to have the pipe operator as a plugin and keeping the 2.0 version as it is. So, users can do

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

While we wait for the new feature implementation, it could be included with some warning about coming deprecation or something. I know that anyone could implement that plugin, but I think that would be better if it is provided and keeped by the Vue team, could that be possible?

azamat-sharapov commented 8 years ago

I could be wrong, but I don't think Vue allows plugins mess with it's compiler..

YerkoPalma commented 8 years ago

@azamat-sharapov Of course not. I just didn't think it would mess with Vue compiler :open_mouth:

chrisvfritz commented 8 years ago

@YerkoPalma I absolutely love the pipe operator. I use it obsessively in functional languages and can't wait to have it in JavaScript! But, imagine Vue had never had filters. Would you be requesting that a frontend framework extend JavaScript's syntax? That's the domain of Babel or a compile-to-JS language, not a UI framework. If you prefer to use a language like LiveScript, as I often do, you can. But the problem here isn't with Vue. It's with JavaScript itself and we're not here to fix that.

Additionally, if we're able to pipe the results of the render in 2.0 through Babel as we hope, then you'll even be able to use the non-TC39 tracked plugin if you want - consistently, everywhere in your JavaScript, instead of just in the template. So if you just want a pipe, it's likely you'll be able to have it. And you can have it today in 1.x - just be warned that the pipe you'd be using in your templates is likely to have a different precedence and behavior than the one in your Babel.

@smolinari and others. There are two phrases (and variations thereof) I keep hearing:

Both imply an assumption - that we're not thinking of these groups.

I've mentioned this before, but I guess it needs reiteration. Everyone on the core team is either a designer, frontend developer, or combination of both. We use these tools every day for our own work. We'll be using Vue 2.0 too. Believe me, we are thinking of that. πŸ˜‰

As for beginners, I made a case here, but I guess I'll go into more detail. I'm an educator. And I was a proponent of eliminating filters, thinking of beginners. I've personally taught hundreds of people - maybe even more than a thousand - how to practice web development, usually from scratch. No former coding experience. I've done this with middle schoolers, high schoolers, university students, professional adults, and senior citizens.

From that perspective, I can tell you that while filters can seem like exciting magic at first, they ultimately slow down a student's learning by introducing more complexity for limited convenience. If they had never been in Angular or Vue and this conversation were reversed - we were trying to introduce them in 2.0 - we'd have a hard time explaining why they were needed and when you should use them.

Before there was any talk of a deprecation in 2.0, I had eliminated filters from the curriculum at our code school, because we'd gathered enough evidence that they were doing more harm than good for beginners. We'd rather they gain experience with more versatile Vue features, like methods and computed properties. We even discouraged the use of filters, because they made it easier to pick up bad practices.

Hope that puts these two complaints to bed. We'll see. πŸ˜ƒ