Skip to content
This repository has been archived by the owner on May 3, 2018. It is now read-only.

0.12 Plan - feedback welcome #158

Open
yyx990803 opened this issue May 13, 2015 · 80 comments
Open

0.12 Plan - feedback welcome #158

yyx990803 opened this issue May 13, 2015 · 80 comments

Comments

@yyx990803
Copy link
Member

Hi Vue.js users, here is a list of changes I'm planning for the 0.12 release. The goal is to remove some cruft in the API and make things more consistent across the board. The two new features have already been implemented in the dev branch, and I will soon start doing 0.12 beta releases so people can try it out. The breaking changes are pretty much just ideas that I'd like to gather feedback for - in particular, let me know how hard do you think it would be for you to migrate your existing app if these changes went live.

New Features

  • async components. Allows defining a component as a function that asynchronous resolves the component definition. This would enable easy lazy-loading mechanisms.
  • one-way paramAttributes/props syntax (prop="{{*onetime}}")

Breaking Changes

  • paramAttributes renamed to props.
  • Intent to remove: v-partial and {{>partial}} syntax. The partial concept is a legacy from string-based templates, and isn't particularly useful when everything should just be components.
  • Intent to remove: v-with syntax.
    • It allows the user to add arbitrary data fields to a child component, which may conflict with the child's default data. At the same time, the child needs to be more explicit about what it expects from the parent.
    • It's also confusing to have two ways of doing the same thing. Everything should just be props (previously paramAttributes).
    • The name v-with isn't super precise for what it does now: passing data down to a child. It is also a legacy from string templates that uses {{#with}} blocks to shift the data context.
  • Intent to remove: v-component syntax.
    • Similar to v-with, it doesn't make much sense to have two ways of doing the same thing. Every component should just be a custom tag.
    • For dynamic components, use the special <component is="{{view}}"></component> syntax. "component" is a reserved component name.
    • It should no longer be required to have a hyphen in your component name in order to use it as a custom tag.
  • Intent to remove: replace option. A component always replaces its placeholder node.
  • Intent to remove: inherit option. Prefer explicitly passing down props.
@holic
Copy link

holic commented May 14, 2015

👍

I'm not sure on the proposed inherit changes. I was working on an app where I tried to make use of paramAttributes to keep my components isolated without tight coupling, but ran into issues. I'll see if I can remember or recreate them so I can mention them here.

@thelinuxlich
Copy link

Agree with everything minus removing the inherit option.

@taylorotwell
Copy link

Looks pretty good overall!

@kazupon
Copy link
Member

kazupon commented May 14, 2015

👍

Among them, I agree especially with removing the v-with directive. because it breaking the child component data.

@nadirabid
Copy link

👍

Vue's simple and flexible API is paramount. To be honest, I haven't personally found need for async but I can see it being useful.

Looking forward to 0.12!

@cheapsteak
Copy link

Breaking v-with would certainly be a pain to refactor were we to upgrade, but I think it's the right way to go. 👍

@OEvgeny
Copy link

OEvgeny commented May 14, 2015

Looks pretty good. Except maybe inheritance. But I think with proper props implementation we will not need to inherit all data. Anyway inherit breaks component system, I think.

As I thought one of the partials purposes was to decrease number of complete Vue instances and replace it with something lightweight. Am I wrong? To be honest, didn't use it overall, but it looks useful.

Also Vue documentation is great, but sometimes I need it to be more reach. Any plans for it?

Waiting for 0.12 too!

@ayamflow
Copy link

👍 pretty good to see Vue move closer to "real" web components.

@pechorin
Copy link

👍

Removing v-with and v-component is great simplification. Also props look's more like react and this is also nice idea.

@crswll
Copy link

crswll commented May 14, 2015

👍

This all sounds great to me.

@azamat-sharapov
Copy link

This is great!!!! Especially async components (which enables lazy loading). I've been spending so many hours to get it work via webpack :D will refactor with pleasure to have lazy loading only from Vue, instead of webpack.

Does "one-way props" have performance advantages? Or it's just for better isolation/protection of prop?

@yyx990803
Copy link
Member Author

@azamat-sharapov performance will be largely the same, it's for better isolation. In some cases you don't want the component to be able to mutate parent state.

@azamat-sharapov
Copy link

@yyx990803 thanks. Personally for my projects, if I decide to switch to 0.12, I will have to get rid of v-component, I have been using it since it's not always easy to come up with good name for component without dash. So now dash is not necessary and it's helpful.
Never used partials and always avoid use of inherit since it looks like bad practice to me, so +1 for removing it. And I still have v-with in some places, though I lately got used to paramAttributes and think it's better, so +1 for removing v-with too, even though it requires refactoring for many.

@young-steveo
Copy link

@yyx990803 I seem to be in the minority when it comes to v-component; I'm a fan of the <div v-component="{{ view }}"></div> syntax. I never use custom tags in my projects (no strong opinion against custom tags, I just prefer the aesthetics of attributes). This isn't the end of the world, and I love using Vue, so I'll migrate to <dynamic-component type="{{ view }}"></dynamic-component> if this change is set in stone.

Love the idea of async components! 👍

@crswll
Copy link

crswll commented May 14, 2015

@young-steveo Agreed, but I think it's just us being stubborn. It's definitely going to be the norm in the future.

@yyx990803
Copy link
Member Author

Update:

  • Simplified <dynamic-component type="{{view}}"> to just <component type="{{view}}">.
  • replace option will be preserved, due to it requiring some significant refactoring for some existing apps. For those of you would like to have it default to true, you can do so by setting Vue.options.replace = true.
  • inherit option will be preserved, although it should be treated as "only use if you know what you are doing"...

@steffans
Copy link

👍

What about naming dynamic components <v-component type="{{ view }}"><v-component>, it's shorter and it matches the current attribute namespace style.

@holic
Copy link

holic commented May 15, 2015

replace option will be preserved, due to it requiring some significant refactoring for some existing apps.

Curious what these use-cases are that would require major refactoring?

@285858315
Copy link

async components 这个真的很赞!

@sjoerdvisscher
Copy link

If <component type="{{view}}"> is only used for dynamic content, you could make type a reactive directive, instead of a literal one: <component type="view">

@azamat-sharapov
Copy link

Why is it type anyway? how about name or variable or maybe source ? can't understand meaning of type..

@yyx990803
Copy link
Member Author

@sjoerdvisscher you can still do <component type="component-id"> and it resolves to the component-id literal value. type here is similar to a prop and the braces make it explicit that it is bound to a dynamic value.

@taylorotwell
Copy link

Agree that name "type" is not very intuitive.

On Saturday, May 16, 2015, Evan You notifications@github.com wrote:

@sjoerdvisscher https://github.com/sjoerdvisscher you can still do and it resolves to the component-id literal value.
type here is similar to a prop and the braces make it explicit that it is
bound to a dynamic value.


Reply to this email directly or view it on GitHub
#158 (comment).

@yyx990803
Copy link
Member Author

What would be better though? I don't think name, variable or source is any better than type.

@crswll
Copy link

crswll commented May 16, 2015

It tells you what type of component it is just like <input type="password"> tells you it's an <input> of type password. I think it makes sense.

@RangerMauve
Copy link

I agree that type makes sense. However, might I suggest borrowing is from the web components spec? Or would that just make things more confusing like having a dash in the name did.

@yyx990803
Copy link
Member Author

@RangerMauve is sounds like a plausible idea, and it resembles real Web Components...

Just to get a feeling of what it looks like:

<component is="{{view}}"></component>

Although personally I still prefer type.

@kzima
Copy link

kzima commented May 19, 2015

+1 for async components and lazy-loading mechanisms. However, I wonder how would that play with webpack?

@yyx990803
Copy link
Member Author

@kzima like this:

