一、组件
1、快速起步(局部组件)
组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 。我们可以在一个通过 new Vue 创建的 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>Document</title>
</head>
<body>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<div-b></div-b>
</div>
<script>
Vue.config.productionTip = false;
//创建vue对象
let vm = new Vue({
el : "#app",
data : {
name : 'wxb'
},
//局部组件
components:{
'div-b':{
//模板
template:`
<div>111</div>
`
}
}
})
</script>
</body>
</html>
2、组件的复用(全局组件)
因为组件是可复用的 Vue 实例,所以它们与 new Vue
接收相同的选项,例如 data
、computed
、watch
、methods
以及生命周期钩子等。仅有的例外是像 el
这样根实例特有的选项。
注意当点击按钮时,每个组件都会各自独立维护它的 count
。因为你每用一次组件,就会有一个它的新实例被创建。
<!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>Document</title>
</head>
<body>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script>
Vue.config.productionTip = false;
// 定义一个名为 button-counter 的新组件
//全局组件
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">点击 {{ count }} 次.</button>'
})
//创建vue对象
let vm = new Vue({
el : "#app",
data : {
name : 'wxb'
}
})
</script>
</body>
</html>
3、全局组件的使用
A)错误代码:
注意:模板里面必须包含一个根标签,而且该根标签里面不能写v-for指令
<!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>Document</title>
</head>
<body>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<b-button></b-button>
</div>
<script>
Vue.component('b-button', {
//模板,注意:模板里面必须包含一个根标签,而且该根标签里面不能写v-for指令
template: `
<button @click="sub">减</button>
{{ count }}
<button @click="add">加</button>
`,
props:{
count : 0
},
methods: {
sub:function(){
this.count--;
},
add:function(){
this.count++;
}
},
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
}
})
</script>
</body>
</html>
B)正确代码
<!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>Document</title>
</head>
<body>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<b-button count="0"></b-button>
</div>
<script>
Vue.component('b-button', {
//模板,注意:模板里面必须包含一个根标签,而且该根标签里面不能写v-for指令
template: `
<div>
<button @click="sub">减</button>
{{ count }}
<button @click="add">加</button>
</div>
`,
//参数,注意:这里是简写,不需要明确参数的类型,默认值等等
props:['count'],
methods: {
sub:function(){
this.count--;
},
add:function(){
this.count++;
}
},
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
}
})
</script>
</body>
</html>
但是此时会提示一个错误:
大致意思为不要直接去修改prop中的值
解决办法:使用data接值,并操作
C)单向数据流
https://cn.vuejs.org/v2/guide/components-props.html#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81
D)使用
新建一个文件夹components和文件button.js
将刚定义的全局组件剪切到mybutton.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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!--注意:一定是先引入vue.js文件,再引入外部组件js文件-->
<script src="./components/mybutton.js"></script>
<div id="app">
<b-button count="0"></b-button>
</div>
<script>
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
}
})
</script>
</body>
</html>
E)补充
<div id="app">
<!--
count='abc' 表示将字符串‘abc’传给参数count
:count='abc' 表示将变量abc的值传给参数count
-->
<b-button :count="0"></b-button>
</div>
4、data必须是一个函数(vue规则)
当我们定义这个 <button-counter>
组件时,你可能会发现它的 data
并不是像这样直接提供一个对象:
data: {
count: 0
}
取而代之的是,一个组件的 data
选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:
data: function () {
return {
count: 0
}
}
如果 Vue 没有这条规则,点击一个按钮就可能影响到其它所有实例
5、通过Prop向子组件传递数据
官方文档:
https://cn.vuejs.org/v2/guide/components.html#%E9%80%9A%E8%BF%87-Prop-%E5%90%91%E5%AD%90%E7%BB%84%E4%BB%B6%E4%BC%A0%E9%80%92%E6%95%B0%E6%8D%AE
A)基础用法
Prop 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。
<!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>Document</title>
</head>
<body>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<blog-post title="11"></blog-post>
<blog-post title="22"></blog-post>
<blog-post title="33"></blog-post>
</div>
<script>
Vue.config.productionTip = false;
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
//创建vue对象
let vm = new Vue({
el : "#app",
data : {
}
})
</script>
</body>
</html>
一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在上述模板中,会发现我们能够在组件实例中访问这个值,就像访问 data
中的值一样。
一个 prop 被注册之后,你就可以像这样把数据作为一个自定义 attribute 传递进来:
<blog-post title="11"></blog-post>
<blog-post title="22"></blog-post>
<blog-post title="33"></blog-post>
B)从data中取值
可以使用 v-bind
来动态传递 prop
<!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>Document</title>
</head>
<body>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<blog-post v-for="post in posts" :title="post.title" :key="post.id">
</blog-post>
</div>
<script>
Vue.config.productionTip = false;
Vue.component('blog-post', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
posts: [
{ id: 1, title: '11' },
{ id: 2, title: '22' },
{ id: 3, title: '33' }
]
}
})
</script>
</body>
</html>
C)Prop的大小写
深入了解prop:https://cn.vuejs.org/v2/guide/components-props.html
HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名
<!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>Document</title>
</head>
<body>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<blog-post v-for="post in posts" :title-aa="post.title" :key="post.id">
</blog-post>
</div>
<script>
Vue.config.productionTip = false;
Vue.component('blog-post', {
props: ['titleAa'],
template: '<h3>{{ titleAa }}</h3>'
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
posts: [
{ id: 1, title: '11' },
{ id: 2, title: '22' },
{ id: 3, title: '33' }
]
}
})
</script>
</body>
</html>
D)prop类型
以上,默认使用以字符串数组形式列出的prop,在实际业务中,通常会希望每个prop都有自己的类型,此时,可以以对象形式列出prop,这些property的名称和值分别是prop各自的名称和类型
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}
第一种写法:
<!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>Document</title>
</head>
<body>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<blog-post v-for="post in posts" :title="post.title" :key="post.id">
</blog-post>
</div>
<script>
Vue.config.productionTip = false;
Vue.component('blog-post', {
//第一种写法
props: {
title:String
},
template: '<h3>{{ title }}</h3>'
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
posts: [
{ id: 1, title: '11' },
{ id: 2, title: '22' },
{ id: 3, title: '33' }
]
}
})
</script>
</body>
</html>
第二种写法:
<!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>Document</title>
</head>
<body>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<blog-post v-for="post in posts" :title="post.title" :key="post.id">
</blog-post>
</div>
<script>
Vue.config.productionTip = false;
Vue.component('blog-post', {
//第一种写法
// props: {
// title:String
// },
//第二种写法
props : {
title : {
//类型
type : String,
//默认值
default : 'aa',
//是否必须
required : true
}
},
template: '<h3>{{ title }}</h3>'
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
posts: [
{ id: 1 },
{ id: 2, title: '22' },
{ id: 3, title: '33' }
]
}
})
</script>
</body>
</html>
E)传入一个对象的所有property
如果你想要将一个对象的所有 property 都作为 prop 传入,你可以使用不带参数的 v-bind
(取代 v-bind:prop-name
)。例如,对于一个给定的对象 post
:
post: {
id: 1,
title: 'My Journey with Vue'
}
下面的模板:
<blog-post v-bind="post"></blog-post>
等价于:
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
代码:
<!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>Document</title>
</head>
<body>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<blog-post v-bind="post">
</blog-post>
</div>
<script>
Vue.config.productionTip = false;
Vue.component('blog-post', {
//第一种写法
props: {
title:String
},
template: '<h3>{{ title }}</h3>'
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
post:{ id: 1, title: '11' }
}
})
</script>
</body>
</html>
6、动态组件
在不同组件之间进行动态切换
通过 Vue 的 <component>
元素加一个特殊的 is
attribute 来实现:
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>
<!DOCTYPE html>
<html>
<head>
<title>Dynamic Components Example</title>
<script src="https://unpkg.com/vue"></script>
<style>
.tab-button {
padding: 6px 10px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
border: 1px solid #ccc;
cursor: pointer;
background: #f0f0f0;
margin-bottom: -1px;
margin-right: -1px;
}
.tab-button:hover {
background: #e0e0e0;
}
.tab-button.active {
background: #e0e0e0;
}
.tab {
border: 1px solid #ccc;
padding: 10px;
}
</style>
</head>
<body>
<div id="dynamic-component-demo" class="demo">
<button
v-for="tab in tabs"
v-bind:key="tab"
v-on:click="currentTab = tab"
>
{{ tab }}
</button>
<component v-bind:is="currentTabComponent" class="tab"></component>
</div>
<script>
Vue.component("tab-home", {
template: "<div>Home component</div>"
});
Vue.component("tab-posts", {
template: "<div>Posts component</div>"
});
Vue.component("tab-archive", {
template: "<div>Archive component</div>"
});
new Vue({
el: "#dynamic-component-demo",
data: {
currentTab: "Home",
tabs: ["Home", "Posts", "Archive"]
},
computed: {
currentTabComponent: function() {
return "tab-" + this.currentTab.toLowerCase();
}
}
});
</script>
</body>
</html>
二、父子组件通信
1、子组件使用父组件数据($parent)
A)搭基础框架
<!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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<b-div title="苹果"></b-div>
<b-div title="香蕉"></b-div>
<b-div title="菠萝"></b-div>
</div>
<script>
Vue.component('b-div', {
props : ['title'],
template : `
<div>{{ title }}</div>
`
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
name : 'wxb',
age : 18
}
})
</script>
</body>
</html>
B)引出问题
想要在子组件中使用父组件的值
先查看父子组件的渲染过程:
页面加载时,是先渲染里面的组件(子),再渲染外面的组件(父)
<!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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<!--页面加载时,是先渲染里面的组件(子),再渲染外面的组件(父)-->
<b-div title="苹果"></b-div>
<b-div title="香蕉"></b-div>
<b-div title="菠萝"></b-div>
</div>
<script>
Vue.component('b-div', {
props : ['title'],
template : `
<div>{{ title }}</div>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
name : 'wxb',
age : 18
},
mounted() {
console.log('app父组件渲染完毕。。。');
},
})
</script>
</body>
</html>
问题现象:
因为先渲染子组件,所以此时子组件是拿不到父组件的值的
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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<b-div title="苹果"></b-div>
<b-div title="香蕉"></b-div>
<b-div title="菠萝"></b-div>
</div>
<script>
Vue.component('b-div', {
props : ['title'],
template : `
<div>{{ title }}</div>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
//$parent获取父组件对象
console.log(this.$parent);
},
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
name : 'wxb',
age : 18
},
mounted() {
console.log('app父组件渲染完毕。。。');
},
})
</script>
</body>
</html>
D)使用
<!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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<b-div title="苹果"></b-div>
<b-div title="香蕉"></b-div>
<b-div title="菠萝"></b-div>
</div>
<script>
Vue.component('b-div', {
props : ['title'],
template : `
<div>{{ title }}---{{ name }}---{{ $parent.age }}</div>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
//$parent获取父组件对象
console.log(this.$parent);
},
//定义data中的值
data() {
return {
name : this.$parent.name
}
},
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
name : 'wxb',
age : 18
},
mounted() {
console.log('app父组件渲染完毕。。。');
},
})
</script>
</body>
</html>
2、父组件使用子组件数据($children)
A)搭基础框架
创建了三个不同类型的子组件
并且每个子组件都有自己的数据address
<!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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<b-div title="苹果"></b-div>
<b-p title="香蕉"></b-p>
<b-li title="菠萝"></b-li>
</div>
<script>
Vue.component('b-div', {
props : ['title'],
template : `
<div>{{ title }}---{{ name }}---{{ $parent.age }}</div>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '北京'
}
},
})
Vue.component('b-p', {
props : ['title'],
template : `
<p style="border:1px solid red">{{ title }}---{{ name }}---{{ $parent.age }}</p>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '上海'
}
},
})
Vue.component('b-li', {
props : ['title'],
template : `
<li style="background:green">{{ title }}---{{ name }}---{{ $parent.age }}</li>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '西安'
}
},
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
name : 'wxb',
age : 18
},
mounted() {
console.log('app父组件渲染完毕。。。');
},
})
</script>
</body>
</html>
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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<b-div title="苹果"></b-div>
<b-p title="香蕉"></b-p>
<b-li title="菠萝"></b-li>
</div>
<script>
Vue.component('b-div', {
props : ['title'],
template : `
<div>{{ title }}---{{ name }}---{{ $parent.age }}</div>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '北京'
}
},
})
Vue.component('b-p', {
props : ['title'],
template : `
<p style="border:1px solid red">{{ title }}---{{ name }}---{{ $parent.age }}</p>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '上海'
}
},
})
Vue.component('b-li', {
props : ['title'],
template : `
<li style="background:green">{{ title }}---{{ name }}---{{ $parent.age }}</li>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '西安'
}
},
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
name : 'wxb',
age : 18
},
mounted() {
console.log('app父组件渲染完毕。。。');
console.log(this.$children);
},
})
</script>
</body>
</html>
D)问题
也就是说,上面的$children所得到的数组,数组的顺序未必是我们使用组件的顺序
可以使用$refs来精确得到子组件的值(查看E内容)
<!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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<b-div title="苹果"></b-div>
<b-p title="香蕉"></b-p>
<b-li title="菠萝"></b-li>
</div>
<script>
Vue.component('b-div', {
props : ['title'],
template : `
<div>{{ title }}---{{ name }}---{{ $parent.age }}</div>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '北京'
}
},
})
Vue.component('b-p', {
props : ['title'],
template : `
<p style="border:1px solid red">{{ title }}---{{ name }}---{{ $parent.age }}</p>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '上海'
}
},
})
Vue.component('b-li', {
props : ['title'],
template : `
<li style="background:green">{{ title }}---{{ name }}---{{ $parent.age }}</li>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '西安'
}
},
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
name : 'wxb',
age : 18
},
mounted() {
console.log('app父组件渲染完毕。。。');
console.log(this.$children[0].address);
},
})
</script>
</body>
</html>
E)$refs
在子组件上添加ref属性,在父组件中通过$refs属性获取所有带ref属性的子组件
<!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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<b-div ref="pg" title="苹果"></b-div>
<b-p ref="xj" title="香蕉"></b-p>
<b-li ref="bl" title="菠萝"></b-li>
</div>
<script>
Vue.component('b-div', {
props : ['title'],
template : `
<div>{{ title }}---{{ name }}---{{ $parent.age }}</div>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '北京'
}
},
})
Vue.component('b-p', {
props : ['title'],
template : `
<p style="border:1px solid red">{{ title }}---{{ name }}---{{ $parent.age }}</p>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '上海'
}
},
})
Vue.component('b-li', {
props : ['title'],
template : `
<li style="background:green">{{ title }}---{{ name }}---{{ $parent.age }}</li>
`,
mounted() {
console.log(this.title+'渲染完毕。。。');
},
//定义data中的值
data() {
return {
name : this.$parent.name,
address : '西安'
}
},
})
//创建vue对象
let vm = new Vue({
el : "#app",
data: {
name : 'wxb',
age : 18
},
mounted() {
console.log('app父组件渲染完毕。。。');
//注意:这里的【0】,可能获取的不是第一个组件
console.log(this.$children[0].address);
//$children返回的是数组
console.log(this.$children);
//$refs返回的是对象,通过对象的属性获取对应的组件
console.log(this.$refs);
console.log(this.$refs.bl.address);
},
})
</script>
</body>
</html>
三、组件内部向组件外部通信($emit)
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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<b-search></b-search>
<div>b-search组件内部搜索的内容是:{{ text }}</div>
</div>
<script>
//开发阶段,取消生成提示信息
Vue.config.productionTip = false;
Vue.component('b-search', {
template:`
<div>
<input v-model="searchText" type="search" placeholder="请输入。。">
<button @click="search">搜索</button>
</div>
`,
data() {
return {
searchText:''
}
},
methods: {
search:function(){
console.log(this.searchText);
}
},
})
new Vue({
el:"#app",
data() {
return {
text:''
}
},
})
</script>
</body>
</html>
2、引出问题
输入框内的输入内容,在组件内部是可以得到并且使用的,但是在组件外部,如何获取使用?
3、解决办法
<!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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
<b-search @abc="getText"></b-search>
<b-search @abc="text=$event"></b-search>
<div>b-search组件内部搜索的内容是:{{ text }}</div>
</div>
<script>
//开发阶段,取消生成提示信息
Vue.config.productionTip = false;
Vue.component('b-search', {
template:`
<div>
<input @keyup.enter="search" v-model="searchText" type="text" placeholder="请输入。。">
<button @click="search">搜索</button>
</div>
`,
data() {
return {
searchText:''
}
},
methods: {
search:function(){
console.log(this.searchText);
//在search方法里需要将值传出去
//自定义一个事件,‘abc’为事件名,searchText为要传的参数
this.$emit('abc', this.searchText);
}
},
})
new Vue({
el:"#app",
data() {
return {
text:''
}
},
methods: {
getText(e){
console.log(e);
this.text = e;
}
},
})
</script>
</body>
</html>
四、常用vue开源库
https://element.eleme.cn/#/zh-CN/component/installation
http://v1.iviewui.com/docs/introduce
1、简单使用
注意要在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>Document</title>
</head>
<body>
<!--开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<div id="app">
<el-radio v-model="radio" label="1">备选项</el-radio>
<el-radio v-model="radio" label="2">备选项</el-radio>
</div>
<script>
//开发阶段,取消生成提示信息
Vue.config.productionTip = false;
new Vue({
el:"#app",
data () {
return {
radio: '1'
};
}
})
</script>
</body>
</html>