vue 2.0封裝model組件

單文件組件

使用單文件組件封裝model的模板孽文、邏輯和樣式,之后就可以在頁(yè)面中調(diào)用此通用組件蜒秤。

model-1.png

需求

model有兩個(gè)使用場(chǎng)景:

  1. 備注/修改密碼(簡(jiǎn)易):
    在屏幕中垂直居中
  2. 添加/修改/展示信息(復(fù)雜):
    距離屏幕頂部200px,內(nèi)容過(guò)長(zhǎng)時(shí)可滾動(dòng)。
  3. 常規(guī)要求(共同點(diǎn)):
    標(biāo)題扎酷,關(guān)閉icon
    點(diǎn)擊確定/關(guān)閉/遮罩檐涝,隱藏model組件

分析上述需求點(diǎn)遏匆,得到如下圖:

model-2.png
  • wrapper
    負(fù)責(zé)遮蓋屏幕
  • inner
    負(fù)責(zé)垂直居中/距頂部200px
  • title
    可變化標(biāo)題
  • content
    可變化的內(nèi)容區(qū)域

方案

  • Prop傳參
    title(標(biāo)題)、show(隱藏/顯示)谁榜、width(寬度)幅聘、type(居中/頂部)
  • 自定義事件
    關(guān)閉model
  • slot分發(fā)
    內(nèi)容區(qū)域可自定義
  • 滾動(dòng)穿透

具體實(shí)現(xiàn)

template

  <div class="model-mask" v-show="show">
    <div :class="[type === 'top' ? 'model-wrapper-top' : 'model-wrapper']" @click="close">
      <div :class="[type === 'top' ? 'model-container-top' : 'model-container']"
        :style="{width:width + 'px'}">
        <div class="model-header">
          <span>{{title}}</span>
          <i class="close-empty" @click="close">
            <Icon
              type="ivu-icon ivu-icon-ios-close-empty"
              size="25"  />
          </i>
        </div>
        <div class="model-body">
          <slot></slot>
        </div>
      </div>
    </div>
  </div>

script

  export default {
  name: 'MyModel',
  props:
  {
    title: String,
    show: Boolean,
    width: Number,
    type: String
  },
  data () {
    return {
      scrollTop: ''
    }
  },
  watch: {
    show: function (val, oldVal) {
      function getScrollTop () {
        return document.body.scrollTop || document.documentElement.scrollTop
      }
      if (val) {
        // 在彈出層顯示之前,記錄當(dāng)前的滾動(dòng)位置
        this.scrollTop = getScrollTop()
        let body = document.querySelector('body')
        body.className = 'not-scroll'
        // 把脫離文檔流的body拉上去窃植!否則頁(yè)面會(huì)回到頂部帝蒿!
        document.body.style.top = -this.scrollTop + 'px'
      }
    }
  },
  methods: {
    close: function (e) {
      function to (scrollTop) {
        document.body.scrollTop = document.documentElement.scrollTop = scrollTop
      }
      let target = e.srcElement || e.target
      if (target.className === 'model-wrapper' ||
          target.className.indexOf('ivu-icon-ios-close-empty') > -1 ||
          target.className === 'model-wrapper-top') {
        this.$emit('close')
        let body = document.querySelector('body')
        body.className = ''
        // 滾回到老地方!
        to(this.scrollTop)
      }
    }
  }
}

style

  <style scoped lang="scss">
.model-mask {
  height: 100%;
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  background: rgba(0, 0, 0, .5);
}
/**
 * 垂直居中
 */
.model-wrapper {
  height: 100%;
  text-align: center;
}
.model-wrapper:before {
  content: "";
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}
.model-container {
  position: relative;
  display: inline-block;
  vertical-align: middle;
  background-color: white;
  text-align: left;
  box-shadow: 0 5px 14px 0 rgba(0,0,0,0.15);
  border-radius: 6px;
  overflow: hidden;
  z-index: 1050;
}
/**
 * 距離頂部100px巷怜,可滾動(dòng)
 */
.model-wrapper-top {
  position: relative;
  height: 100%;
  overflow-x: hidden;
  overflow-y: scroll;
}
.model-container-top {
  margin: 100px auto;
  background-color: white;
  text-align: left;
  box-shadow: 0 5px 14px 0 rgba(0,0,0,0.15);
  border-radius: 6px;
  overflow: hidden;
}
.close-empty {
  position: absolute;
  right: 16px;
  top: 10px;
  overflow: hidden;
  cursor: pointer;
  z-index: 1100;
}
.model-header {
  position: relative;
  height: 45px;
  line-height: 45px;
  padding: 0 20px;
  font-size: 14px;
  color: #999;
  border-bottom: 1px solid #eee;
}
</style>

引用

  <button type="button" @click="showModel">戳我呀</button>
import MyModel from '../componets/model.vue'
export default {
  name: 'test',
  components: {
    MyModel
  },
  data () {
    return {
      show: false
    }
  },
  methods: {
    /**
     * 打開model
     */
    closeModel: function () {
      this.show = false
    },
    /**
     * 關(guān)閉model
     */
    showModel: function () {
      this.show = true
    }
  }
}

引用一

  <my-model title="標(biāo)題" :width="400" :show="show" v-on:close="closeModel">
      <!-- slot -->
      <div class="tips">
          <p>this is content area葛超。</p>
      </div>
    </my-model>

引用二

  <my-model type="top" title="標(biāo)題" :width="400" :show="show" v-on:close="closeModel">
      <!-- slot -->
      <div class="tips">
          <p v-for="i in 50">this is content area暴氏。</p>
      </div>
    </my-model>

demo

  • 垂直居中
model-3.png
  • 距頂部200px,可滾動(dòng)
model-4.png

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绣张,一起剝皮案震驚了整個(gè)濱河市答渔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌侥涵,老刑警劉巖沼撕,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異芜飘,居然都是意外死亡务豺,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門嗦明,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)笼沥,“玉大人,你說(shuō)我怎么就攤上這事招狸【赐兀” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵裙戏,是天一觀的道長(zhǎng)乘凸。 經(jīng)常有香客問(wèn)我,道長(zhǎng)累榜,這世上最難降的妖魔是什么营勤? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮壹罚,結(jié)果婚禮上葛作,老公的妹妹穿的比我還像新娘。我一直安慰自己猖凛,他們只是感情好赂蠢,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著辨泳,像睡著了一般虱岂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上菠红,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天第岖,我揣著相機(jī)與錄音,去河邊找鬼试溯。 笑死蔑滓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播键袱,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼燎窘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蹄咖?” 一聲冷哼從身側(cè)響起荠耽,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎比藻,沒(méi)想到半個(gè)月后铝量,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡银亲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年慢叨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片务蝠。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拍谐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出馏段,到底是詐尸還是另有隱情轩拨,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布院喜,位于F島的核電站亡蓉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏喷舀。R本人自食惡果不足惜砍濒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望硫麻。 院中可真熱鬧爸邢,春花似錦、人聲如沸拿愧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)浇辜。三九已至券敌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奢赂,已是汗流浹背陪白。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工颈走, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膳灶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像轧钓,于是被迫代替她去往敵國(guó)和親序厉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容