a标签传值到另一个页面_Vue组件传值与通信集合
Vue的組件化給前端開發帶來極大的便利,這種依賴數據來控制Dom的模式,區別于以前的開發控制Dom的開發理念,這也導致了一種情況,在Vue中是單向數據流的,意味著只能從父組件向子組件傳值,不允許子組件向父組件傳值。
這樣會防止從子組件意外改變父級組件的狀態,從而導致你的應用的數據流向難以理解。 ---vue教程然而當我們把組件拆分到足夠細的時候,子組件控制父組件的數據,或者兄弟組件之間的傳值就變得尤為突出,這里我將總結各式各樣的傳值,函數調用的方法。
父組件中的通信方法
閱讀完官方文檔后,我們一定會對props有強烈的印象,然而在父組件中可不止有這種通信的方式。
props
- 命名規范
HTML 中的特性名是大小寫不敏感的,所以瀏覽器會把所有大寫字符解釋為小寫字符。這意味著當你使用 DOM 中的模板時,camelCase (駝峰命名法) 的 prop 名需要使用其等價的 kebab-case (短橫線分隔命名) 命名:
- 傳遞靜態或動態 Prop 假如你想傳字符串給子組件只需要給便簽添加屬性就可以了
當然那些非字符串的類型就直接依賴于v-bind進行傳值(Number、Boolean、Array...)
<!-- 動態賦予一個變量的值 --> <blog-post v-bind:title="post.title"></blog-post><!-- 動態賦予一個復雜表達式的值 --> <blog-postv-bind:title="post.title + ' by ' + post.author.name" ></blog-post>- 子組件接收
常見的就是聲明式接收: props: [...] 數組形式
但官方更推薦對象形式的接收,至少為每個prop指定類型
Vue.component('my-component', {props: {// 基礎的類型檢查 (`null` 和 `undefined` 會通過任何類型驗證)propA: Number,// 多個可能的類型propB: [String, Number],// 必填的字符串propC: {type: String,required: true},// 帶有默認值的數字propD: {type: Number,default: 100},// 帶有默認值的對象propE: {type: Object,// 對象或數組默認值必須從一個工廠函數獲取default: function () {return { message: 'hello' }}},// 自定義驗證函數propF: {validator: function (value) {// 這個值必須匹配下列字符串中的一個return ['success', 'warning', 'danger'].indexOf(value) !== -1}}} })type 可以是下列原生構造函數中的一個:
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
使用上我們除了this.prop外還可以使vm.$props(當前組件接收到的 props 對象。Vue 實例代理了對其 props 對象屬性的訪問。)
- 禁用特性繼承
如果你不希望組件的根元素繼承特性,這尤其適合配合實例的 $attrs 屬性使用,你可以在組件的選項中設置 :
當然還有非聲明式的接收 $attrs (2.4.0 新增):
包含了父作用域中不作為 prop 被識別 (且獲取) 的特性綁定 (class 和 style 除外)。當一個組件沒有聲明任何 prop 時,這里會包含所有父作用域的綁定 (class 和 style 除外),并且可以通過 v-bind="$attrs" 傳入內部組件——在創建高級別的組件時非常有用。<base-input label="姓名" class="username-input" placeholder="Enter your username" data-date-picker="activated" ></base-input> Vue.component("base-input", {inheritAttrs: false, //此處設置禁用繼承特性props: ["label"],template: `<label>{{label}}{{$attrs.placeholder}} //這里不用聲明props可以直接調用{{$attrs["data-date-picker"]}}<input v-bind="$attrs"/></label>`,mounted: function() {console.log(this.$attrs);} })provide/inject
provide 和 inject 主要為高階插件/組件庫提供用例。并不推薦直接用于應用程序代碼中。// 父級組件提供 'foo' var Provider = {provide: {foo: 'bar'},// ... }// 子組件注入 'foo' var Child = {inject: ['foo'],created () {console.log(this.foo) // => "bar"}// ... }提示:provide 和 inject 綁定并不是可響應的。這是刻意為之的。然而,如果你傳入了一個可監聽的對象,那么其對象的屬性還是可響應的。更多的用法是用來注入方法的:
// 父級組件提供 'foo' var Provider = {provide: {foo: this.fn},methods:{fn(){console.log('bar')}}// ... }// 子組件注入 'foo' var Child = {inject: ['foo'],created () {this.foo(); // => "bar"}// ... }vm.$children
通過Vue實例代理的$children獲取其子組件的值,為一個類數組,你可以在控制臺中打印出來,里面有子組件中的一切屬性。
vm.$slots
插槽的使用更多在官方文檔中查看,這里顯示基礎的使用方法:
<navigation-link url="/profile">Your Profile </navigation-link>然后你在 的模板中可能會寫為:
<av-bind:href="url"class="nav-link" ><slot></slot> </a>除了用標簽獲取傳遞的數據,我更喜歡用$slots處理,比如在這個輸入框中,你既要設定lable又要設定placeholder,然而它們兩其實是同一個數據,這時候我們可以這樣:
<inputBox :readonly='readonly' v-model='item.contactName'>聯系人</inputBox> <inputBox :readonly='readonly' v-model='item.mobile'>電話</inputBox> var Component = {props: {readonly: {default: false},type: {default: 'text'},value: [String, Number],maxlength: {default: 20}},data() {return {inputValue: this.value}},watch: {value(newValue) {this.inputValue = newValue},inputValue(newValue) {this.$emit('input', newValue)}},template: `<div class='input'><cube-input v-model.trim="inputValue" :placeholder="'請輸入' + this.$slots.default[0].text" :readonly="readonly" :type="type" :maxlength="maxlength"><template v-slot:prepend><slot></slot></template></cube-input></div>`};其他的為ui框架的組件不用在意,重要的是this.$slots.default[0].text這一段對$slots的應用。
小結
通過上面的四種方法,我們可以看出,它們都是可以完成值得傳遞或者獲取的,除了$slots不能傳遞方法函數外,其他三種均可完成。
子組件中的通信方法
首先我們先要理解子組件傳遞的原理,下面這張圖大家在很多的地方都看過了,實際上就是父組件通過prop給子組件下發數據,子組件通過事件給父組件發送信息,而使用的工具為:
$on(evntName)監聽事件; $emit(eventName,optionalPayload)觸發事件; 接下來的方法都是對這個原理實現的變形
v-on / $emit
首先我們來實現一個單向傳遞的例子:
//父組件 <template><child @childHandler="parentHandle"></child> </template><script> export default {data: {message: ''},methods: {parentHandle(send) {this.message = send;}} } </script> //子組件 <template><button @cilck="sendHandle"></button> </template> <script> export default {date: {news:"from children"},methods: {sendHandle() {this.$emit('childHandler',this.news);}} } </script>上面的過程我就不再描述一遍了,你們自己看代碼理解理解,這樣我們就實現了由子組件傳遞數據到父組件。但在更復雜的場景時,我們不僅需要修改父組件的值,還需要通過父組件的值影響到子組件的渲染,也就是實現子父組件的數據雙向綁定。
更多的場景下我們希望其是自動觸發數據交互的,這時我們需要用到watch,現在我們對上面的代碼進行修改一下。
//父組件 <template><child @childHandler="parentHandle" :status="status" :name="name"><button @cilck="emptyHandle">清空</button> </child> </template><script> export default {data: {status:'男',name:'Max.Law'},methods: {parentHandle(send) {this.child.status = send;},emptyHandle(){status = '';}} } </script> //子組件 <template><p><span>姓名:</span>{{name}}</p><p><span>性別:</span>{{childStatus}}</p><button @cilck="sendHandle('男')">男</button><button @cilck="sendHandle('女')">女</button> </template> <script> export default {props: {status: [String, Number],name: [String, Number]},date: {childStatus:this.status},methods: {sendHandle(data) {this.childStatus = data},watch: {status(newValue) {this.childStatus = newValue},childStatus(newValue) {this.$emit('childHandler', newValue)}}, } </script>這里實現的是在子組件的性別狀態繼承于父組件,子組件修改性別的狀態的同時改變父組件的數據以便父組件使用。
我們在使用vue的過程中很清楚,假如子組件直接寫{{status}}來繼承父組件的值,在修改狀態的時候vue會提示不建議直接修改父組件的值來改變子組件(vue中一個重要邏輯,當前組件只處理當前組件的數據),所以我們使用childStatus來接收父組件的值。
那我們如何做到子組件的改變能影響父組件,父組件更新值時又能影響子組件呢?這時候重點都在這個watch上:
當status改變時則改變childStatus的值, 當childStatus改變時,用上面的方法與父組件通信,改變父組件的值
這樣我們就完成子父組件的數據雙向綁定,整個過程為: 1. 給子組件幫一個通信方法 2. 綁定一個傳值對象 3. 監控數據的變化
看到這里有沒有熟悉的感覺,是不是跟 v-modle 很像,vue提供的雙向綁定的指令,而 v-modle 的本質就是綁定了一個input的方法,和一個value值,這時候我們就能把上面的雙向數據綁定的方法簡化了(v-modle是在本組件內實現雙向綁定,并沒有做到子父組件雙向綁定)
v-model/vm.$emit
還記得我上面講$slot的代碼嗎?這里我們簡化一下:
//父組件 <template><inputBox :readonly='readonly' v-model='brand'>設備品牌</inputBox> </template><script> export default {data: {brand:'默認'} } </script> //子組件 <template><div><h1><slot></slot></h1><input v-model="inputValue"></input></div> </template><script> export default {props: {value: [String, Number]},data() {inputValue: this.value},watch: {value(newValue) {this.inputValue = newValue},inputValue(newValue) {this.$emit('input', newValue)}} } </script>這時候,我們不僅可以修改子組件中的輸入框值,還是能同時改變父組件的值,這在做上傳表單的時候尤為重要,保證我們父組件一直都是獲取用戶最新輸入的值。(這個在我做微信公眾號一個表單項目時候突發奇想的實現)
this.$parent
這個是vue提供的api,使用也很簡單,場景一般適合在父組件寫入多個子組件需要調用的公共方法,比provide/inject占用性能要低,也更明確作用域。
只需要在父組件注冊方法,在子組件這樣使用: this.$parent.parentFn(); 這里要注意層級,也許是孫組件,或者從孫組件,可以這樣調用: this.$parent.$parent.grandfatherFn(); 只需要打印出當前的this.$parent查看,確定層級即可。
好了,上面就是 《 Vue組件傳值與通信集合 》的全部內容了,希望能夠對你有所幫助,如有疑問歡迎留言~
總結
以上是生活随笔為你收集整理的a标签传值到另一个页面_Vue组件传值与通信集合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 广升麻的功效与作用、禁忌和食用方法
- 下一篇: 生川芎的功效与作用、禁忌和食用方法