Vue.js 전투 2.x 나 가이드 (13)의 이벤트 핸들러

 그림

13 개 기본 구성 요소
13.1 기본 예제
뷰 컴포넌트 예시 :
 
버튼 - 카운터라는 새로운 구성 요소를 정의 //
 
Vue.component (버튼 카운터 '{
 
  데이터 : 함수 () {
 
    {반환
 
      수 : 0
 
    }
 
  },
 
  템플릿 : '<버튼 V-에 = "계산 ++"를 클릭>. 당신은 저를 클릭 {{count} 개 회 </ 버튼>'
 
})
 
예 뷰 컴포넌트는 재사용하고, 이름을 가진 <버튼 카운터>이 예이다. 우리가 사용하는 사용자 지정 요소로이 구성 요소에 새 뷰를 통해 루트 인스턴스 뷰를 만들 수 있습니다 :
 
<DIV ID = "구성 요소-데모">
 
  <버튼 카운터> </ 버튼 카운터>
 
</ DIV>
 
새로운 뷰 (은 {: '# 구성 요소 - 데모'})
 
13.2 재사용 부품
당신은 부품 재사용의 모든 숫자가 될 수 있습니다 :
 
<DIV ID = "구성 요소-데모">
 
  <버튼 카운터> </ 버튼 카운터>
 
  <버튼 카운터> </ 버튼 카운터>
 
  <버튼 카운터> </ 버튼 카운터>
 
</ DIV>
 
데이터는 함수이어야
우리는 <버튼 - 카운터> 요소를 정의 할 때, 당신은이 같은 객체에 직접 데이터를 제공하지 않는 것을 발견 할 수있다 :
 
데이터 : {
 
  수 : 0
 
}
 
대신, 데이터 기능 구성 요소의 옵션이 있어야합니다, 개체의 별도의 사본을 유지할 수 있습니다 각 인스턴스가 반환됩니다
 
데이터 : 함수 () {
 
  {반환
 
    수 : 0
 
  }
 
}
 
이 규칙은 뷰가 아닌 경우, 다른 모든 인스턴스에 영향을 미치는 등 다음 코드처럼 보일 수있는 버튼을 클릭합니다 :
 
13.3 조직 구성 요소
응용 프로그램은 일반적으로 중첩 된 조립 조직 트리의 형태로 될 것입니다 :
 
  그림
 
 
 
템플릿을 사용하려면, 이러한 구성 요소는 뷰를 식별 할 수 있도록하기 위해 등록해야합니다. 등록 글로벌 및 지역 등록 : 등록 유형의 두 가지 구성 요소가 있습니다. 이 시점에서, 우리는 Vue.component 글로벌 등록하여 단지 구성 요소는 다음과 같습니다
 
Vue.component ( '내 구성 요소 이름', {
 
  // ... 옵션 ...
 
})
 
이 모든 뷰 루트 인스턴스에 등록 된 후 구성 요소 글로벌 등록을 사용할 수있는 새로 (새로운 뷰에 의해), 또한 구성 요소 트리에 하위 구성 요소의 모든 템플릿이 포함되어 만들었습니다.
 
소유하여 서브 어셈블리 13.4 송신 데이터
블로그 구성 요소에 제목을 제공하기 위해, 우리는 허용 소품에서의 구성 요소 목록에 포함 할 수있는 소품 옵션을 사용할 수 있습니다 :
 
Vue.component ( '블로그 게시물', {
 
  소품 : '제목',
 
  템플릿 : '<H3> {{제목}} </ H3>'
 
})
 
기본 구성 요소는 소품의 수는, 값이 어떤 소품에 전달 될 수 있습니다 할 수 있습니다.
 
소품을 등록 할 후 전달 사용자 정의 속성으로 다음과 같은 데이터를 넣을 수 있습니다 :
 
<블로그 게시물 제목 = "뷰 나의 여행">
 
</ 블로그 포스트> <= "뷰와 블로깅"블로그 게시물 제목> </ 블로그 포스트>
 
<블로그 게시물 제목 = "뷰가 너무 재미 왜"> </ 블로그 포스트>
 
然而在一个典型的应用中,你可能在 data 里有一个博文的数组:
 
new Vue({
 
  el: '#blog-post-demo',
 
  data: {
 
    posts: [
 
      { id: 1, title: 'My journey with Vue' },
 
      { id: 2, title: 'Blogging with Vue' },
 
      { id: 3, title: 'Why Vue is so fun' }
 
    ]
 
  }
 
})
 
并想要为每篇博文渲染一个组件:
 
<blog-post
 
  v-for="post in posts"
 
  v-bind:key="post.id"
 
  v-bind:title="post.title"
 
></blog-post>
 
13.5单个根元素
当构建一个 <blog-post> 组件时,你的模板最终会包含的东西远不止一个标题:
 
<h3>{{ title }}</h3>
 
最最起码,你会包含这篇博文的正文:
 
<h3>{{ title }}</h3><div v-html="content"></div>
 
然而如果你在模板中尝试这样写,Vue 会显示一个错误,并解释道 every component must have a single root element (每个组件必须只有一个根元素)。你可以将模板的内容包裹在一个父元素内,来修复这个问题,例如:
 
<div class="blog-post">
 
  <h3>{{ title }}</h3>
 
  <div v-html="content"></div>
 
</div>
 
看起来当组件变得越来越复杂的时候,我们的博文不只需要标题和内容,还需要发布日期、评论等等。为每个相关的信息定义一个 prop 会变得很麻烦:
 
<blog-post
 
  v-for="post in posts"
 
  v-bind:key="post.id"
 
  v-bind:title="post.title"
 
  v-bind:content="post.content"
 
  v-bind:publishedAt="post.publishedAt"
 
  v-bind:comments="post.comments">
 
</blog-post>
 
所以是时候重构一下这个 <blog-post> 组件了,让它变成接受一个单独的 post prop:
 
<blog-post
 
  v-for="post in posts"
 
  v-bind:key="post.id"
 
  v-bind:post="post">
 
</blog-post>
 
Vue.component('blog-post', {
 
  props: ['post'],
 
  template: `
 
    <div class="blog-post">
 
      <h3>{{ post.title }}</h3>
 
      <div v-html="post.content"></div>
 
    </div>
 
  `
 
})
 
13.6监听子组件事件
在我们开发 <blog-post> 组件时,它的一些功能可能要求我们和父级组件进行沟通。例如我们可能会引入一个辅助功能来放大博文的字号,同时让页面的其它部分保持默认的字号。
 
在其父组件中,我们可以通过添加一个 postFontSize 数据属性来支持这个功能:
 
new Vue({
 
  el: '#blog-posts-events-demo',
 
  data: {
 
    posts: [/* ... */],
 
    postFontSize: 1
 
  }
 
})
 
它可以在模板中用来控制所有博文的字号:
 
<div id="blog-posts-events-demo">
 
  <div :style="{ fontSize: postFontSize + 'em' }">
 
    <blog-post
 
      v-for="post in posts"
 
      v-bind:key="post.id"
 
      v-bind:post="post"
 
    ></blog-post>
 
  </div>
 
</div>
 
现在我们在每篇博文正文之前添加一个按钮来放大字号:
 
Vue.component('blog-post', {
 
  props: ['post'],
 
  template: `
 
    <div class="blog-post">
 
      <h3>{{ post.title }}</h3>
 
      <button>
 
        Enlarge text
 
      </button>
 
      <div v-html="post.content"></div>
 
    </div>
 
  `
 
})
 
问题是这个按钮不会做任何事:
 
<button>
 
  Enlarge text
 
</button>
 
当点击这个按钮时,我们需要告诉父级组件放大所有博文的文本。幸好 Vue 实例提供了一个自定义事件的系统来解决这个问题。父级组件可以像处理 native DOM 事件一样通过 v-on 监听子组件实例的任意事件:
 
<blog-post
 
  ...
 
  v-on:enlarge-text="postFontSize += 0.1">
 
</blog-post>
 
同时子组件可以通过调用内建的 $emit 方法 并传入事件名称来触发一个事件:
 
<button v-on:click="$emit('enlarge-text')">
 
  Enlarge text
 