components: {
  'my-async-component': function (resolve) {
    // require.ensure is webpack's code-splitting point
    require.ensure(['./my-async-component.js'], function (require) {
      resolve(require('./my-async-component.js'))
    })
  }
}

It could be even simpler using webpack's AMD syntax:

components: {
  'my-async-component': function (resolve) {
    require(['./my-async-component'], resolve)
  }
}

@azamat-sharapov
Copy link

@yyx990803 no passing require parameter?

@fullfs
Copy link

fullfs commented May 29, 2015

Oh and I use partials a lot. It's very useful sometimes. Definitely don't want to convert them all into components...

@young-steveo
Copy link

@fullfs It seems you have built a pretty large body of work around a pre-v1.0.0 library. That can sometimes get pretty painful as the API stabilizes.

@fullfs
Copy link

fullfs commented May 29, 2015

@young-steveo true. And I'm aware it. It was a risk to begin with. But I can give some useful feedback :D So I'd like partials to be kept :)

@yyx990803
Copy link
Member Author

@fullfs if you really want partials that bad, we can maybe ship it as a standalone directive separately.

@mark-hahn
Copy link

@OEvgeny said ...
Wonder why people love is so much. At first is is a verb.

The word "is" is an indicative which is nothing like a noun or verb. An indicative indicates what something is. So its usage is perfect here.

@kazupon
Copy link
Member

kazupon commented May 31, 2015

In async components feature,
when the undefined component found, if we can resolve lazy-loading with hook function, I think that is very useful.

like this:

var Vue = require('Vue')
var _ = Vue.util

new Vue({
  ...

  components: {
    // with object
    component1: {
      ...
    },
    // with url path
    component2: 'components/component2.js',
    ...
  },
  ...

  // lazy-loading hook function
  loading: function (raw, resolve) {
    if (_.isPlainObject(raw) { // component plain object
      resolve(raw)
    } else if (typeof raw === 'string') { // component url path
      // lazy-loading with require.js
      require([raw], resolve)

      /* lazy-loading with webpack
      require.ensure([raw], function (require) {
        resolve(require(raw))
      })
      */
    }
  },
  ...
}).$mount('#app')
...

what do you think about it ?

@yyx990803
Copy link
Member Author

@kazupon one problem with this is that module bundler like Browserify and Webpack rely on seeing the literal string of module id (e.g. require('my-component')) in order to resolve dependencies between modules. When you require(dynamicVar), they won't be able to tell which module you are trying to require.

This should work with requirejs though. You can make a helper function:

function async (path) {
  return function (resolve) {
    require([path], resolve)
  }
}

Vue.component(async('my-component.js'))

@fullfs
Copy link

fullfs commented May 31, 2015

@yyx990803 by the way, please notice error handling while getting async components. There is a problem with the case while using webpack.

@yyx990803
Copy link
Member Author

@fullfs can you elaborate?

@fullfs
Copy link

fullfs commented Jun 1, 2015

@yyx990803
Ok, for example we've got an async component require. In webpack we go like this first:

var component = require('bundle?lazy&name=component!My/Async/Component');

Then we try to pull the component:

component(function (file) {
    resolve(file);
});

The thing is there is no way we can catch an error if server didn't respond (server may go down or something). The callback just won't fire. I've tried a plugin for the case, but it didn't work properly too. Then my app just will be freezed.

So there is a need for some way to catch the error (timeout?) and say something like "oops we couldn't get the component, so lets fall back".

It could be a reject callback, for example:

components: {
  'my-async-component': function (resolve, reject) {
    var timeout = setTimeout(function () {
      reject('timeout');
    }, 3000);
    require(['./my-async-component'], function (file) {
      clearTimeout(timeout)
      resolve(file)
    })
  }
}

@kazupon
Copy link
Member

kazupon commented Jun 1, 2015

@yyx990803
I see !!
I will try to use helper function. :)

@yyx990803
Copy link
Member Author

