简体   繁体   中英

Vue.js 2.0 - creating reusable components

I am trying to create fully reusable component using Vue.js 2 and single file components, and right now my approach seems to be impossible to realize.

The goal is to create component for creating forms for a complex, nested JSON structure. This structure is supposed to be edited and then sent to the server. The component itself displays a header and submit button but the fields along with their placing is entirely the responsibility of the user of my component. (front-end engineer)

The MyForm component (implementation is not relevant here) is passed the JSON data and url to post them to.

The form is supposed to be reusable by many other users and the contents of the form itself is supposed to be not relevant. It may have a mix of html/inputs/custom components as children.

Let's imagine a simple scenario without data nesting with the following data:

var mymodel={ name : "My name", surname : "My surname" }

And a form i would like to create using my component:

<MyForm :model="mymodel" :url="http://localhost/post">
   <div>
     <MyTextInput v-model="model.name" label="Name"/>
     <MyPanel>
       <MyTextInput v-model="model.surname" label="Surname"/>
     </MyPanel>
   </div>
</MyForm>

Therefore:

  1. MyForm gets passed a model to submit, stores it in data
  2. MyTextInput is a custom component for displaying input with label
  3. Second MyTextInput is the same component but created in another component contained called 'MyPanel' since this field needs to be placed differently.

As we can see there are many problems with passing variables and composition itself:

Composition:

  1. If i put a <slot></slot> in the tempplate of MyForm for displaying the fields it would be compiled in parent scope, therefore all children (including MyTextField) would not have access to the "model"
  2. If i try to use <MyForm inline-template> i cannot automatically display the form header and footer since all content is being replaced. Additionally when using single file components the compiler will look for all components inside the inline-template which means that i would have to import MyTextInput and MyPanel into MyForm which is not practical. I do not know in advance all components that will never end up in my form!

Passing variables:

  1. If i use the variables directly from "model" (in first TextInput) i receive warning that i am modifying a variable from parent and it will be overwritten on next render (but in this case it will not be overwritten since i am INTENTIONALLY modifying the parent)
  2. I cannot pass the model into second MyTextInput without passing it to MyPanel first. Actually i would have to pass it into EVERY custom component in between. And i do not know in advance how many custom components will there be. Which means that i would have to modify the code of every component that would ever be put into MyForm and require users to pass the data for each custom component they include.
  3. If i would try to properly inform the parent about changes i would need to add v-on: event to every textinput and every custom component in between in order for the event to reach MyForm .

As i have said the component was supposed to be simple and easilly reusable. Requiring users of this component to modify code of every child they put into it and requiring them to add v-on: to every component inside does not seem practical.

Is my idea solvable using Vue.js 2.0 ? I have designed the same component before for AngularJS (1.5) and it was working fine and did not require to add modifications to each child of the form.

I've been using a ui framework based on vue 2.0 and you may get some ideas from its implementation . Based on its implementaion and my little experience with it, I think it's the person who uses your framework's responsibility to assemble the form-model. Also, for a form, we can always easily get all the data to be sent by using fields' value props without v-model 's help.

The framework's doc on form element may also be helpful but it's currently only available in Chinese except for the code samples.

I suggest you to use Form Input Components using Custom Events to pass variables in your form.

Mutating a prop locally is now considered an anti-pattern, eg declaring a prop a and then set this.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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM