Giter VIP home page Giter VIP logo

Comments (16)

shentao avatar shentao commented on May 3, 2024

😍

Vue.observable – do we want to use the name observable? As it was already pointed out somewhere else, it might be misleading as it is in 2.6 and might not be a good idea to keep it.

All current lifecycle hooks will have an equivalent useXXX function that can be used inside setup():

onXXX typo

These options will only be available in the compatibility build of 3.0

  • data (replaced by value and value.raw returned from setup())
  • computed (replaced by computed returned from setup())
  • methods (replaced by plain functions returned from setup())
  • watch (replaced by watch)
  • provide/inject (replaced by provide and inject)
  • mixins (replaced by function composition)
  • extends (replaced by function composition)
  • All lifecycle hooks (replaced by onXXX functions)

This is huge. What happens to this? Will it be available inside setup? Where should we $emit events? Can this be done inside composition functions by receiving the vm? But this will probably hide the source of the events?

In the compat build, will it be possible to call composition functions in other places than setup?

from core.

Akryum avatar Akryum commented on May 3, 2024

Where should we $emit events?

I agree this is quite unclear in the current RFC. Maybe something like this:

import { emit } from 'vue'

export function myComposition () {
  emit('change', 42)
}

from core.

posva avatar posva commented on May 3, 2024

Motivation > Bundle Size

The returned object in setup will still keep the original names, wouldn't it? I was wondering if it's possible to mangle those in production with some activable option, it could reduce the size of apps even more.

Detailed Design > State

is state dropped in favor of always using value. Is was on vuejs/rfcs#22, so I think people will wonder where did it go and mentioning they got merged would help

Regarding the example with props:

setup(props) {
    return {
      msg: `hello ${props.name}!`
    }
  },

Does this return a static value or is it equivalent to creating a computed property

Watchers

If we watch a function that returns an array, does the watcher trigger whenever the array is modified? I'm asking because right now, passing a getter to the watcher will trigger only if the value or reference is modified, which requires the dev to serialize the information to properly trigger one watcher when one of the multiple properties we want to watch changes.

// taken from https://github.com/vuejs/rfcs/pull/22#issuecomment-481084795
watch(
  () => [currentArenaRef.value, currentUserRef.value],
  ([currentArena, currentUser], [prevArena, prevUser]) => {
    findMatches(currentArena,currentUser ) ...
  }
})

can we also do

const currentInfo = observe({
  currentArenaRef,
  currentUserRef
})

watch(
  currentInfo,
  // what happens if the user does
  // () => currentInfo
  // do we warn them?
  // ...
})

const currentArenaAndUser = value([
  currentArenaRef,
  currentUserRef
])

watch(
  currentArenaAndUser,
  // can we do this?
})

Watcher Callback Timing

The sync option triggers the watcher as soon as the value being watched is modified, doesn't it? I think an extra sentence like Doing count.value++ will immediately trigger the watcher
I think it's worth adding that lazy and deep are the same as current API (maybe with a link to docs). What are onTrack and onTrigger?

Adoption Strategy > Options deprecated by this RFC

What is value.raw? is it value

Drawbacks

Another drawback is having pretty much everything inside of one function, leaving to the user how to organize all the logic, which could indeed bring spaghetti code like mentioned in (vuejs/rfcs#22 (comment)). Previously, having methods, data, computed etc, constrained developers to organize their code

from core.

shentao avatar shentao commented on May 3, 2024

Kinda agree on the drawback @posva mentioned. Thought the setup would be intended to go along the object properties and not entirely replacing them.

from core.

posva avatar posva commented on May 3, 2024

Thinking about vue router navigation guards. Since properties returned in setup are not accessible through this, we will need to provide a function-based api as well for in-component guards like onBeforeRouteEnter, onBeforeRouteUpdate and onBeforeRouteLeave but at the same time, it's impossible from the router to pick up onBeforeRouteEnter function as they have to be invoked before the component is even instantiated.
Is there a way we make the returned value in setup available in the component so other libraries can still interact with component properties through custom functions

from core.

nekosaur avatar nekosaur commented on May 3, 2024

I am also worried that having everything defined in setup might very well lead to spaghetti code for developers who are unfamiliar with any best practices for using this new API.

With regard to being able to mutate unwrapped values in template, as shown:

const MyComponent = {
  setup() {
    return {
      count: value(0)
    }
  },
  template: `<button @click="count++">{{ count }}</button>`
}

Would that also apply when passing the unwrapped value through a scoped slot? e.g.

const MyComponent = {
  setup() {
    return {
      count: value(0)
    }
  },
  template: `<div><slot v-bind:count="count"></slot></div>`
}

const OtherComponent = {
  template: `<my-component><button v-slot="props" @click="props.count++">{{ props.count }}</button></my-component>`
}

from core.

shentao avatar shentao commented on May 3, 2024

What also worries me that this will most likely break plugins like Vuelidate, that rely on component options and this context. I imagine it could be rewritten to become a composition function

const validatedState = vuelidate(state, validationSchema)

I like the idea personally, but I fear this will make the library harder to use, especially since currently it also supports validating computed properties or Vuex getters.

Also, how would we use Vuex with that API? Say using mapState inside setup to get a variable?

const [users, posts] = mapGetters(['users', 'posts'])

from core.

yyx990803 avatar yyx990803 commented on May 3, 2024

@shentao Vue.observable – do we want to use the name observable? As it was already pointed out somewhere else, it might be misleading as it is in 2.6 and might not be a good idea to keep it.

Yes, this should be one of the unresolved questions. I was thinking between state and value.raw.

  • Technically state doesn't really exclude primitive values, so the distinction between state and value isn't super clear just by looking at the name.
  • value.raw() makes it more obvious that you are creating a non-wrapped reactive object, but looks... uglier?

@shentao What happens to this? Will it be available inside setup?

this will still be there and will be available in setup.


@nekosaur Would that also apply when passing the unwrapped value through a scoped slot?

No, slot props are always immutable.


@posva I was wondering if it's possible to mangle those in production with some option

This would require template references to be mangled too - which can be very hard.


@posva Does (the props example) return a static value or is it equivalent to creating a computed property

It works just like returning an object from data().


If we watch a function that returns an array, does the watcher trigger whenever the array is modified? I'm asking because right now, passing a getter to the watcher will trigger only if the value or reference is modified, which requires the dev to serialize the information to properly trigger one watcher when one of the multiple properties we want to watch changes.

I don't understand the question. Watchers have always been working this way. If you want to trigger watcher with nested mutations you should be using deep: true.


Spaghetti code

I tend to look at this problem this way: since function-based APIs leave more flexibility to the users, this can lead to both less organized code (by beginners) AND better organized code. However, the less organized code can be largely mitigated with proper documentation of best practices, while the better organized code can never be achieved with current options-based API.

With component options, your code only seem to be organized - in a complex component, logic related to a specific task is often split up between multiple options. Separation of options vs. setup() is like sticking to the separation of HTML/CSS/JS vs. Single File Components. If you put all the logic of your app in a single SFC, that SFC is going to become a monster and become very hard to maintain - so we split the component into many smaller ones. Similarly, if you have a huge setup() function, you split it into multiple functions. Function based API makes better organized code easily possible while with options you are stuck with... options (because splitting into mixins makes things worse).

from core.

shentao avatar shentao commented on May 3, 2024

With component options, your code only seem to be organized - in a complex component, logic related to a specific task is often split up between multiple options. Separation of options vs. setup() is like sticking to the separation of HTML/CSS/JS vs. Single File Components. If you put all the logic of your app in a single SFC, that SFC is going to become a monster and become very hard to maintain - so we split the component into many smaller ones. Similarly, if you have a huge setup() function, you split it into multiple functions. Function based API makes better organized code easily possible while with options you are stuck with... options (because splitting into mixins makes things worse).

This does work for me. Thank you!
Just one more question and I think I already know the answer, but just need to make sure – there are no hidden restrictions as to what a composition function is returning right? So it can return methods that can be later used inside the component.

I also imagine that possibly, a composition function could return a render function (a functional component) that could then be used inside the components render function? Or template?

from core.

LinusBorg avatar LinusBorg commented on May 3, 2024
  • Compatibility build: supports both the new function-based APIs AND all the 2.x options.

Does that mean that it's possible to mix the two?

export default {
  setup() {
    return {
      count: value(0)
    }
  },
  computed: {
    plusOne() {
      return this.count + 1
    }
  }
}

Not that I think this is nice, but it would be convenient for migrating bigger components piece by piece from the object notation to the setup function.

from core.

posva avatar posva commented on May 3, 2024

I don't understand the question. Watchers have always been working this way. If you want to trigger watcher with nested mutations you should be using deep: true.

I'm realizing I have been teaching a way of doing this that is more complicated than it should because using an array also works 😅. It may trigger more times if a value returned in the array is changed multiple times before a flush and is set to the same value it had before being changed the first time

However, the less organized code can be largely mitigated with proper documentation of best practices

I think that practice has shown us that people don't read the documentation, no matter how good it is. Aren't we going to complexify things for people who are starting if they learn first the object based syntax (Vue 2) and then learn the advanced version which allows them to use the smaller version of Vue? It feels like we are making the learning curve steeper.
However, I do agree that having the functional approach is better in bigger projects. So I wonder if having some tool to hint how to convert (I doubt it is possible to fully automatize) plus a good documentation teaching how to move from the non function-based syntax to the function one is enough to keep Vue as approachable as it is today, which is, in my experience the most selling point of Vue

from core.

yyx990803 avatar yyx990803 commented on May 3, 2024

I think that practice has shown us that people don't read the documentation, no matter how good it is.

I don't think that's true at all. People probably don't read the API listing in full details, but they definitely read the guide when they first learn Vue. The point is - anyone learning the new API will have to learn it through something - be it docs or 3rd party content - and any 3rd party content will be some sort of spin-off of the docs. So as long as the initial v3 docs introduces it properly, most users will learn to use it properly.

from core.

yyx990803 avatar yyx990803 commented on May 3, 2024

@LinusBorg Does that mean that it's possible to mix the two?

Yes. There might be some edge cases (I haven't fully implemented 2.x compat support yet) but theoretically it should work.

from core.

KaelWD avatar KaelWD commented on May 3, 2024

const plusOne = computed(() => count.value + 1)

Could that also be const plusOne = computed(() => this.count + 1) or is setup more like beforeCreate?

from core.

yyx990803 avatar yyx990803 commented on May 3, 2024

@KaelWD it's more like beforeCreate. It will be called only after beforeCreate and props resolution, but before all other 2.x options.

from core.

gustojs avatar gustojs commented on May 3, 2024
const writableComputed = computed(
  // read
  () => count.value + 1,
  // write
  val => {
    count.value = val - 1
  }
)

I like how it's much easier to switch between a read-only and writeable computed properties without having to rewrite between an object and functions.

from core.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.