Vue を使用してページの右上隅にフローティング/非表示メニューを実装する方法

php中世界最好的语言
リリース: 2018-06-01 11:22:05
オリジナル
2709 人が閲覧しました

今回はVueを使ってページ右上にフローティング・非表示メニューを実装する方法を紹介します Vueを使ってページ右上にフローティング・非表示メニューを実装する場合の注意点は何ですか?ここで実際のケースを見てみましょう。

これは、ほとんどの Web サイトで非常に一般的な機能です。ページの右上隅にあるアバターをクリックしてフローティング メニューを表示するか、アバターを再度クリックしてメニューを非表示にします。

jQuery フロントエンドの包囲ライオンとしては、この機能の実装は非常に簡単であると言えますが、vue ドキュメントをざっと見ただけの初心者にとっては、まだ個人的に落とし穴を踏む必要があります成功するために。

知識ポイント

  • コンポーネントとコンポーネント間通信

  • 計算されたプロパティ

テキスト

1親コンポーネント

これにはシステムのみが関係します現時点ではメニュー この機能はまだルーティングの対象になっていません。

基本的な考え方は、props を通じて showCancel のブール値を子コンポーネントに渡し、イベントを親コンポーネントと子コンポーネントにそれぞれバインドして、システム メニューの表示状態を制御するというものです。親コンポーネントのバインドされたクリック イベントでは、子コンポーネントに渡される showCancel 値がリセットされます。

ここで最初の小さな知識ポイントです - サブコンポーネントの呼び出し:

まず、サブコンポーネントによってレンダリングされるのを待っているカスタム要素を書き込みます:

<t-header :showCancel=showCancel></t-header>
ログイン後にコピー

次に、書き込まれたサブコンポーネントをインポートします:

import THeader from "./components/t-header/t-header";
ログイン後にコピー

次に、登録しますコンポーネント内のサブコンポーネント:

components: {
 THeader
}
ログイン後にコピー

この時点で、新入生は、これらのコード行がサブコンポーネントを タグにマッピングする方法について混乱するかもしれません。公式ドキュメントには次のように書かれています。

コンポーネントを登録するとき (または prop)、ケバブケース (ハイフンで区切られた名前)、キャメルケース (キャメルケースの名前)、またはパスカルケース (単語の最初の文字が大文字になった名前) を使用できます。

HTML テンプレートでは、kebab-case を使用してください。

me たとえば、カスタム要素が の場合、登録されたコンポーネント名は t-header、tHeader、THeader の 3 つの方法で記述できると理解されます。この場合、登録されたコンポーネントは自動的に次のようになります。認識され、 にレンダリングされます。

上記は HTML テンプレートであり、単一ファイル コンポーネントの

このようにして、親コンポーネントのプロトタイプが誕生しました:


<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 を使用して表示と非表示を制御します。親コンポーネントと子コンポーネントの場合は、状況に応じて showCancel 値を変更するだけで済みます。システム メニューのいくつかのオプションのバインディング イベントが親子コンポーネントでバインディング イベントをトリガーしないように注意してください。メニューをクリックするだけではメニューが消えてしまうので、バインディング イベントで .stop が使用されます。つまり、
@click.stop ="doSomething"@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

つまり、すべて問題ありません。このように:

/*父组件自定义元素绑定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);
 }
}
ログイン後にコピー
ログイン後にコピー
しかし、最初の落とし穴の後、私はまだ若すぎることが明らかになりました。悪い例をいくつか示します。

prop の showCancel 値は実際に使用できます。サブコンポーネント ボタンをクリックすると、

this.showCancel=!this.showCancel

によってメニューの表示が実現されます。非表示にしますが、コンソールが開くと、クリックするたびにエラーが発生します: 🎜🎜🎜vue.esm.js?efeb:578 [Vue warn]: 親コンポーネントが再レンダリングされるたびに値が上書きされるため、プロップを直接変更しないでください。代わりに、プロパティの値に基づいてデータまたは計算されたプロパティを使用します。🎜🎜🎜 は、親コンポーネントが再レンダリングされると、この値が上書きされるため、プロパティの値を変更しないことを意味します。

另外,尽管在这个按钮上实现了显示状态的切换,但是点击其他区域的时候,并不会隐藏它,原因是:子组件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>
ログイン後にコピー

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

怎样使用vue mint-ui tabbar(附代码)

怎样使用Vue结合Video.js播放m3u8视频

以上がVue を使用してページの右上隅にフローティング/非表示メニューを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート