前言
vue作为前端目前三大主流框架之一,在前端中也是占有重要的地位。特别是在国内,现在想要找一份前端的工作,那么学会vue,将你的不二之选。
vue目前为什么这么重要呢?因为vue的作者是中国人。那当然不是啦~ 最最最最重要的原因是它有很多优点:
- 双向数据绑定
- 组件化
- 单页面应用用户体验好
- 简单易学
- ……
好了,现在知到vue.js的优点就是简单易学,那接下来我们就一起来学习学习它的组件化开发 --> component
什么是组件
我们来看看官网的介绍,他说是可复用的 Vue 实例。那怎么复用呢?复用什么呢?之前我们写过了css样式,当有些样式是一样的,我们就会将它写到一个文件里然后通过@import url("CSS文件路径");
将css文件引入,这样就可以不用多写重复的样式了。
那么组件你可以理解成html、css、javaScript的集合,然后在其他地方引用。之前引入的css或者引入js都是纯粹的它的样式或者行为。而组件包过HTML代码、css代码、js代码,也就是说一个组件就有自己的结构、样式和行为了。有了组件,我们的代码的重复率就不会那么高了,代码的复用性就增强了。因为有很多页面的其中一部分都是一样的,比如:tabbar、导航栏等等。
学习组件
1. 组件的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件化基本使用</title>
</head>
<body>
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件 -->
<test-cpn></test-cpn>
</div>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
//1.创建组件构造器对象
const TestCpn = Vue.extend({
// template --> 定义组件的HTML模板
template: `
<div>
<h2>组件标题</h2>
<p>组件内容</p>
</div>
`
})
//2.注册组件
// Vue.component('组件的标题','构造器对象')
Vue.component('test-cpn', TestCpn);
const vm = new Vue({
el: '#app'
})
</script>
</body>
</html>
组件的基本使用就是这三个步骤:
- 创建组件构造器对象
- 注册组件
- 使用组件
当然组件可以使用多次,就像这样,你使用一次,它就渲染一次,它使用多少次,他就渲染多少次。你是不是开始觉得组件有点东西了!
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件 -->
<test-cpn></test-cpn>
<test-cpn></test-cpn>
<!-- 使用单标签 -->
<test-cpn/>
</div>
组件中还可以定义data,但但但值得注意的是组件的data必须是一个函数且data函数要返回一个对象
<script>
//1.创建组件构造器对象
const TestCpn = Vue.extend({
// template --> 定义组件的HTML模板
template: `
<div>
<h2>组件标题</h2>
<p>组件内容</p>
{
{mes}}
</div>
`,
// data --> 用于存放组件的数据
data() {
return {
mes: 'hello vue component!'
}
}
})
//2.注册组件
// Vue.component('组件的标题','构造器对象')
Vue.component('test-cpn', TestCpn);
const vm = new Vue({
el: '#app'
})
</script>
那么有人就有疑惑了!现在组件不是只有结构吗?样式呢?行为呢?好的!show code!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件化基本使用</title>
<style>
.some-style{
color: red;
font-size: 20px;
font-weight: bolder;
}
</style>
</head>
<body>
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件 -->
<test-cpn></test-cpn>
<test-cpn></test-cpn>
<!-- 使用单标签 -->
<test-cpn/>
</div>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
//1.创建组件构造器对象
const TestCpn = Vue.extend({
// template --> 定义组件的HTML模板
template: `
<div>
<h2>组件标题</h2>
<p class="some-style">组件内容</p>
{
{mes}}
<button @click="handleBtn">点我你就知道了</button>
</div>
`,
// data --> 用于存放组件的数据
data() {
return {
mes: 'hello vue component!'
}
},
// methods --> 组件的方法都写到这里面
methods: {
handleBtn() {
console.log('这不就是组件的行为了吗?讨厌!')
}
}
})
//2.注册组件
// Vue.component('组件的标题','构造器对象')
Vue.component('test-cpn', TestCpn);
const vm = new Vue({
el: '#app'
})
</script>
</body>
</html>
好了,现在我们知道组件用也有data、也有methods。其实组件还有computed、watch、等等。
其实我们通过 Vue.component() 注册的组件都是全局组件,这也就意味着可以在多个Vue的实例中使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件化基本使用</title>
<style>
.some-style{
color: red;
font-size: 20px;
font-weight: bolder;
}
</style>
</head>
<body>
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件 -->
<test-cpn></test-cpn>
<test-cpn></test-cpn>
<!-- 使用单标签 -->
<test-cpn/>
</div>
<div id="app2">
<hr>
<h1>This is a piece of app2 message!</h1>
<test-cpn/>
</div>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
//1.创建组件构造器对象
const TestCpn = Vue.extend({
// template --> 定义组件的HTML模板
template: `
<div>
<h2>组件标题</h2>
<p class="some-style">组件内容</p>
{
{mes}}
<button @click="handleBtn">点我你就知道了</button>
</div>
`,
// data --> 用于存放组件的数据
data() {
return {
mes: 'hello vue component!'
}
},
// methods --> 组件的方法都写到这里面
methods: {
handleBtn() {
console.log('这不就是组件的行为了吗?讨厌!')
}
}
})
//2.注册组件
// Vue.component('组件的标题','构造器对象')
Vue.component('test-cpn', TestCpn);
const vm = new Vue({
el: '#app'
})
const vm2 = new Vue({
el: '#app2'
})
</script>
</body>
</html>
那怎么使用局部组件呢?那就是在实例里边注册组件。
如下例子:当我们在实例vm
里边注册TestCpn
组件,那么在实例vm2
里使用TestCpn
组件时,它就会报错,且没有数据展示到页面上。这是因为实例vm2
找不到TestCpn
组件。因为它是在实例vm
定义的嘛!所以这就是局部组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件化基本使用</title>
<style>
.some-style{
color: red;
font-size: 20px;
font-weight: bolder;
}
</style>
</head>
<body>
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件 -->
<test-cpn></test-cpn>
<test-cpn></test-cpn>
<!-- 使用单标签 -->
<test-cpn/>
</div>
<div id="app2">
<hr>
<h1>This is a piece of app2 message!</h1>
<test-cpn/>
</div>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
//1.创建组件构造器对象
const TestCpn = Vue.extend({
// template --> 定义组件的HTML模板
template: `
<div>
<h2>组件标题</h2>
<p class="some-style">组件内容</p>
{
{mes}}
<button @click="handleBtn">点我你就知道了</button>
</div>
`,
// data --> 用于存放组件的数据
data() {
return {
mes: 'hello vue component!'
}
},
// methods --> 组件的方法都写到这里面
methods: {
handleBtn() {
console.log('这不就是组件的行为了吗?讨厌!')
}
}
})
const vm = new Vue({
el: '#app',
//2.在vm实例里面 注册组件
// component('组件的标题','构造器对象')
components: {
'test-cpn': TestCpn
}
})
const vm2 = new Vue({
el: '#app2'
})
</script>
</body>
</html>
其实有个问题,我们在注册组件的时候(Vue.component('组件的标题', '构造器对象'))
component的第二个参数不是要传一个构造器对象吗? 那我们传给它好了,直接传一个选项对象,不用我们亲自去调用extend
方法,因为Vue会帮我们去调用它,所以我们完全可以这样写:
Vue.component('test-cpn', {
/* ... */ })
注册全局组件就是这样写:
el: 'app',
data() {
return{
....
}
},
component: {
'test-cpn': {
/* ... */ }
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件化基本使用</title>
<style>
.some-style{
color: red;
font-size: 20px;
font-weight: bolder;
}
</style>
</head>
<body>
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件 -->
<test-cpn></test-cpn>
<test-cpn></test-cpn>
<!-- 使用单标签 -->
<test-cpn/>
</div>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
//2.注册组件
// Vue.component('组件的标题','构造器对象')
components: {
'test-cpn': {
// template --> 定义组件的HTML模板
template: `
<div>
<h2>组件标题</h2>
<p class="some-style">组件内容</p>
{
{mes}}
<button @click="handleBtn">点我你就知道了</button>
</div>
`,
// data --> 用于存放组件的数据
data() {
return {
mes: 'hello vue component!'
}
},
// methods --> 组件的方法都写到这里面
methods: {
handleBtn() {
console.log('这不就是组件的行为了吗?讨厌!')
}
}
}
}
})
</script>
</body>
</html>
当然,这样写代码结构乱七八糟的,我们应该把html代码抽离出去,这样html代码和js代码不会混在一起了,看着也是舒服一点。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件化基本使用</title>
<style>
.some-style{
color: red;
font-size: 20px;
font-weight: bolder;
}
</style>
</head>
<body>
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件 -->
<test-cpn></test-cpn>
<test-cpn></test-cpn>
<!-- 使用单标签 -->
<test-cpn/>
</div>
<!-- vue组件结构模板 -->
<template id="test-cpn">
<div>
<h2>组件标题</h2>
<p class="some-style">组件内容</p>
{
{mes}}
<button @click="handleBtn">点我你就知道了</button>
</div>
</template>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
//2.注册组件
// Vue.component('组件的标题','构造器对象')
components: {
'test-cpn': {
// template --> 定义组件的HTML模板
template: '#test-cpn',
// data --> 用于存放组件的数据
data() {
return {
mes: 'hello vue component!'
}
},
// methods --> 组件的方法都写到这里面
methods: {
handleBtn() {
console.log('这不就是组件的行为了吗?讨厌!')
}
}
}
}
})
</script>
</body>
</html>
丝毫不影响我们程序运行、而且代码看起来也舒舒服服的~
组件通信
父传子
现在我们知道组件有data
、有methods
、有computed
、watch
、等。其实组件还有一个重要的属性props
props
跟data
差不多,是用于存放组件中用到的数据的,但是props
中的数据是从父组件中传递过来的,并且只能在父组件中修改props
中的数据,子组件只能用props
中的数据,不能直接修改props
中的数据。 而data
中的数据是组件自己定义的。组件也可以直接修改data
中的数据。
哪个是父组件?哪个又是子组件呢?在上面例子中,test-cpn
就是子组件, vm
实例就是父组件,因为我们在 vm
实例上注册了 test-cpn
组件并且使用它。
那如何从父组件传递数据呢?show code!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件化基本使用</title>
<style>
.some-style{
color: red;
font-size: 20px;
font-weight: bolder;
}
</style>
</head>
<body>
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件,并且送给它一段话 -->
<test-cpn msg="我是你爹!"></test-cpn>
<!-- 3.使用组件,我没什么要给它的 -->
<test-cpn></test-cpn>
<!-- 使用组件,使用单标签,我也没什么要给它的 -->
<test-cpn/>
</div>
<!-- vue组件结构模板 -->
<template id="test-cpn">
<div>
<h2>组件标题</h2>
<p class="some-style">组件内容</p>
{
{mes}}
<button @click="handleBtn">点我你就知道了</button>
<h4>让我看看父组件给我传来了什么消息:{
{msg}}</h4>
</div>
</template>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
//2.注册组件
// Vue.component('组件的标题','构造器对象')
components: {
'test-cpn': {
// template --> 定义组件的HTML模板
template: '#test-cpn',
// props --> 用于接收从父组件传递来的数据
props: ['msg'],
// data --> 用于存放组件的数据
data() {
return {
mes: 'hello vue component!'
}
},
// methods --> 组件的方法都写到这里面
methods: {
handleBtn() {
console.log('这不就是组件的行为了吗?讨厌!')
}
}
}
}
})
</script>
</body>
</html>
看吧!就是这么简单,只需要在父组件中使用子组件时,写一个属性和值就可以了。属性就是在子组件定义好的数据,值就是你想要传的数据。上述例子中,我们在父组件使用了三次 test-cpn
组件,但是只有第一次使用的时候传递msg
,而第二次和第三次使用的时候都没有传递msg
,所以第一次的时候才会出现msg
的数据,而第二次和第三次并没有出现。
props
只能接收字符串吗?呵,它可不止这么简单,它还可以接收数字、数字、对象,而且还可以对要传递的数据进行类型限制、默认值,等校验。也可以动态传递。
props
有两种写法:如果对从组件传递的数据不需要类型限制等校验,那么props
写成数组形式就好了;如果对从组件传递的数据需要类型限制等校验,那么props
就要写成对象形式
// 不需要校验时
props: ['a', 'b', 'c']
// 需要校验时
props: {
a: {
...},
b: {
...},
c: {
...}
}
不校验的写法我们已经写过了,接下来就是不校验的写法了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件化基本使用</title>
<style>
.some-style{
color: red;
font-size: 20px;
font-weight: bolder;
}
</style>
</head>
<body>
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件,并且送给它一段话 -->
<test-cpn msg="我是你爹!"></test-cpn>
<!-- 3.使用组件,并且动态传递了一个数组给它-->
<test-cpn :fm="fourMasterpieces"></test-cpn>
<!-- 使用组件,使用单标签,我也没什么要给它的 -->
<test-cpn/>
</div>
<!-- vue组件结构模板 -->
<template id="test-cpn">
<div>
<h2>组件标题</h2>
<p class="some-style">组件内容</p>
{
{mes}}
<button @click="handleBtn">点我你就知道了</button>
<h4>让我看看父组件给我传来了什么消息:{
{msg}}</h4>
<ul>
<li v-for="item in fm">{
{item}}</li>
</ul>
</div>
</template>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
fourMasterpieces: ['西游记', '三国演义', '水浒传', '红楼梦']
},
//2.注册组件
// Vue.component('组件的标题','构造器对象')
components: {
'test-cpn': {
// template --> 定义组件的HTML模板
template: '#test-cpn',
// props --> 用于接收从父组件传递来的数据
props: {
msg: {
type: String, // 类型限制
default: '我是默认滴数据' // 默认值
},
fm: {
type: Array // 类型限制
}
},
// data --> 用于存放组件的数据
data() {
return {
mes: 'hello vue component!'
}
},
// methods --> 组件的方法都写到这里面
methods: {
handleBtn() {
console.log('这不就是组件的行为了吗?讨厌!')
}
}
}
}
})
</script>
</body>
</html>
当我们进行类型等校验之后,父组件传的数据类型不对,数据还是能显示出来,但就会报错。 一下代码我只截取一部分
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件,并且送给它一段话 -->
<test-cpn msg="我是你爹!" :count="num"></test-cpn>
<!-- 3.使用组件,并且动态传递了一个数组给它-->
<test-cpn :fm="fourMasterpieces"></test-cpn>
<!-- 使用组件,使用单标签,我也没什么要给它的 -->
<test-cpn/>
</div>
<!-- vue组件结构模板 -->
<template id="test-cpn">
<div>
<h2>组件标题</h2>
<p class="some-style">组件内容</p>
{
{mes}}
<button @click="handleBtn">点我你就知道了</button>
<h4>让我看看父组件给我传来了什么消息:{
{msg}}{
{count}}</h4>
<ul>
<li v-for="item in fm">{
{item}}</li>
</ul>
</div>
</template>
data: {
num: '100',
fourMasterpieces: ['西游记', '三国演义', '水浒传', '红楼梦']
},
这是就可以写多个可能的类型,这样就不对报错了!
props: {
...
count: {
type: [Number, String]
},
...
}
也可以设置必传数据,如果设置必传数据,那每一次使用都要传,如果父组件不传就会报错。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件化基本使用</title>
<style>
.some-style{
color: red;
font-size: 20px;
font-weight: bolder;
}
</style>
</head>
<body>
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 由于parentName是必须数据, 所以每次有的时候都要传进去 -->
<!-- 3.使用组件,并且送给它一段话,并且传了动态数据,-->
<test-cpn msg="我是你爹!" :count="num" :parent-name="name"></test-cpn>
<!-- 3.使用组件,并且动态传递了两个数组给它-->
<test-cpn :fm="fourMasterpieces" :parent-name="name"></test-cpn>
<!-- 3.使用组件,使用单标签,并且传了动态数据 --->
<test-cpn :parent-name="name"/>
</div>
<!-- vue组件结构模板 -->
<template id="test-cpn">
<div>
<h2>组件标题</h2>
<p>我的爸爸叫:{
{parentName}}</p>
<p class="some-style">组件内容</p>
{
{mes}}
<button @click="handleBtn">点我你就知道了</button>
<h4>让我看看父组件给我传来了什么消息:{
{msg}}{
{count}}</h4>
<ul>
<li v-for="item in fm">{
{item}}</li>
</ul>
</div>
</template>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
num: '100',
name: 'vm实例',
fourMasterpieces: ['西游记', '三国演义', '水浒传', '红楼梦']
},
//2.注册组件
// Vue.component('组件的标题','构造器对象')
components: {
'test-cpn': {
// template --> 定义组件的HTML模板
template: '#test-cpn',
// props --> 用于接收从父组件传递来的数据
props: {
msg: {
type: String, // 类型限制
default: '我是默认滴数据' // 默认值
},
count: {
type: [Number, String]
},
fm: {
type: Array // 类型限制
},
parentName: {
type: String,
required: true // 是否必须传递
}
},
// data --> 用于存放组件的数据
data() {
return {
mes: 'hello vue component!'
}
},
// methods --> 组件的方法都写到这里面
methods: {
handleBtn() {
console.log('这不就是组件的行为了吗?讨厌!')
}
}
}
}
})
</script>
</body>
</html>
上面说过在组件里面不能直接修改props
中的值,我来添加一个按钮,点击按钮改变props
中的count为0,它依然能改变,但是报错了,Vue大概意思是不能在组件里直接修改props
中的状态。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件化基本使用</title>
<style>
.some-style{
color: red;
font-size: 20px;
font-weight: bolder;
}
</style>
</head>
<body>
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件,并且送给它一段话,并且传了动态数据 -->
<test-cpn msg="我是你爹!" :count="num" :parent-name="name"></test-cpn>
<!-- 3.使用组件,并且动态传递了两个数组给它-->
<test-cpn :fm="fourMasterpieces" :parent-name="name"></test-cpn>
<!-- 使用组件,使用单标签,并且传了动态数据 --->
<test-cpn :parent-name="name"/>
</div>
<!-- vue组件结构模板 -->
<template id="test-cpn">
<div>
<h2>组件标题</h2>
<p>我的爸爸叫:{
{parentName}}</p>
<p class="some-style">组件内容</p>
{
{mes}}
<button @click="handleBtn">点我你就知道了</button>
<button @click="changePropsValue">修改props中的值</button>
<h4>让我看看父组件给我传来了什么消息:{
{msg}}{
{count}}</h4>
<ul>
<li v-for="item in fm">{
{item}}</li>
</ul>
</div>
</template>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
num: '100',
name: 'vm实例',
fourMasterpieces: ['西游记', '三国演义', '水浒传', '红楼梦']
},
//2.注册组件
// Vue.component('组件的标题','构造器对象')
components: {
'test-cpn': {
// template --> 定义组件的HTML模板
template: '#test-cpn',
// props --> 用于接收从父组件传递来的数据
props: {
msg: {
type: String, // 类型限制
default: '我是默认滴数据' // 默认值
},
count: {
type: [Number, String]
},
fm: {
type: Array // 类型限制
},
parentName: {
type: String,
required: true // 是否必须
}
},
// data --> 用于存放组件的数据
data() {
return {
mes: 'hello vue component!'
}
},
// methods --> 组件的方法都写到这里面
methods: {
handleBtn() {
console.log('这不就是组件的行为了吗?讨厌!')
},
changePropsValue() {
this.count = 0
}
}
}
}
})
</script>
</body>
</html>
子传父
既然有父传子,那么就有子传父。子传父稍微比父传子更复杂一点,当时我我在学的时候,脑子也是嗡嗡的,后面多敲一点就好了,其实不复杂,等你多敲几遍,那你就会觉得跟呼吸一样简单。说白了,子传父就是发射一个自定义事件。
上述例子,直接在组件中修改props
中的状态,是不行滴~由于props中的数据是从父组件中传过来的,所以应当在父组件中修改它才是最棒的方式!所以可以在子组件中发射一个自定义事件,然后在父组件中使用这自定义事件可以改变传递的数据,数据一改变,子组件就会第一时间收到新的数据。show code!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件化基本使用</title>
<style>
.some-style{
color: red;
font-size: 20px;
font-weight: bolder;
}
</style>
</head>
<body>
<div id="app">
<h1>This is a piece of app message!</h1>
<!-- 3.使用组件,并且送给它一段话,并且传了动态数据,
并接收了自定义事件 -->
<test-cpn
msg="我是你爹!"
:count="num"
:parent-name="name"
@change-props-value="hanldeValue"
></test-cpn>
<!-- 3.使用组件,并且动态传递了两个数组给它-->
<test-cpn :fm="fourMasterpieces" :parent-name="name"></test-cpn>
<!-- 使用组件,使用单标签,并且传了动态数据 --->
<test-cpn :parent-name="name"/>
</div>
<!-- vue组件结构模板 -->
<template id="test-cpn">
<div>
<h2>组件标题</h2>
<p>我的爸爸叫:{
{parentName}}</p>
<p class="some-style">组件内容</p>
{
{mes}}
<button @click="handleBtn">点我你就知道了</button>
<button @click="changePropsValue">修改props中的值</button>
<h4>让我看看父组件给我传来了什么消息:{
{msg}}{
{count}}</h4>
<ul>
<li v-for="item in fm">{
{item}}</li>
</ul>
</div>
</template>
<!-- 引入Vue -->
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
num: '100',
name: 'vm实例',
fourMasterpieces: ['西游记', '三国演义', '水浒传', '红楼梦']
},
// vm实例方法的集合
methods: {
hanldeValue(){
this.num--;
}
},
//2.注册组件
// component('组件的标题','构造器对象')
components: {
'test-cpn': {
// template --> 定义组件的HTML模板
template: '#test-cpn',
// props --> 用于接收从父组件传递来的数据
props: {
msg: {
type: String, // 类型限制
default: '我是默认滴数据' // 默认值
},
count: {
type: [Number, String]
},
fm: {
type: Array // 类型限制
},
parentName: {
type: String,
required: true // 是否必须
}
},
// data --> 用于存放组件的数据
data() {
return {
mes: 'hello vue component!'
}
},
// methods --> 组件的方法都写到这里面
methods: {
handleBtn() {
console.log('这不就是组件的行为了吗?讨厌!')
},
changePropsValue() {
// $emit --> 发射自定义事件
this.$emit('change-props-value')
}
}
}
}
})
</script>
</body>
</html>
上述例子给子组件’(修改props中的值)'按钮绑定一个点击事件(changePropsValue),然后在事件处理中我们通过this.$emit
发发射一个自定义事件change-props-value
。然后在父组件中接收change-props-value
自定义事件,通过hanldeValue
方法修改父组件中num
的值,num
的值一改变,子组件就会第一时间收到改变后的值,直接渲染到页面了。
值得注意的是,这里的自定义事件我为什么不写小驼峰命名呢?这里官网说了,HTML 是大小写不敏感的,所以他推荐我们使
-
代替 小驼峰
当然,子组件在发射自定义事件时,也可以传递参数,直接this.$emit('事件名', 一些参数, 另外的一些参数)
传递参数
changePropsValue() {
// $emit --> 发射自定义事件
this.$emit('change-props-value', 10)
}
<!-- 3.使用组件,并且送给它一段话,并且传了动态数据,
并接收了自定义事件 -->
<test-cpn
msg="我是你爹!"
:count="num"
:parent-name="name"
@change-props-value="hanldeValue"
></test-cpn>
// 直接在hanldeValue方法接收参数
hanldeValue(data) {
console.log(data);
this.num -= data;
}
学到这里是不是感觉脑子乱七八糟的,懵逼是正常的,动动您的手敲几遍,你就会发现突然豁然开朗!还不快去 !打!代!码!,最后再送你一张图: