Closed yyx990803 closed 7 years ago
I just saw that certain features will only be available in the standalone build. Does that mean that this and the NPM version are significantly different?
@rekateka 2.0 standalone build means (compiler + runtime). The default export of the NPM package will be runtime only, because if installing from NPM, you will likely pre-compile the templates with a build tool.
Thanks, @yyx990803. I still have a couple more questions regarding the compiler and other features, but I've used the forum for that.
Are there any worrisome changes made to docs I should review by any chance? Great work! Keep it up man. You're redefining web development. Thank you!
Can I get this.arg
of my directive?
I see vnode.data.directives
has arg
, but when I have two or more directives, I can not know the index
.
<!-- show @ 0, img @ 1-->
<img v-show="true" v-img:200*200="imgSrc">
<!-- img @ 0, show @ 1-->
<img v-img:200*200="imgSrc" v-show="true">
Should I use forEach
? Thank you!
@banricho good point, that's been overlooked! See updated directive function signature.
First of all, sorry for I am not quite sure that could I ask this problem here, and I have a little bit requirements want to say. The requirement is I hope I can design my component's usage like this
<carousel>
<img src="..." alt="..." desc="..." is="argument">
<img src="..." alt="..." desc="..." is="argument">
</carousel>
I hope the children can be as some kind of arguments, not only limit in attributes For now I can make a component, the usage like
<carousel items="[{}, {}, {}]"></carousel>
But I think it's not quite good, I hope it can like this one I made before in React coverflow
@andyyou - that question is probably best posted on the forum, since it isn't an issue, nor a clear suggestion, nor any real help to this issue.
If you find out that your requirements can't be met with Vue in your forum thread, then you can open a new issue here.
Scott
@smolinari Thanks
"But for more complex cases, it is recommended to introduce a dedicated state management layer using Vuex." This seems to imply that state should be used over events. I see them as completely separate - an event is a moment in time, whereas state does not change. You could say that you could watch the state, but that also does not convey a specific moment, but instead anytime something changes. I'm interested in the meaning behind this recommendation.
@jrenton Generally, we can consider the event system simply as component A telling component B to change it's state, or A telling B to do something else. So for the first case, we can use state management (managing a shared state for A and B) instead of using event system to let A tell B to change state. For the second case, I think it can be handled with the 'event bus' approach pretty well.
@jrenton instead of a soup of components talking to each other Vuex suggest a single channel for components to express "intentions" with actions, and record "facts" with mutations.
I'm using Twig along with Vue.
Until now (vue 1.0) I've been passing data into my components like this:
<my-component data="{{ DATA }}"><my-component>
(Note that {{
and }}
are twig tags - for vue I've been using custom delimiters ${
and }
)
If I'm understanding things correctly, in Vue 2.0 I should do it like this:
<my-component :data=" '{{ DATA }}' "></my-component>
right?
@gholol no it's just
<my-component :data="{{ DATA }}"></my-component>
Actually it seems your old usage shouldn't work in the first place.
Well it worked fine...
Like I said, the data are coming from twig templating engine. Now in Vue 2.0 it doesn't work. I've been trying to pass it like you said (without single apostrophes) but data property gets undefined.
Error: SyntaxError: missing } after property list
EDIT: It works, I forgot to mention that the DATA variable is a string
@jrenton My idea and motivation is quite simple seems Vue doesn't like React that compel us to use JSX. We can choose a lot of template
.
I hope I can use children element syntax as a parameter(arguments) pass args to parent because in some template language like slim
if you have a bit many attributes or say the attr's name is quite long then we have to put all the things in one line. it's easier make code of one line over 80 characters.
@yyx990803 Feeling adventurous today wanted to see how much effort would it take to migrate some 1.0 to 2.0a, unfortunately since it's not possible to use simple interpolation anymore, how would I go about and do something simple as <input type="text" name="account[categories][{{ category.id }}]">
in 2.0?
ES6 inline templates work in binding expressions:
<input type="text" :name="`account[categories][${ category.id }]`">
If that's the only way to get this working on 2.0, then don't mind me saying that that's a regression in the lovely syntax 1.0 got us used to – yes I know that's just ES2015.
I assume interpolation was removed for performance reasons? I just hope it's worth the uglier syntax.
@oskarkrawczyk I assume you want to end up with something like name="account[categories][fruits]"
in your DOM, because this is what your expression would render.
The 2.0 version (and proper 1.0, in fact) will be :name=" 'account[categories][' + category.id + ']' "
.
@simplesmiler Understood. I think {{ }}
just spoiled me a bit.
@yyx990803 can I dynamically insert component, like this?
render () {
return this.$createElement('div', { staticClass: 'list-container' }, this.list)
},
data () {
return {
list: []
}
},
method: {
a () {
this.list.push(this.$createElement('myComponent', {}))
}
}
How I can bind few values for an attribute which depend on expression? For example:
new Vue({
el:'body',
data:{
flag: true
}
})
<input type="text" v-bind:placeholder="{test: flag, test2: !flag}" />
I expect next result:
<input type="text" placeholder="test" />
<!-- or -->
<input type="text" placeholder="test2" />
@nervgh this is not the right place to ask this question.
Use ternary expression, v-bind:placeholder="flag ? 'test' : 'test2'"
.
@simplesmiler , thanks for your answer. I try to say that Object-Syntax will be useful in these cases, but is does not work as I expect.
@nervgh object syntax is only applicable to attributes that take a list of strings. Of native attributes the only such attribute is class
, and for the components there would be no way to detect from the child side whether you meant to send a list of strings or a proper object.
Re: .once
and .sync
are deprecated.
Doesn't this break really common design patterns?
I can't think how you'd be able to have simple components for handling form fields without these.
I have simple components for different form field types, eg here's my "textbox" component template::
<label>{{type.caption}}:<input type="text" v-model="data"></label>
...and also a more complex component for lists which provides a ui to add and remove elements from arrays in the data structure
Then I use these components eg like so:
<div v-for="field in type.fields">
<component :data.sync="data[field.name]" :is="field.ctype" :type="field">
Note: All of these components have two props: data
and type
. data
is the node in the data structure being edited that the component is responsible for providend a UI for editing, and type
is the node in the (massive, static) data structure which contains the types/fields hierarchy.
How can stuff like that work without .sync
?
It seems to me that it would severely complicate things to create some sort of messaging system between these components where the sub-components can somehow communicate to the parent which sub-component they are, and the parent can then figure out what part of its data structure to modify.
I really hope I'm missing something.... because it looks like you're saying that using components to create editors for parts of your data structure is an anti-pattern. Whaat? So far that's the only thing I've used Vue for. I'm guessing you think that removing this feature will encourage people to write cleaner code. Maybe it will have that effect on some people, but many people will write much nastier code to work around this limitation. Modifying state is the only useful thing that computers do. Please continue to make this easier.
@JasonWoof v-model
in 2.0 can work on custom components. The component simply needs to:
value
input
event when the value needs to be synced to parent, e.g. this.$emit('input', value)
See example.
@yyx990803 Thanks for the explanation and link. Now I'm just stuck on:
Why remove .sync
?
I don't see the advantage, only disadvantages. The example you linked shows that you can achieve the same thing with either :selected.sync
or v-model
. I only see disadvantages for the v-model method:
.sync
propsI don't see how switching to v-model makes anything clearer/cleaner. In both cases, the only indication in the parent that the child component can easily modify parent state is the syntax of the prop in the template. I would even argue that .sync
is more clear.
The other thing is that when you pass objects/arrays/etc as props, then they are mutable from the child component. So you can't shield programmers from being able to change the state from the child components in this case (which I assume is very common.) So it seems to me like you are introducing a stumbling block by removing the thing that makes it so passing string values works the same as passing object values. .sync
makes my code simpler and more consistent by always having my "data" props writable from the child side, no matter the data type.
I'm new to Vue.js (3 days ago) but from what I can see so far, Vue.js is valuable mainly because of two things:
At least that's what I've discovered so far.
It seems to me that removing .sync
makes it difficult to get Vue.js to consistently do the second.
@JasonWoof because explicit vs. implicit side effects outside of the components own scope makes all the difference in long term maintainability.
... and while one could argue that people simply should learn when to not use .sync
, our experience so far is different. people tend to rely too much on this and create code they later can hardly debug.
so this is a design decision to force people to do it right from the beginning.
an example:
name
between a parent and a child. all is well.watch
function. Nice!console.log()
anywhere to trace the behaviour.watch
function somehow....and this becomes even more crazy when you sync more than one level deep.
This is an (anti-)pattern we have seen over and over on the forums and in the gitter chat.
Removing .sync
forces people to write clear, explizit, maintainable code from the start, because their code won't stay simple enough for .sync
for very long, most of the time.
OK. Thank you for explaining.
It's good to hear what problem you are trying to solve.
I seriously doubt this will help though... Make it so people can't easily break the patters you like and people will do far worse things to work around the limitations.
This reminds me a lot of abstraction. Abstractions get us into so much trouble. They make code hard to read, hard to debug, etc.... But you can't fix this by taking away the ability to make abstractions... that's pretty much the thing that makes programming possible/useful. The solution to this is not at the language or framework level, but in teaching, advice, learning. We encourage people not to make things overly abstract.
It sounds to me like you are talking about such a design philosophy. In many cases, it's a great philosophy to keep in mind while coding. But when it is imposed as a limitation, and the programmer thinks that this limitation stops her from doing what she needs to do, then she's going to work around it, which will result in all the problems you were trying to avoid and worse.
People are not going to stop trying to mutate parent state from the children. You can't force people not to do that.
Your v-model
thing is complicated enough that I would work around this problem by passing the parent object/array and a key so that the child can modify it.
I guess this last bit hit's at the heart of what I'm trying to get across: I (personally) see the lack of .sync
as a problem, and will work around it or not use your framework. I bet a lot of people will have the same approach.
Perhaps this goes without saying, but it makes me a little angry when people try to impose design philosophies on me. I would much rather build things that go terribly wrong and learn not to do that again than to use systems that purposely withhold power for fear that I might use it badly.
P.S. Sorry, I can't help myself, one more comment, then I'll leave you guys alone. Most programmers write code that they cannot debug. This happens to every programmer in every language with every framework. This is how programmers become better programmers: they make mistakes, they make code they cannot fix, they learn how to write things differently in the future. Please don't dumb down your framework for everybody in an attempt to make it so programmers who abstract themselves into the corner can make their stuff a little bit more confusing/complex before it becomes such a mess that they can't debug it.
@JasonWoof it has nothing to do with "dumbing down", and preventing users from common pitfalls / ensuring better maintainability is by definition part of the job of a framework. We made the decision based on first hand experience designing, using the framwork itself, and observing user behavior in various use cases. If it's an anti-pattern, we will discorage users from using it, and provide guidence on the idiomatic solution. You are free to disagree with that based on your personal opninion, but I find your arguments hardly convincing.
People are not going to stop trying to mutate parent state from the children. You can't force people not to do that.
Sure. And we won't 'force' them, because there may be some edge cases where this might still be nessessary. So you can still access this.$parent
, you can pass $data
through a prop etc, but quite frankly doing so will be not much more convient that $emit
ing an event most of the time, so they won't be as attractive as .sync
sugar.
Also, $parent
et.al. are not part of the official guide, so users who use them are actively working around suggested best practices - which they are free to do, but we don't encourage that behaviour.
Consequently, the framework should not encourage similar behaviour by providing 'magical' syntactic sugar like .sync
if we feel that such a feature is misused in most scenarios and opposed to the best practices the framework seeks to establish.
尤大 有没有中文版的。。
What does the compatibility look like for vue-router?
@roblav96
There are some changes needed to be compatible, we are hoping to better incorporate the Router into Vue.
@blake-newman
Can we get a boilerplate template together on vue-cli? I can't seem to get any of this working 😢
@roblav96
There are some currently, there are some change changes needed with vue-loader to make it compatible. Currently 2.0 should be used for experimentation only until all further dependencies for large scale applications are updated.
Is there an ETA for the beta / release candidates?
@Evertt Alpha is due this week. Beta will follow with documentation completed, and maybe more support from core extending libraries (Vue-router ect). Release Candidate when Beta is proven successful.
@blake-newman thank you for that quick, concise and complete response. Those are the best. :-D
Any workaround for replace: false
in vue 2.0 ?
Hi, is JSX already usable?
@reohjs - No and I would personally see that as a real step backwards for Vue, if it did support JSX.
Scott
@reohjs In Evan's stream last night he mentioned it could be made with a plugin so i imagine once this goes into beta it wouldn't take long for someone to create it. I'm happy that it's not in the core but a JSX plugin sounds like a great idea.
I'm happy that it's not in the core
👍 👍 👍 👍
Yeah should be a plugin. However, as seen templates have a lot of benefits for standard components.
JSX compilation should be easy to achieve with this plugin: https://babeljs.io/docs/plugins/transform-react-jsx/
I think the _h
function would be the replacement for React.createElement
Both of these are being deprecated in favor of more explicit named indices and keys. This syntax is a bit magical and has limitations in nested loops. As a bonus, there will be two fewer points of syntax for newcomers to learn.
value in arr
(value, index) in arr
(switched order of arguments to be more consistent with JavaScript'sforEach
andmap
)value in obj
(value, key) in obj
(switched order of arguments, partly to be more consistent with many common object iterators, such as lodash's)(value, key, index) in obj
(index will now be available in object iteration for visual purposes, such as table striping)Directive interface change
In general, in 2.0 directives have a greatly reduced scope of responsibility: they are now only used for applying low-level direct DOM manipulations. In most cases, you should prefer using Components as the main code-reuse abstraction.
Directives no longer have instances - this means there's no more
this
inside directive hooks andbind
,update
andunbind
now receives everything as arguments.Note the
binding
object is immutable, settingbinding.value
will have no effect, and properties added to it will not be persisted. You can persist directive state onel
if you absolutely need to:You can use destructuring if you only care about the value:
In addition, the
update
hook has a few changes:bind
.binding.value === binding.oldValue
to skip unnecessary updates, but there are also cases where you'd want to always apply updates, e.g. when the directive is bound to an Object that might have been mutated instead of replaced.elementDirective
, directive params and directive options such asacceptStatement
,deep
etc. are all deprecated.Filter Usage and Syntax Change
In Vue 2.0, there are several changes to the filter system:
{{}}
tags). In the past we've found using filters with directives such asv-model
,v-on
etc. led to more complexity than convenience, and for list filtering onv-for
it is more appropriate to move that logic into JavaScript as computed properties.The filter syntax has changed to be more inline with JavaScript function invocation, instead of taking space-delimited arguments:
Transition System
Transition CSS class changes:
The always-on
v-transition
class is no longer added and Vue now uses the same classes Angular and React CSSTransitionGroup does:v-enter
: applied before element is inserted, remove after 1 tick. (starting state for enter)v-enter-active
: applied before element is inserted, removed when transition/animation finishes. (active + ending state for enter)v-leave
: applied right when the leave transition is triggered, remove after 1 tick (starting state for leave)v-leave-active
: applied right when the leave transition is triggered, removed when the transition/animation finishes. (active + ending state for leave)v-enter-active
andv-leave-active
gives you the ability to specify different easing curves for enter/leave transitions. In most cases, upgrading means simply replacing your currentv-leave
withv-leave-active
. (For CSS animations, usev-enter-active
+v-leave-active
)Transition API Change
The
<transition>
componentAll single-element transition effects are now applied by wrapping the target element/component with the
<transition>
built-in component. This is an abstract component, which means it does not render an extra DOM element, nor does it show up in the inspected component hierarchy. It simply applies the transition behavior to the wrapped content inside.The simplest usage example:
The component defines a number of props and events that maps directly to the old transition definition options:
Props
Used to automatically generate transition CSS class names. e.g.
name: 'fade'
will auto expand to.fade-enter
,.fade-enter-active
, etc. Defaults to"v"
.Whether to apply transition on initial render. Defaults to
false
.Whether to apply CSS transition classes. Defaults to
true
. If set tofalse
, will only trigger JavaScript hooks registered via component events.Specify the type of transition events to wait for to determine transition end timing. Available values are
"transition"
and"animation"
. By default, it will automatically detect the type that has a longer duration.Controls the timing sequence of leaving/entering transitions. Available modes are
"out-in"
and"in-out"
; defaults to simultaneous.Individually configure transition CSS classes.
Example applying transition to dynamic components:
Events
Corresponds to the JavaScript hooks available in 1.x API.
Example:
When the entering transition completes, the component's
transitionComplete
method will be called with the transitioned DOM element as the argument.Some notes:
leave-cancelled
is no longer available for insertion/removals. Once a leave transition starts, it cannot be cancelled. It is, however, still available forv-show
transitions.enter
andleave
hooks, the presence ofcb
as the second argument indicates the user wants explicit control of the ending timing of the transition.The
<transition-group>
componentAll multi-element transition effects are now applied by wrapping the elements with the
<transition-group>
built-in component. It exposes the same props and events as<transition>
does. The difference being that:<transition>
,<transition-group>
renders a real DOM element. By default it renders a<span>
, and you can configure what element is should render via thetag
prop. You can also use it with theis
attribute, e.g.<ul is="transition-group">
.<transition-group>
does not support themode
prop.<transition-group>
must be uniquely keyed.Example:
Moving Transitions
<transition-group>
supports moving transitions via CSS transform. When a child's position on screen has changed after an updated, it will get applied a moving CSS class (auto generated from thename
prop or configured with themoveClass
prop). If the CSStransform
property is "transition-able" when the moving class is applied, the element will be smoothly animated to its destination using the FLIP technique.See a live demo here.
Creating Reusable Transitions
Now that transitions are applied via components, they are no longer considered an asset type, so the global
Vue.transition()
method and thetransition
option are both deprecated. You can just configure the transition inline with component props and events. But how do we create reusable transition effects now, especially those with custom JavaScript hooks? Well, the answer is creating your own transition components (they are particularly suitable as functional components):You can then use it like this:
v-model changes
The
lazy
andnumber
params are now modifiers:.trim
- trims the input, as the name suggests.debounce
param has been deprecated. (See upgrade tip at bottom)v-model
no longer cares about initial inlinevalue
. It will always treat the Vue instance data as the source of truth. This means the following will render with a value of 1 instead of 2:Same goes for
<textarea>
with existing content. So instead of:Do:
The main idea is that the JS side should be considered the source of truth, not your templates.
v-model
no longer works when used on av-for
iterated primitive value:This doesn't work because it's the equivalent of this in JavaScript:
As you can see, setting
str
to another value in the iterator function will do nothing because it's just a local variable in the function scope. Instead, you should use an array of objects so thatv-model
can update the field on the object:Props Behavior
.once
and.sync
are deprecated. Props are now always one-way down. To produce side effects in the parent scope, a component needs to explicitly emit an event instead of relying on implicit binding.a
and then setthis.a = someOtherValue
in the component. Due to the new rendering mechanism, whenever the parent component re-renders, the child component's local changes will be overwritten. In general, in 2.0 you should treat props as immutable. Most use cases of mutating a prop can be replaced by either a data property or a computed property.keep-alive
keep-alive
is no longer a special attribute: it is now a wrapper component, similar to<transition>
:This makes it possible to use
keep-alive
on multiple conditional children (note the children should eventually evaluate to a single child - any child other than the first one will be ignored):When used together with
<transition>
, make sure to nest it inside:Slots
<slot>
s with the same name in the same template. When a slot is rendered it is "used up" and cannot be rendered elsewhere in the same render tree.<slot>
no longer preserves theslot
attribute. Use a wrapper element to style them, or, for advanced use cases, modify the inserted content programmatically using render functions.Refs
v-ref
is now no longer a directive: it is now a special attribute similar tokey
andtransition
:Dynamic ref bindings are now also supported:
vm.$els
andvm.$refs
are merged. When used on a normal element the ref will be the DOM element, and when used on a component the ref will be the component instance.vm.$refs
are no longer reactive, because they are registered/updated during the render process itself. Making them reactive would require duplicate renders for every change.On the other hand,
$refs
are designed primarily for programmatic access in JavaScript - it is not recommended to rely on$refs
in templates because it entails referring to state that does not belong to the instance itself.Misc
track-by
has been replaced withkey
. It now follows the same rule for binding an attribute: withoutv-bind:
or:
prefix, it is treated as a literal string. In most cases you'd want to use a dynamic binding, which expects a full expression instead of a string key. For example:Interpolation inside attributes are deprecated:
Attribute binding behavior change: only
null
,undefined
andfalse
are considered falsy when binding attributes. This means0
and empty strings will render as-is. For enumerated attributes. This means:draggable="''"
will render asdraggable="true"
.Also, for enumerated attributes, in addition to the falsy values above, the string value of "false" will also render as attr="false".
v-on
now only listens to custom events $emitted by that component. (no longer listens to DOM events)v-else
no longer works withv-show
- just use negation expression.{{* foo }}
) deprecated - usev-once
instead.:style
no longer supports inline!important
propsData
instead)el
option can no longer be used inVue.extend
. It can now only be used as an instance creation option.Vue.set
andVue.delete
cannot work on Vue instances. It is now mandatory to properly declare all top-level reactive properties in thedata
option.$data
. This prevents some edge cases in the reactivity system and makes the component state more predictable (especially with type-checking systems).User watchers created via
vm.$watch
are now fired before the associated component re-renders. This gives the user a chance to further update other state before the component re-render, thus avoiding unnecessary updates. For example, you can watch a component prop and update the component's own data when the prop changes.To do something with the DOM after component updates, just use the updated lifecycle hook.
Upgrade Tips
How to Deal with Deprecation of
$dispatch
and$broadcast
?The reason that we are deprecating
$dispatch
and$broadcast
is that event flows that depend on the components tree structure can be hard to reason about when the components tree becomes large (simply put: it doesn't scale well in large apps and we don't want to set you up for pain later).$dispatch
and$broadcast
also do not solve the communication between sibling components. Instead, you can use a pattern similar to the EventEmitter in Node.js: a centralized event hub that allows components to communicate, no matter where they are in the components tree. Because Vue instances implement the event emitter interface, you can actually use an empty Vue instance for that purpose:And don't forget to use $off to unbind the event.
This pattern can serve as a replacement for
$dispatch
and$broadcast
in simple scenarios. But for more complex cases, it is recommended to introduce a dedicated state management layer using Vuex.How to Deal with the Deprecation of Array Filters?
For list filtering with
v-for
- one of the more common usage of filters - it is now recommended to use computed properties that return a processed copy of the original Array (see updated data grid example). The benefits is that you are no longer limited by the arbitrary filter syntax/API - it's just plain JavaScript now, and you naturally have access to the filtered result because it is a computed property.Also see this discussion thread.
How to Deal with the Deprecation of
debounce
forv-model
?Debouncing is used to limit how often we execute Ajax requests and other expensive operations. Vue's
debounce
attribute parameter forv-model
makes this easy, but it also debounces state updates rather than the expensive operations themselves, which comes with limitations.These limitations become apparent when designing a search indicator. Take a look at that example. Using the
debounce
attribute, there'd be no way to detect a dirty input before the search begins, because we'd lose access to the input's real-time state. By decoupling the debounce function from Vue, we're able to debounce only the operation we want to limit.There will be other times when debouncing isn't quite the right wrapper function. In the very common example of hitting an API for search suggestions, waiting to offer suggestions until after the user has stopped typing isn't an ideal experience. What you probably want instead is a throttling function. Now since you're already using a utility library like lodash for
debounce
, refactoring to usethrottle
instead takes only a few seconds!