</button>
 
有了这个 v-on:enlarge-text="postFontSize += 0.1" 监听器,父级组件就会接收该事件并更新 postFontSize 的值。
 
使用事件抛出一个值
有的时候用一个事件来抛出一个特定的值是非常有用的。例如我们可能想让 <blog-post> 组件决定它的文本要放大多少。这时可以使用 $emit 的第二个参数来提供这个值:
 
<button v-on:click="$emit('enlarge-text', 0.1)">
 
  Enlarge text
 
</button>
 
然后当在父级组件监听这个事件的时候,我们可以通过 $event 访问到被抛出的这个值:
 
<blog-post
 
  ...
 
  v-on:enlarge-text="postFontSize += $event">
 
</blog-post>
 
或者,如果这个事件处理函数是一个方法:
 
<blog-post
 
  ...
 
  v-on:enlarge-text="onEnlargeText">
 
</blog-post>
 
那么这个值将会作为第一个参数传入这个方法:
 
methods: {
 
  onEnlargeText: function (enlargeAmount) {
 
    this.postFontSize += enlargeAmount
 
  }
 
}
 
在组件上使用 v-model
 
自定义事件也可以用于创建支持 v-model 的自定义输入组件。记住:
 
<input v-model="searchText">
 
等价于:
 
<input
 
  v-bind:value="searchText"
 
  v-on:input="searchText = $event.target.value"
 
>
 
当用在组件上时,v-model 则会这样:
 
<custom-input
 
  v-bind:value="searchText"
 
  v-on:input="searchText = $event">
 
</custom-input>
 
为了让它正常工作,这个组件内的 <input> 必须:
 
将其 value 特性绑定到一个名叫 value 的 prop 上
 
在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出
 
写成代码之后是这样的:
 
Vue.component('custom-input', {
 
  props: ['value'],
 
  template: `
 
    <input
 
      v-bind:value="value"
 
      v-on:input="$emit('input', $event.target.value)"
 
    >
 
  `
 
})
 
现在 v-model 就应该可以在这个组件上完美地工作起来了:
 
<custom-input v-model="searchText"></custom-input>
 
13.7通过插槽分发内容
和 HTML 元素一样,我们经常需要向一个组件传递内容,像这样:
 
<alert-box>
 
  Something bad happened.
 
</alert-box>
 
幸好,Vue 自定义的 <slot> 元素让这变得非常简单:
 
Vue.component('alert-box', {
 
  template: `
 
    <div class="demo-alert-box">
 
      <strong>Error!</strong>
 
      <slot></slot>
 
    </div>
 
  `
 
})
 
13.8动态组件
有的时候,在不同组件之间进行动态切换是非常有用的,
 
可以通过 Vue 的 <component> 元素加一个特殊的 is 特性来实现:
 
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
 
<component v-bind:is="currentTabComponent"></component>
 
13.9解析 DOM 模板时的注意事项
有些 HTML 元素,诸如 <ul>、<ol>、<table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li>、<tr> 和 <option>,只能出现在其它某些特定的元素内部。
 
这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:
 
<table>
 
  <blog-post-row></blog-post-row>
 
</table>
 
这个自定义组件 <blog-post-row> 会被作为无效的内容提升到外部,并导致最终渲染结果出错。幸好这个特殊的 is 特性给了我们一个变通的办法:
 
<table>
 
  <tr is="blog-post-row"></tr>
 
</table>
 
需要注意的是如果我们从以下来源使用模板的话,这条限制是不存在的:
 
字符串 (例如:template: '...')
单文件组件 (.vue)
<script type="text/x-template">
到这里,你需要了解的解析 DOM 模板时的注意事项——实际上也是 Vue 的全部必要内容,大概就是这些了。恭喜你!接下来还有很多东西要去学习,不过首先,我们推荐你先休息一下,试用一下 Vue,自己随意做些好玩的东西。
 
 
 
完整代码:
 
13 组件基础1.html
 
<!DOCTYPE html>
 
<html>
 
<head>
    
<title>组件基础</title>
    
 
</head>
 
<body>
<div id="components-demo">
  <button-counter></button-counter>
</div>
 
<script>
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
  
new Vue({ el: '#components-demo' })
 
</script>
 
</body>
 
</html>
 
 
13 组件基础2.html
 
<!DOCTYPE html>
 
<html>
 
<head>
    
<title>组件基础</title>
    
 
</head>
 
<body>
<div id="components-demo">
  <button-counter></button-counter>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>
 
<script>
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
  
new Vue({ el: '#components-demo' })
 
</script>
 
</body>
 
</html>
 
 
13 组件基础3.html
 
<!DOCTYPE html>
 
<html>
 
<head>
    
<title>组件基础</title>
    
 
</head>
 
<body>
<div id="blog-post-demo">
  <blog-post title="My journey with Vue"></blog-post>
  <blog-post title="Blogging with Vue"></blog-post>
  <blog-post title="Why Vue is so fun"></blog-post>
 
</div>
 
<script>
Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})
  
new Vue({
  el: '#blog-post-demo',
  data: {
    
  }
})
 
 
</script>
 
</body>
 
</html>
 
 
13 组件基础4.html
 
<!DOCTYPE html>
 
<html>
 
<head>
    
<title>组件基础</title>
    
 
</head>
 
<body>
<div id="blog-post-demo">
  <blog-post
    v-for="post in posts"
    v-bind:key="post.id"
    v-bind:title="post.title">
  </blog-post>
 
</div>
 
<script>
Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})
  
new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue' },
      { id: 2, title: 'Blogging with Vue' },
      { id: 3, title: 'Why Vue is so fun' }
    ]
  }
})
 
</script>
 
</body>
 
</html>
 
 
13 组件基础5.html
 
<!DOCTYPE html>
 
<html>
 
<head>
    
<title>组件基础</title>
    
 
</head>
 
<body>
<div id="blog-post-demo">
  <blog-post
    v-for="post in posts"
    v-bind:key="post.id"
    v-bind:title="post.title"
v-bind:content="post.content"
  >
  </blog-post>
 
</div>
 
<script>
Vue.component('blog-post', {
  props: ['title', 'content'],
  template: `<div class="blog-post">
  <h3>{{ title }}</h3>
  <div v-html="content"></div>
</div>
`
})
  
new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue', content: 'My journey with Vue content content content' },
      { id: 2, title: 'Blogging with Vue', content: 'Blogging with Vue content content content' },
      { id: 3, title: 'Why Vue is so fun', content: 'Why Vue is so fun content content content' }
    ]
  }
})
 
</script>
 
</body>
 
</html>
 
 
13 组件基础6.html
 
<!DOCTYPE html>
 
<html>
 
<head>
    
<title>组件基础</title>
    
 
</head>
 
<body>
<div id="blog-post-demo">
  <blog-post
    v-for="post in posts"
    v-bind:key="post.id"
    v-bind:post="post">
  </blog-post>
 
</div>
 
<script>
Vue.component('blog-post', {
  props: ['post'],
  template: `
    <div class="blog-post">
      <h3>{{ post.title }}</h3>
      <div v-html="post.content"></div>
    </div>
  `
})
  
new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue', content: 'My journey with Vue content content content' },
      { id: 2, title: 'Blogging with Vue', content: 'Blogging with Vue content content content' },
      { id: 3, title: 'Why Vue is so fun', content: 'Why Vue is so fun content content content' }
    ]
  }
})
 
</script>
 
</body>
 
</html>
 
 
13 组件基础7.html
 
<!DOCTYPE html>
 
<html>
 
<head>
    
<title>组件基础</title>
    
 
</head>
 
<body>
<div id="blog-posts-events-demo">
  <div :style="{ fontSize: postFontSize + 'em' }">
    <blog-post
      v-for="post in posts"
      v-bind:key="post.id"
      v-bind:post="post"
  v-on:enlarge-text="postFontSize += 0.1"
    ></blog-post>
  </div>
</div>
 
<script>
Vue.component('blog-post', {
  props: ['post'],
  template: `
    <div class="blog-post">
      <h3>{{ post.title }}</h3>
      <button v-on:click="$emit('enlarge-text')">
        Enlarge text
      </button>
      <div v-html="post.content"></div>
    </div>
  `
})
  
