>웹 프론트엔드 >JS 튜토리얼 >Vue는 페이지 오른쪽 상단에 부동/숨겨진 시스템 메뉴를 구현합니다.

Vue는 페이지 오른쪽 상단에 부동/숨겨진 시스템 메뉴를 구현합니다.

不言
不言원래의
2018-05-05 10:54:172176검색

이 기사에서는 페이지 오른쪽 상단에 일시 중지/숨길 수 있는 시스템 메뉴를 구현하기 위해 Vue를 주로 소개합니다. 구현 아이디어는 부울 값 showCancel을 소품을 통해 하위 구성 요소에 전달하고 이벤트를 상위 구성 요소에 바인딩하는 것입니다. 시스템 메뉴 표시 상태를 각각 제어하는 ​​하위 구성요소입니다. 필요한 친구들은 참고하면 됩니다

페이지 오른쪽 상단에 있는 아바타를 클릭하면 페이지의 다른 곳을 클릭하거나 아바타를 다시 클릭하면 숨길 수 있습니다. 메뉴.

jQuery 프론트엔드 공성사자로서 이 기능을 구현하는 것은 매우 쉽다고 할 수 있지만, vue 문서를 이제 막 본 초보자에게는 여전히 개인적으로 넘어야 할 함정이 있습니다. 성공하기 위해.

지식 포인트

  • 구성 요소 및 구성 요소 간 통신

  • 계산된 속성

Text

1. 상위 구성 요소

이것은 시스템에만 관련됩니다. 현재 메뉴 이 기능은 아직 라우팅에 포함되지 않습니다.

기본 아이디어는 props를 통해 showCancel의 부울 값을 하위 구성 요소에 전달하고 이벤트를 각각 상위 및 하위 구성 요소에 바인딩하여 시스템 메뉴의 표시 상태를 제어하는 ​​것입니다. 상위 구성 요소의 바운드 클릭 이벤트에서 하위 구성 요소에 전달된 showCancel 값이 재설정됩니다.

여기에는 첫 번째 작은 지식 포인트가 포함됩니다 - 하위 구성 요소 호출:

먼저 하위 구성 요소가 렌더링될 때까지 기다리는 사용자 정의 요소를 작성합니다.

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

그런 다음 작성된 하위 구성 요소를 가져옵니다.

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

그런 다음 등록합니다. 구성 요소의 하위 구성 요소:

components: {
 THeader
}

이 시점에서 신입생은 이러한 코드 줄이 하위 구성 요소를 19d41f1de6b48708f8fbbade5bd62dd3 태그에 매핑하는 방법에 대해 혼란스러울 수 있습니다. 공식 문서에는 다음과 같이 나와 있습니다. :

컴포넌트(또는 prop)를 등록할 때 kebab-case(대시로 구분된 이름 지정), camelCase(카멜 케이스 이름 지정) 또는 PascalCase(단어의 첫 글자를 대문자로 한 이름)를 사용할 수 있습니다. template, please use kebab-case;

제가 이해한 바에 따르면, (예를 들어) custom 요소가 19d41f1de6b48708f8fbbade5bd62dd3인 경우 등록된 구성 요소 이름은 t-header, tHeader 및 THeader의 세 가지 방법으로 작성할 수 있습니다. 이 경우 등록된 구성요소는 자동으로 인식되어 19d41f1de6b48708f8fbbade5bd62dd3로 렌더링됩니다.

위의 내용은 단일 파일 구성 요소에서 d477f9ce7bf77f53fbcf36bec1b69b7adcdc0fa59b5fea5bdae0d810c3919fcd으로 지정되는 HTML 템플릿이며 구성 요소 옵션에서 사용되는 문자열 템플릿도 있습니다. 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>

피트를 밟기 전 아이디어에 따르면 v-show를 사용하여 하위 구성 요소가 수신된 후 디스플레이를 제어하고 숨깁니다. 그런 다음 상위 및 하위 구성 요소의 바인딩된 클릭 이벤트에서 상황에 따라 showCancel만 변경하면 됩니다. 시스템 메뉴에 있는 여러 옵션의 바인딩 이벤트 - 메뉴를 클릭만 하면 사라지기 때문에 바인딩 이벤트에 .stop이 사용됩니다. 즉

@click.stop="doSomething" code><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 경고]: 상위 구성 요소가 다시 렌더링될 때마다 값을 덮어쓰게 되므로 소품을 직접 변경하지 마세요. . 대신 prop의 값을 기반으로 데이터 또는 계산된 속성을 사용하세요.🎜🎜🎜즉, prop 값을 수정하지 마세요. 상위 구성 요소가 다시 렌더링되면 이 값이 덮어쓰여지기 때문입니다.🎜🎜또한, 표시 상태 전환은 버튼에 구현되어 있지만 다른 영역을 클릭하면 숨겨지지 않습니다. 이유는 하위 컴포넌트의 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으로 문의하세요.