この記事では主に、ページの右上隅に一時停止/非表示にできるシステム メニューを実装するための Vue を紹介します。実装のアイデアは、ブール値 showCancel を props を通じて子コンポーネントに渡し、イベントを親コンポーネントにバインドすることです。それぞれの子コンポーネントでシステム メニューの表示ステータスを制御します。必要な友達はそれを参照してください
これは、ほとんどの Web サイトで非常に一般的な機能です。ページの右上隅にあるアバターをクリックしてフローティング メニューを表示するか、アバターをもう一度クリックしてメニューを非表示にします。メニュー。
jQuery フロントエンドの包囲ライオンとしては、この機能の実装は非常に簡単であると言えますが、vue ドキュメントをざっと見ただけの初心者にとっては、まだ個人的に落とし穴を踏む必要があります成功するために。
知識ポイント
コンポーネントとコンポーネント間通信
計算されたプロパティ
テキスト
1親コンポーネント
これにはシステムのみが関係します現時点ではメニュー この機能はまだルーティングの対象になっていません。
基本的な考え方は、props を通じて showCancel のブール値を子コンポーネントに渡し、イベントを親コンポーネントと子コンポーネントにそれぞれバインドして、システム メニューの表示状態を制御するというものです。親コンポーネントのバインドされたクリック イベントでは、子コンポーネントに渡される showCancel 値がリセットされます。
これには、最初の小さな知識ポイント、つまりサブコンポーネントの呼び出しが含まれます:
まず、サブコンポーネントのレンダリングを待機するカスタム要素を書き込みます:
<t-header :showCancel=showCancel></t-header>
次に、書き込まれたサブコンポーネントをインポートします:
import THeader from "./components/t-header/t-header";
その後、登録しますコンポーネント内のサブコンポーネント:
components: { THeader }
この時点で、新入生は、これらのコード行がサブコンポーネントを
コンポーネント (またはプロップ) を登録するときは、ケバブケース (ダッシュ区切りの名前)、キャメルケース (キャメルケースの名前)、またはパスカルケース (単語の最初の文字を大文字にした名前) を使用できます。テンプレートは、kebab-case を使用してください。
私の理解では、(たとえば) カスタム要素が
上記は HTML テンプレートであり、単一ファイル コンポーネントの で指定されています。また、コンポーネントのオプションで使用される文字列テンプレートもあります。 template: "" 指定されたテンプレート。文字列テンプレートを使用する場合、カスタム タグは 3 つの方法で記述できます。詳細については、コンポーネントの命名規則に関する公式ドキュメントを参照してください。
このようにして、親コンポーネントのプロトタイプが誕生しました:
<t-header :showCancel=showCancel></t-header>
<script> import THeader from "./components/t-header/t-header"; 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>
ピットを踏む前のアイデアに従って、v-show を使用して表示を制御し、子コンポーネントが受信した後に非表示にします。次に、親コンポーネントと子コンポーネントのバインドされたクリック イベントで、値を変更する必要があるのは、親コンポーネントと子コンポーネントのバインディング イベントをトリガーしないことだけです。システム メニューのいくつかのオプションのバインディング イベント - メニューをクリックするだけではメニューが消えるわけではないため、バインディング イベントでは .stop が使用されます。つまり
@click.stop="doSomething"</コード><p><br/>それで、すべてがうまくいき、次のようになります: <code>@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 "./components/t-header/t-header"; export default { name: "app", components: { THeader }, data() { return { showCancel: false }; }, methods: { hideCancel() { this.showCancel = false; }, switchShow(val) { this.showCancel = val; } } }; </script> /*子组件*/
Title
你好,管理员!
<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 は、ページの右上隅にフローティング/非表示のシステム メニューを実装します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。