new Vue({
  el: '#blog-posts-events-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue', content: 'My journey with Vue content content content' },
      { id: 2, title: 'Blogging with Vue', content: 'Blogging with Vue content content content' },
      { id: 3, title: 'Why Vue is so fun', content: 'Why Vue is so fun content content content' }
    ],
postFontSize: 1
  }
})
 
</script>
 
</body>
 
</html>
 
 
13 组件基础8.html
 
<!DOCTYPE html>
 
<html>
 
<head>
    
<title>组件基础</title>
    
 
</head>
 
<body>
<div id="blog-posts-events-demo">
  <div :style="{ fontSize: postFontSize + 'em' }">
    <blog-post
      v-for="post in posts"
      v-bind:key="post.id"
      v-bind:post="post"
  v-on:enlarge-text="postFontSize += $event"
    ></blog-post>
  </div>
</div>
 
<script>
Vue.component('blog-post', {
  props: ['post'],
  template: `
    <div class="blog-post">
      <h3>{{ post.title }}</h3>
      <button v-on:click="$emit('enlarge-text', 0.1)">
        Enlarge text
      </button>
      <div v-html="post.content"></div>
    </div>
  `
})
  
new Vue({
  el: '#blog-posts-events-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue', content: 'My journey with Vue content content content' },
      { id: 2, title: 'Blogging with Vue', content: 'Blogging with Vue content content content' },
      { id: 3, title: 'Why Vue is so fun', content: 'Why Vue is so fun content content content' }
    ],
postFontSize: 1
  }
})
 
</script>
 
</body>
 
</html>
 
 
13 组件基础9.html
 
<!DOCTYPE html>
 
<html>
 
<head>
    
<title>组件基础</title>
    
 
</head>
 
<body>
<div id="blog-posts-events-demo">
  <div :style="{ fontSize: postFontSize + 'em' }">
    <blog-post
      v-for="post in posts"
      v-bind:key="post.id"
      v-bind:post="post"
  v-on:enlarge-text="onEnlargeText"
    ></blog-post>
  </div>
</div>
 
<script>
Vue.component('blog-post', {
  props: ['post'],
  template: `
    <div class="blog-post">
      <h3>{{ post.title }}</h3>
      <button v-on:click="$emit('enlarge-text', 0.1)">
        Enlarge text
      </button>
      <div v-html="post.content"></div>
    </div>
  `
})
  
new Vue({
  el: '#blog-posts-events-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue', content: 'My journey with Vue content content content' },
      { id: 2, title: 'Blogging with Vue', content: 'Blogging with Vue content content content' },
      { id: 3, title: 'Why Vue is so fun', content: 'Why Vue is so fun content content content' }
    ],
postFontSize: 1
  },
  methods: {
    onEnlargeText: function (enlargeAmount) {
      this.postFontSize += enlargeAmount
    }
  }
})
 
</script>
 
</body>
 
</html>
 
 
13 组件基础10.html
 
<!DOCTYPE html>
 
<html>
 
<head>
    
<title>组件基础</title>
    
 
</head>
 
<body>
<div id="alert-box">
  <alert-box>
    Something bad happened.
  </alert-box>
 
</div>
 
<script>
Vue.component ( '경고 박스', {
  템플릿 :`
    <DIV 클래스 = "데모 경고 박스">
      의 <strong> 오류! </ STRONG>
      <슬롯> </ 슬롯>
    </ DIV>
  `
})
 
  
새로운 뷰 ({
  전기 : '# 경고 박스,
  데이터 : {
    
  },
  방법 : {
    
  }
})
 
</ script>
 
<스타일>
.demo-경고 박스 {
  색상 : 빨간색
}
</ 스타일>
</ body>
 
</ HTML>

비디오 자습서에 오신 것을 환영합니다 : https://ke.qq.com/course/432961?tuin=36914f34 의심, QQ 채팅 토론 그룹 665,714,453을 추가하십시오.
 

추천

출처www.cnblogs.com/daqiang123/p/11368421.html