@fullfs it might be helpful to have some warning, but if you failed to resolve an async component, what would you expect as the fallback? There's no component to render, so the app can't really do anything. Calling the callback when the component resolution has failed will just result in an error.

You can actually create a generic "oops" component and just resolve(oops) when something goes wrong...

@fullfs
Copy link

fullfs commented Jun 2, 2015

@yyx990803 When async component's failed to resolve I want a way for my app to react, that's it. Resolving another component is a good thing. It's actually the fallback I'd like to have (for some reason didn't think I could do that :D).
Thanks :)

@yyx990803
Copy link
Member Author

Some thoughts on improving DOM event and Vue event handling syntax: https://github.com/yyx990803/vue/issues/722#issuecomment-109849898

@nirazul
Copy link

nirazul commented Jun 8, 2015

I don't like the proposal concerning v-on. I imagine that it can get very sluggish when you want to handle multiple dom-events on the same element.
For me it's no improvement to switch out a custom tag with an also namespaced tag which is different for every event that exists and is to come in the future.
I like the possibility to pass a dynamic object to v-on, rather than writing custom tags for everything.

As for v-events I've recently had some struggle to differenciate between using v-events as a Directive and the events property. Maybe these two could be made clearer.

@fullfs
Copy link

fullfs commented Jun 8, 2015

@yyx990803
By the way, talking about version 0.12. Is there any hope to have 0.11 -> 0.12 migration plugin? :)
I would have really hard time with the migration if no, after all. There are 3 things I'd like to have there: v-component, v-with and partials.

@thelinuxlich
Copy link

I don't see any benefits for the new event syntax :(

@yyx990803
Copy link
Member Author

Looks like most people want to stick with v- directives, we'll keep things as is for now then.
Maybe v-events can have a better name, e.g. v-callbacks?

@nirazul
Copy link

nirazul commented Jun 10, 2015

v-callbacks sounds alright, maybe v-listeners would be clearer for the purpose. It sort of "listens" for events happening in its child.

@yyx990803
Copy link
Member Author

@nirazul I've decided to just remove it. You can now just pass down parent methods as props and let children call them.

@federicodionisi
Copy link

@yyx990803
As @fullfs suggested, would be really nice to have a migration plugin from 0.11.0 to 0.12.0

All new features inside 0.12.0 are amazing but most of them are breaking changes and for those who are using Vue in production will be painful to update it.

@cjsaylor
Copy link

@fullfs @federicodionisi You guys should collaborate and make one. I don't think it's necessary for a library author of pre-release software to also have to contend with writing migration scripts.

@fullfs
Copy link

fullfs commented Jun 18, 2015

@yyx990803 Can I ask you for solution about partials? Now it's gone and they need to be replaced by something.
I usully use partials as something similar to template includes to make my templates smaller.
For example, I'm selling apartments and I've got a page with about one with several sets of props.
There are a lot of props there, but all of them are just a part of single data object. And so I've got several partials with sets of the params for each view case.
What should I do now? The simplest solution is to make them into components with inherit: true, but it looks overhead to me, I don't want to create extra VMs.
Is there any recommended way?

@yyx990803
Copy link
Member Author

@fullfs does making v-html auto compile its content sound like a solution?

@fullfs
Copy link

fullfs commented Jun 18, 2015

@yyx990803 I'm afraid it's not. I won't be able to use v-on and etc. there, right?
Basically I just want to split one big template into several small templates

@nirazul
Copy link

nirazul commented Jun 18, 2015

I have the same feeling about v-partial. It was the excellent solution for a component that can take multiple shapes that differ in markup and css, but not in functionality. Now I'm forced to use v-if, v-html or make a new component.

@yyx990803
Copy link
Member Author

Yeah, ever since 0.12 I've seen people run into cases where partial just makes more sense. I'll consider adding it back in 0.12.2.

@fullfs
Copy link

fullfs commented Jun 18, 2015

@yyx990803 That would be absolutely great! Thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests