v-model 用在組件中


官方文檔:

  使用自定義事件的表單輸入組件

官方也說明了,v-model只不過是一個語法糖而已,真正的實現靠的還是

1.  v-bind :  綁定響應式數據
2.  觸發 input 事件 並傳遞數據  (核心和重點)

大體就是:

   監聽原生組件的事件, 當獲取到原生組件的值后把值通過調用 $emit('input' ,data) 方法去觸發 input事件 
 
demo:
  父組件代碼:
<template>
  <div class="hello">
       <button @click="ifShow=!ifShow">點擊顯示</button>
       <show-alert v-model="ifShow"></show-alert>
  </div>
</template>

<script>
import showAlert from './showAlert.vue'
export default {
  name: 'HelloWorld',
  components:{
      showAlert,
  },
  data () {
    return {
            ifShow:false,
    }
  }
}
</script>

  子組件代碼:

<template>
    <div id="showAlert" :value="value" v-if="ifValue">
        <div>showAlert 內容</div>
        <button class="close" @click="ifValue=false">關閉</button>
    </div>
</template>

<script>
    export default{
        props:{
            value:{ type:Boolean, default:false, }
        },
        data:function(){
            return{
                ifValue:false,
            }
        },
        watch:{
            value(bool){
                this.ifValue=bool;
                console.log('bool='+ bool);
            },
            ifValue(val){
                /*使用了v-model的組件會自動監聽 input 事件, * 並把這個input事件所攜帶的值 傳遞給v-model所綁定的屬性, * 這樣組件內部的值就給到了父組件了 */
                this.$emit('input',val);//傳值給父組件, 讓父組件監聽到這個變化
            }
        },
    }
</script>

<style scoped>
    .close{
        background:red;
        color:white;
    }
</style>

    實現效果:

  點擊顯示按鈕以后:

  前提: this.$emit('input',data);

  點擊子組件關閉按鈕后:

  如果未加this.$emit('input',data);

  點擊子組件關閉按鈕后:

  如果未通過$emit把值傳到父組件, 則父組件監聽不到子組件的變化.

 

 

====================================================================

封裝一個可復用的彈窗組件

<!-- 
    彈出窗口組件,
    調用方法:
    父組件import 當前vue文件, 在對應的components中注冊即可使用,
    注意:
    需要在父組件給一個boolean的屬性 通過v-model的形式關聯即可
    其他屬性看下方注釋,

    params(父組件調用 標簽屬性):
    title-info      彈出框顯示文字
    left-button     左邊按鈕文字
    right-button    右邊按鈕文字
    left-click      左邊按鈕點擊回調函數
    right-click     右邊按鈕點擊回調函數

    中間部分可以從父元素自定義設置通過slot放入
    例子:
    <show-model>
        <p slot="reference">111</p>
    </show-model>

    例子:
    <show-model 
        v-model="flag" 
        title-info="優惠碼輸入錯誤,請重試"
        left-button="取消"
        right-button="確定"
        @left-click="left_button"
        @right-click="right_button"></show-model>

    ****
    watch中增加.
    當彈出窗彈出時,阻止后面頁面可以滾動的問題
 -->
<template>
    <div class="model-wrapper" :value="value" v-if="ifValue">
        <div class="mask" @click="close_click"></div>
        <div class="model-content">
            <p v-if="titleInfo">{{titleInfo}}</p>
            <div class="button-group" v-if="leftButton || rightButton">
                <div v-if="leftButton" @click="left_click">{{leftButton}}</div>
                <div v-if="rightButton" @click="right_click">{{rightButton}}</div>
            </div>
        </div>
    </div>
</template>

<script>
    export default{
        props:{
            value:{
                type:Boolean,
                default:false
            },
            titleInfo:{
                type:String,
                default:''
            },
            leftButton:{
                type:String
            },
            rightButton:{
                type:String
            }
        },
        data:function(){
            return {
                ifValue:false,
            }
        },
        methods:{
            close_click:function(){
                this.$emit('close-click');
            },
            left_click:function(){
                this.$emit('left-click');
            },
            right_click:function(){
                this.$emit('right-click');
            }
        },
        watch:{
            value(bool){
                this.ifValue=bool;
            },
            ifValue(val){
                this.$emit('input',val);
            }
        }
    }
</script>

<style scoped>
    .model-wrapper{
        width:100%;
        height:100%;
        position:fixed;
        top:0;
        left:0;
        z-index:999;
    }
    .mask{
        width:100%;
        height:100%;
        position:absolute;
        left:0;
        top:0;
        z-index:1;
        background-color:rgba(0,0,0,0.5);
    }
    .model-content{
        width:80%;
        background:white;
        position:absolute;
        top:50%;
        left:50%;
        transform:translate(-50%,-50%);
        z-index:10;
    }
    .button-group{
        margin-top:40px;
        display:flex;
        padding:0 10px 10px;
    }
    .button-group div{
        flex:1;
        height:40px;
        line-height:40px;
        box-sizing:border-box;
        cursor:pointer;
    }
    .button-group div:first-child{
        background:#000;
        color:#fff;
    }
    .button-group div:last-child{
        border:1px solid gray;
    }
</style>

在首頁調用

    <button @click="showModel">點擊顯示彈窗</button>
    <show-model v-model="ifShowModel" titleInfo="嘿嘿嘿" leftButton="確定" rightButton="取消" @close-click="close_click" @left-click="left_click" @right-click="right_click"     ></show-model>
    showModel:function(){
          this.ifShowModel=true;
          
      },
      close_click:function(){
          this.ifShowModel=false;
      },
      left_click:function(){
          this.ifShowModel=false;
      },
      right_click:function(){
          this.ifShowModel=false;
      }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM