首頁  >  文章  >  web前端  >  Vue在頁面右上角實現可懸浮/隱藏的系統選單

Vue在頁面右上角實現可懸浮/隱藏的系統選單

不言
不言原創
2018-05-05 10:54:172142瀏覽

這篇文章主要介紹了Vue在頁面右上角實現可懸浮/隱藏的系統選單,實現想法大概是透過props將showCancel這個Boolean值傳遞到子組件,對父子組件分別綁定事件,來控制這個系統選單的顯示狀態。需要的朋友可以參考下

這是大多數網站很常見的功能,點擊頁面右上角頭像顯示一個懸浮選單,點擊頁面其他位置或再次點擊頭像則選單隱藏。

作為一個jQuery前端攻城獅實現這個功能可以說是很easy了,但是對只剛粗看了一遍vue文檔的菜鳥來說,坑還是要親自踩過才算圓滿。

知識點

  • #元件與元件間通訊

  • #計算屬性

正文

#1.父元件

這裡暫時只涉及系統選單這一功能,因此路由暫未涉及。

基本想法是:透過props將showCancel這個Boolean值傳遞到子元件,對父子元件分別綁定事件,來控制這個系統選單的顯示狀態。其中在父元件的綁定click事件中,將傳入子元件的showCancel值重設。

這裡就涉及第一個小知識點-子元件呼叫:

先寫好等待被子元件渲染的自訂元素:

<t-header :showCancel=showCancel></t-header>

接著import寫好的子元件:

import THeader from "./components/t-header/t-header";

然後在元件中註冊子元件:

components: {
 THeader
}

到這裡,新入坑的同學可能會比較疑惑這幾行程式碼是怎樣把子元件對應到19d41f1de6b48708f8fbbade5bd62dd3標籤的,官方文件是這樣說的:

當註冊元件(或prop) 時,可以使用kebab-case (短橫線分隔命名)、camelCase (駝峰式命名) 或PascalCase (單字首字母大寫命名);

在HTML 範本中,請使用kebab-case;

我的理解是(舉例),當自訂元素為19d41f1de6b48708f8fbbade5bd62dd3時,註冊元件名稱可以有三種寫法:t-header、 tHeader和THeader,在這種情況下註冊的元件會自動識別並渲染到19d41f1de6b48708f8fbbade5bd62dd3。

要注意的是,以上使用的是HTML 模板,是在單一檔案元件裡用d477f9ce7bf77f53fbcf36bec1b69b7adcdc0fa59b5fea5bdae0d810c3919fcd指定的模板;另外存在一種字串模板,是用在組件選項裡用template: "" 指定的模板。使用字串範本時,自訂標籤可以用三種寫法,具體情況請移步官方文件 元件命名約定。

這樣父元件的雛形就誕生了:


<script>
 import THeader from &quot;./components/t-header/t-header&quot;;
 export default {
 name: "app",
 components: {
  THeader
 },
 data() {
  return {
  showCancel: false
  };
 },
 methods: {
  hideCancel() {
  this.showCancel = false;
  }
 }
 };
</script>

2. 子元件

子元件中.cancel為開啟系統選單的按鈕,.cancel-p為系統選單,最開始是這個樣子:

<template>
 <p class="header-wrapper">
 /*这里是logo和title*/
 ...
 /*这里是用户名和按钮*/
 <p class="info-wrapper">
  <span class="username">你好,管理员!</span>
  <span class="cancel" @click.stop="switchCancelBoard">
  <p class="cancel-p" v-show="showCancel">
   <ul>
   <li @click.stop="doSomething" title="用户设置">设置 </li>
   <li @click.stop="doSomething" title="退出登录">退出 </li>
   </ul>
  </p>
  </span>
 </p>
 </p>
</template>

# #依照踩坑之前的思路,在子組件接到showCancel值後用v-show控制顯示隱藏,那麼在父子組件的綁定click事件中只需要根據情況更改showCancel值就可以了,只要注意對系統菜單內幾個選項的綁定事件不要觸發父子元件上的綁定事件-總不能一點選單它就沒了,所以在綁定事件中用到了.stop,即


@click.stop ="doSomething"

於是萬事大吉,也就是像這樣:

<script>
 export default {
 props: {
  showCancel: {
  type: Boolean
  }
 },
 methods: {
  doSomething() {},
  switchCancelBoard() {
  this.showCancel = !this.showCancel;
  }
 },
 computed: {
  ifShowCancel() {
  return this.showCancel;
  }
 }
 };
</script>

##然而第一波踩坑之後一起表明顯然我還是太年輕。以下是一些不好的示範:

prop來的showCancel值的確可以用,點擊子元件按鈕的時候,

this.showCancel=!this.showCancel

#實作了選單的顯示/隱藏,但一開啟控制台,每次點擊貢獻了一則報錯:

vue.esm.js?efeb:578 [Vue warn] : Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value.

###################################問題,因為父元件一旦re-render,這個值就會被覆蓋;######另外,儘管在這個按鈕上實現了顯示狀態的切換,但是點擊其他區域的時候,並不會隱藏它,原因是:子元件prop值的變化並沒有影響到父元件,因此showCancel的值一直保持初始值沒有變化,而只有在這個值被更新時才會觸發子元件中相關值的更新。 ######——好吧,那麼老實的用一個計算屬性接收showCancel值,這樣實現點擊子元件控制系統選單的狀態切換;###

获得了计算属性ifShowCancel,组件相应的变成了v-show="ifShowCancel",我试图在绑定事件里通过this.ifShowCancel=!this.ifShowCancel切换菜单状态,报错,得到报错信息:Computed property "ifShowCancel" was assigned to but it has no setter;

明白了,要以直接赋值的形式改变计算属性ifShowCancel的值,需要一个setter函数,但是setter函数中无法修改prop值,因此在getter中也就无法通过return this.showCancel来更新这个计算属性,所以这个方法貌似也行不通;

到此为止,好像路都成了堵死状态:prop值不能改->要用计算属性;计算属性不能改->需要setter;而写入了getter、setter,计算属性的值依赖于prop值->prop值不能改。——一个堪称完美的闭环诞生了!

走投无路之际我想起了$emit和$on这一对。

3. 父子互相通信

前边的prop实现了从父到子的单向通信,而通过$emit和$on,就可以实现从子组件到父组件的通信:这不能直接修改父组件的属性,但却可以触发父组件的指定绑定事件,并将一个值传入父组件。

在这一步我摒弃了点击按钮时的去操作子组件内属性的想法,既然计算属性ifShowCancel依赖于prop值,那么就在点击按钮时,通过$emit触发父组件的事件,并将需要修改的属性值传入父组件,于是:

/*父组件自定义元素绑定switch-show事件*/
<t-header :showCancel=showCancel @switch-show="switchShow"></t-header>
// 父组件js
methods: {
 //会被子组件$emit触发的方法
 switchShow(val) {
 this.showCancel = val;
 }
}
// 子组件js
methods: {
 //按钮上的绑定click事件
 switchCancelBoard() {
 this.$emit("switch-show", this.ifShowCancel);
 }
}

这样处理流程就变成了:点击按钮->作为计算属性的ifShowCancel值传入父组件并触发父组件事件,对showCancel赋值->父组件属性更新->触发子组件prop更新->触发重新compute,更新ifShowCancel值->v-show起作用。
另外在点击其他区域时,通过父组件绑定的click事件,就可以重置showCancel值,进而隐藏掉出现的系统菜单。

下边放出这个功能的完整代码。

4. 完整代码

/*父组件*/

<script>
 import THeader from &quot;./components/t-header/t-header&quot;;
 export default {
 name: "app",
 components: {
  THeader
 },
 data() {
  return {
  showCancel: false
  };
 },
 methods: {
  hideCancel() {
  this.showCancel = false;
  },
  switchShow(val) {
  this.showCancel = val;
  }
 }
 };
</script>

/*子组件*/

<script>
 export default {
 props: {
  showCancel: {
  type: Boolean
  }
 },
 methods: {
  doSomething() {},
  switchCancelBoard() {
  // this.ifShowCancel = !this.showCancel;
  this.$emit("switch-show", !this.ifShowCancel);
  }
 },
 computed: {
  ifShowCancel() {
  return this.showCancel;
  }
 }
 };
</script>

相关推荐:

Vue 按键修饰符处理事件的方法

Vue如何制作图片轮播组件(附代码)

以上是Vue在頁面右上角實現可懸浮/隱藏的系統選單的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn