2017-02-23 118 views
2

我試圖構建一個可重用組件來處理通過AJAX使用Vue.js提交表單。理想情況下,我想要做的是有一個通用組件,可以用來代替HTML form元素,其中可能包含一組未知的表單元素,例如input,selecttextarea等。Vue.js將數據從插槽傳遞到組件實例

我已經得到了我的組件下面的代碼被命名爲ajax-form

<template> 
    <form class="form" :action="action" :method="method" v-on:submit.prevent="ajaxSubmit"> 
     <slot></slot> 
    </form> 
</template> 

<script> 
module.exports = { 
    props: { 
     action: { 
      required: true, 
      type: String 
     }, 
     method: { 
      default: 'post', 
      required: false, 
      type: String 
     } 
    }, 
    data() { 
     return { 
      formData: {} 
     } 
    }, 
    methods: { 
     ajaxSubmit() { 
      // Do ajax 
     } 
    } 
} 
</script> 

而在我的HTML,我會像下面這樣:

<ajax-form action="http://example.com/do/something"> 
    <input name="first_name" type="text"> 
    <textarea name="about_you"></textarea> 
</ajax-form> 

什麼,我會非常喜歡發生的事情是將所有的表單元素放置在我的組件中,使用它的插槽映射到我的Vue組件實例中的data.formData屬性。因此,在這種情況下,data財產會是什麼樣子:

data: { 
    formData: { 
     first_name: '', 
     about: '' 
    } 
} 

如果我是另一個字段添加到我的HTML組件,我希望這也被映射到Vue的實例的data財產。

有沒有辦法實現這個目標?有沒有一種方法可以告訴Vue,將表單元素通過槽插入組件時,我希望將此元素映射到組件的data中的某些內容?

我曾嘗試加入v-modelv-bind每個表單元素上,看它是否會以某種方式將數據傳遞到組件的數據:

<ajax-form action="http://example.com/do/something"> 
    <input name="first_name" type="text" v-model="formData.first_name"> 
</ajax-form> 

然而,Vue公司抱怨說,無功數據屬性必須他們之前聲明'在模板中使用:

[Vue警告]:屬性或方法「formData」沒有在實例上定義,但在渲染過程中被引用。確保在數據選項中聲明反應數據屬性。

+0

只是想大聲:我不知道你是否可以使用'mounted'(https://開頭vuejs 。org/v2/api /#mounted)方法來獲得對Vue創建的DOM元素的引用,然後遍歷它的子元素(使用jQuery?)並通過'Vue.set'將反應性屬性添加到'this.data'中https://vuejs.org/v2/api/#Vue-set)。 – PatrickSteele

+0

查看此筆http://codepen.io/anon/pen/evYzOv?editors=1011 –

+0

感謝您的建議傢伙。 @PatrickSteele我嘗試了你的建議,但無法再進一步了。我開始認爲這是不可能的。文檔似乎在這裏說明:https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties。 @ShekharJoshi我不確定你瞭解我的問題。我無法提前知道插槽的內容,我希望能夠通過槽和我的「數據」項傳入我的組件之間的元素之間創建反應式綁定。您的建議假定我知道數據等將提前。 – Jonathon

回答

2

由於插槽範圍僅限於父範圍,因此您無法進行所要求的操作。

您可以在全局Vue實例上定義formData,因此現在可以從父範圍訪問它。

const app = new Vue({ 
    el: '#app', 
    data: { 
     formData : {} 
    } 
}); 

現在你可以將它傳遞給形式爲道具:

<ajax-form action="#" :form-data="formData> 
    <input name="first_name" type="text" v-model="formData.first_name"> 
</ajax-form> 
+0

完美。我覺得Vue不會讓我按照我想要的方式做,只需要一個組件傳入插槽中的數據,但這是一個很好的解決方法。 – Jonathon

4

你可以用scopedSlots做到這一點。

的API看起來是這樣的:

<ajax-form action="http://example.com/do/something"> 
    <template scope="{formData}">  
    <input name="first_name" type="text" v-model="formData.first_name"> 
    </template> 
</ajax-form> 

而在ajax-form組件:

<form class="form" :action="action" :method="method" v-on:submit.prevent="ajaxSubmit"> 
    <slot :formData="formData"> 
</form> 
+0

這幫了很多!謝謝。 –

相關問題