Índice
1.1 Crie um objeto construtor de componente
2. Componentes globais e componentes locais
3. A diferença entre componentes pais e componentes filhos
4. Açúcar sintático para registrar componentes
5. Escrita separada de modelos de componentes
6.1 Problemas de armazenamento
6.2 Por que os dados do componente devem ser uma função
7. O componente pai passa dados para o componente filho
7.1 Usando o atributo props, o componente pai passa dados para o componente filho
8.1 Passagem de pai para filho (Identificação de adereços da jubarte)
8.2 $emitido de filho para pai
8.3 Caso de comunicação do componente pai-filho
9. Acesso dos pais ao filho (filhos-ref)
1. Uso básico de componentes
Exemplo de componente simples
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 3.使用组件 -->
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<cpnc></cpnc>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建组件构造器对象
const cpnc = Vue.extend({
template:`
<div>
<h2>标题</h2>
<p>内容1...<p>
<p>内容2...<p>
</div>`
})
// 2.全局注册组件
Vue.component('my-cpn', cpnc)
const app = new Vue({
el:"#app",
data:{
},
components:{
//局部组件创建
cpnc:cpnc
}
})
</script>
</body>
</html>
Os componentes são instâncias reutilizáveis do Vue com um nome: neste caso my-cpn
. Podemos new Vue
usar este componente como um elemento personalizado em uma instância raiz do Vue criada via: <my-cpn></my-cpn>
.
1.1 Crie um objeto construtor de componente
template
onde está o conteúdo do elemento DOM do componente.
1.2 Cadastrar componentes
- Registro global, aprovado
Vue.component
. - Registro parcial, aprovado
components:{cpnc:cpnc}
.
1.3 Usando componentes
Use tags HTML semelhantes.
<div id="app">
<!-- 3.使用组件 -->
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<cpnc></cpnc>
</div>
2. Componentes globais e componentes locais
Existem duas maneiras de registrar componentes, uma é com componentes globais e a outra é com componentes locais.
<div id="app">
<h2>全局组件</h2>
<my-cpn></my-cpn>
<h2>局部组件</h2>
<cpnc></cpnc>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建组件构造器对象
const cpnc = Vue.extend({
template:`
<div>
<h2>标题</h2>
<p>内容1</p>
<p>内容2</p>
</div>`
})
// 2.注册组件(全局组件,可以在多个vue实例中使用)
Vue.component('my-cpn', cpnc)
const app = new Vue({
el:"#app",
components:{//局部组件创建
cpnc:cpnc
}
})
</script>
2.1 Componentes globais
Os componentes globais, que podem ser usados em múltiplas instâncias vue, são semelhantes às variáveis globais.
Cadastre-se usando Vue.component('my-cpn', cpnc)
o método e ligue diretamente <my-cpn></my-cpn>
. my-cpn
É o nome do componente global e cpnc
é o objeto do componente definido.
2.2 Componentes parciais
Componentes locais só podem ser usados em objetos montados pela instância vue atual, semelhante às variáveis locais, com escopo em nível de bloco.
Como se registrar
const app = new Vue({
el:"#app",
components:{//局部组件创建
cpnc:cpnc
}
})
Use da mesma forma que variáveis globais, use diretamente <cpnc></cpnc>
a chamada. cpnc:cpnc
O primeiro cpnc é o nome dado ao componente e o segundo é o objeto componente definido. Se os dois tiverem o mesmo nome, você também poderá usar a sintaxe es6 diretamente:
components:{//局部组件创建
cpnc
}
3. A diferença entre componentes pais e componentes filhos
<div id="app">
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建组件构造器对象
const cpn1 = Vue.extend({
template:`
<div>
<h2>标题1</h2>
<p>组件1</p>
</div>`
})
// 组件2中使用组件1
const cpn2 = Vue.extend({
template:`
<div>
<h2>标题2</h2>
<p>组件2</p>
<cpn1></cpn1>
</div>`,
components:{
cpn1:cpn1
}
})
const app = new Vue({
el:"#app",
components:{//局部组件创建
cpn2:cpn2
}
})
</script>
No código acima, dois objetos componentes são definidos cpn1
e registrados usando componentes locais no cpn2
componente , e os registrados são usados no componente , e então os componentes locais são registrados na instância vue e chamados no div montado por a instância vue e formar um relacionamento de componente pai-filho.cpn2
cpn1
template
cpn1
cpn2
cpn2
cpn2
cpn1
Nota: Um componente é uma instância vue, e os atributos da instância vue também podem ser incluídos no componente, como dados, métodos, computados, etc.
4. Açúcar sintático para registrar componentes
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.注册全局组件语法糖
Vue.component('cpn1', {
template:`
<div>
<h2>全局组件语法糖</h2>
<p>全局组件语法糖</p>
</div>`
})
const app = new Vue({
el:"#app",
components:{//局部组件创建
cpn2:{
template:`
<div>
<h2>局部组件语法糖</h2>
<p>局部组件语法糖</p>
</div>`
}
}
})
</script>
Ao registrar um componente, você não precisa instanciar o objeto do componente, mas instanciá-lo diretamente durante o registro. {}
É um objeto componente.
5. Escrita separada de modelos de componentes
Etiqueta de script 5.1
Use script
a tag para definir o modelo do componente, e script
o tipo de atenção da tag é text/x-template
.
<!-- 1.script标签注意类型是text/x-template -->
<script type="text/x-template" id="cpn1">
<div>
<h2>组件模板的分离写法</h2>
<p>script标签注意类型是text/x-template</p>
</div>
</script>
5.2 etiqueta de modelo
Use template
tags para escrever conteúdo dentro de tags.
<!-- 2.template标签 -->
<template id="cpn2">
<div>
<h2>组件模板的分离写法</h2>
<p>template标签</p>
</div>
</template>
Para chamar o modelo desanexado, use
template:'#cpn1'
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
components: { //局部组件创建
cpn1:{
template:'#cpn1'
},
cpn2: {
template: '#cpn2'
}
}
})
</script>
6. Dados dos componentes
6.1 Problemas de armazenamento
Como mencionado anteriormente, um componente vue é uma instância vue, e o componente vue correspondente também possui data
atributos para armazenar dados.
<div id="app">
<cpn1></cpn1>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
components: { //局部组件创建
cpn1:{
template:'<div>{
{msg}}</div>',
data(){
return {
msg:"组件的数据存放必须要是一个函数"
}
}
}
}
})
</script>
template
Use os dados dentro do componente em msg
.
6.2 Por que os dados do componente devem ser uma função
A ideia dos componentes é reutilizar, e definir componentes é, obviamente, extrair coisas públicas comuns para reutilização.
<div id="app">
<h2>data不使用函数</h2>
<cpn1></cpn1>
<cpn1></cpn1>
<hr>
<h2>data使用函数</h2>
<cpn2></cpn2>
<cpn2></cpn2>
<hr>
</div>
<script src="../js/vue.js"></script>
<template id="cpn1">
<div>
<button @click="count--">-</button>
当前计数:{
{count}}
<button @click="count++">+</button>
</div>
</template>
<template id="cpn2">
<div>
<button @click="count--">-</button>
当前计数:{
{count}}
<button @click="count++">+</button>
</div>
</template>
<script>
const obj = {
count:0
};
const app = new Vue({
el: "#app",
components: { //局部组件创建
cpn1: {
template: '#cpn1',
data() {
return obj;
}
},
cpn2: {
template: '#cpn2',
data() {
return {
count: 0
}
}
}
}
})
</script>
No código acima são definidos dois componentes cpn1
e dois contadores. Embora os dados utilizem funções, para simular , uma constante é utilizada para retornar a contagem.cpn2
con1
data:{count:0}
obj
Como pode ser visto na figura, aqueles que não usam funções data
parecem compartilhar o mesmo count
atributo, enquanto aqueles que usam funções data
usam suas próprias contagens. Assim como as variáveis locais, elas têm escopo em nível de bloco. Este nível de bloco é o escopo de Componentes Vue.
Quando reutilizamos componentes, definitivamente esperamos que cada componente use suas próprias variáveis. Se realmente precisarmos usar as mesmas variáveis, podemos registrar componentes globalmente ou usar vuex para gerenciamento de estado.
7. O componente pai passa dados para o componente filho
7.1 Usando props
atributos, os componentes pai passam dados para componentes filhos
Usando
props
propriedades de componentes
const cpn = {
template: "#cpn",
props: {
cmessage: {
type: String,
default: 'zzzzz',
required: true //在使用组件必传值
}
}
}
Passar valor para objeto cmessage
<div id="app">
<cpn :cMessage="message"></cpn>
</div>
<script>
const app = new Vue({
el: "#app",
data: {
message: "你好",
movies: ["复仇者联盟", "钢铁侠", "星际穿越", "哪吒传奇"]
},
components: {
cpn
}
})
</script>
7.2 Uso do atributo props
Escrita de matriz
props: ['cmovies', 'cmessage']
Escrita de objeto
props: {
cmessage: {
type: String,
default: 'zzzzz',
required: true //在使用组件必传值
}
}
Restrições de tipo em atributos de props
//1.类型限制(多个类使用数组)
cmovies:Array,//限制为数组类型
cmessage:String,//限制为Strin类型
cmessage:['String','Number']//限制为String或Number类型
O valor padrão do atributo props
// 2.提供一些默认值,以及必传值
cmessage: {
type: String,
default: 'zzzzz',//默认值
}
O valor necessário do atributo props
cmessage: {
type: String,
default: 'zzzzz',
required: true //在使用组件必传值
}
O tipo é Object/Array, o valor padrão deve ser uma função
//O tipo é Object/Array, o valor padrão deve ser uma função
cmovies: {
type: Array,
default () {
return [1, 2, 3, 4]
}
},
função de validação personalizada
vaildator: function (value) {
//这个传递的值必须匹配下列字符串中的一个
return ['zzzzz', 'ttttt', 'yyy'].indexOf(value) !== -1
}
tipo personalizado
function Person(firstName,lastName) {
this.firstName = firstName
this.lastName = lastName
}
cmessage:Person//限定了cmeessage必须是Person类型
uso abrangente
<div id="app">
<cpn :cMovies="movies" :cMessage="message"></cpn>
</div>
<template id="cpn">
<div>
<ul>
<li v-for="(item, index) in cmovies" :key="index">{
{item}}</li>
</ul>
<h2>{
{cmessage}}</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
function Person(firstName,lastName) {
this.firstName = firstName
this.lastName = lastName
}
// 父传子:props
const cpn = {
template: "#cpn",
// props: ['cmovies', 'cmessage'],//数组写法
props: { //对象写法
// 1.类型限制(多个类使用数组)
// cmovies:Array,
// cmessage:String,
// cmessage:['String','Number'],
// 2.提供一些默认值,以及必传值
cmessage: {
type: String,
default: 'zzzzz',
required: true //在使用组件必传值
},
//类型是Object/Array,默认值必须是一个函数
cmovies: {
type: Array,
default () {
return [1, 2, 3, 4]
}
},
// 3.自定义验证函数
// vaildator: function (value) {
// //这个传递的值必须匹配下列字符串中的一个
// return ['zzzzz', 'ttttt', 'yyy'].indexOf(value) !== -1
// }
// 4.自定义类型
// cmessage:Person,
},
data() {
return {
}
},
methods: {
},
};
const app = new Vue({
el: "#app",
data: {
message: "你好",
movies: ["复仇者联盟", "钢铁侠", "星际穿越", "哪吒传奇"]
},
components: {
cpn
}
})
</script>
8. Comunicação de componentes
8.1 Passagem de pai para filho (Identificação de adereços da jubarte)
v-bind não suporta o uso de camel case, por exemplo, cUser
ele precisa ser alterado para c-User
.
<div id="app">
<!-- v-bind不支持驼峰 :cUser改成 :c-User-->
<!-- <cpn :cUser="user"></cpn> -->
<cpn :c-User="user"></cpn>
<cpn :cuser="user" ></cpn>
</div>
<template id="cpn">
<div>
<!-- 使用驼峰 -->
<h2>{
{cUser}}</h2>
<!-- 不使用 -->
<h2>{
{cuser}}</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 父传子:props
const cpn = {
template: "#cpn",
props: { //对象写法
//驼峰
cUser:Object,
//未使用驼峰
cuser:Object
},
data() {return {}},
methods: {},
};
const app = new Vue({
el: "#app",
data: {
user:{
name:'zzz',
age:18,
height:175
}
},
components: {
cpn
}
})
</script>
adereços recebem tipo de referência
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- <cpn1 :msg="message"></cpn1> -->
<!-- <cpn1 :msg="message2"></cpn1> -->
<cpn1 :msgab="add"></cpn1>
<h2>{
{count}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
/* message: ['蔡英文', '吴钊燮'] */
/* message2:{
name:'蔡英文',
age:56,
sex:'女'
} */
count:0
},
methods: {
add:function(){
return this.count++
}
},
computed: {
},
components: {
cpn1: {
/* template: `
<div>我是中国人{
{msg.name}}{
{msg.sex}}</div>
`, */
template: `
<div>
<div @click="sum">+</div>
</div>
`,
props: {
/* msg:{
type: Array
} */
/* msg:{
type: Object
} */
msgab:{
type:Function
},
},
methods:{
sum(){
this.msgab()
}
}
}
}
})
</script>
</body>
</html>
8.2 Filho e pai$emit
Os componentes filhos passam valores para os componentes pais, usando eventos personalizados $emit
.
<!-- 父组件 -->
<div id="app">
<!-- 不写参数默认传递btnClick的item -->
<cpn @itemclick="cpnClcik"></cpn>
</div>
<!-- 子组件 -->
<template id="cpn">
<div>
<button v-for="(item, index) in categoties" :key="index" @click="btnClick(item)">{
{item.name}}</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const cpn = {
template: "#cpn",
data() {
return {
categoties: [{
id: 'aaa',
name: '热门推荐'
},
{
id: 'bbb',
name: '手机数码'
},
{
id: 'ccc',
name: '家用家电'
},
{
id: 'ddd',
name: '电脑办公'
},
]
}
},
methods: {
btnClick(item) {
this.$emit('itemclick', item)
}
},
};
const app = new Vue({
el: "#app",
data() {
return {
}
},
methods: {
cpnClcik(item) {
console.log('cpnClick'+item.name);
}
},
components: {
cpn
},
})
</script>
1. Defina um método no subcomponente btnClick(item)
, use $emit
, 'itemclick' é o nome do evento e item
o valor passado.
methods: {
btnClick(item) {
this.$emit('itemclick', item)
}
},
2. Ouça o evento click no componente filho e chame de volta este método
<div>
<button v-for="(item, index) in categoties" :key="index" @click="btnClick(item)">{
{item.name}}</button>
</div>
3. Defina um método cpnClcik(item) no componente pai
methods: {
cpnClcik(item) {
console.log('cpnClick'+item.name);
}
},
4. E chame-o no componente pai (instância vue) <cpn @itemclick="cpnClcik"></cpn>
( o item de btnClick é passado por padrão sem escrever parâmetros ), e o componente pai escuta itemclick
o evento passado pelo componente filho com o nome do evento.
<cpn @itemclick="cpnClcik"></cpn>
Ouça eventos de clique nativos
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
<div id="app">
<cpn @click.native="btnClick">点击</cpn>
</div>
<!-- 子组件 -->
<template id="cpn">
<div>
我是子组件
</div>
</template>
</body>
<script type="text/javascript">
// 父传子:props
const cpn = {
template: "#cpn",
data() {
return {
name:"我是子组件的name"
}
}
};
const app = new Vue({
el: "#app",
data() {
return {
message:"hello"
}
},
methods: {
btnClick(){
console.log('click')
}
},
components: {
cpn
},
})
</script>
</html>
8.3 Caso de comunicação do componente pai-filho
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>组件通信-父子通信案例</title>
</head>
<body>
<!-- 父组件 -->
<div id="app">
<cpn :number1='num1' :number2='num2'></cpn>
</div>
<!-- 子组件 -->
<template id="cpn">
<div>
<h2>number1:{
{number1}}</h2>
<input type="text" v-model="number1">
<h2>number2:{
{number2}}</h2>
<input type="text" v-model="number2">
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 父传子:props
const cpn = {
template: "#cpn",
data() {
return {
}
},
props:{
number1:[Number,String],
number2:[Number,String],
},
};
const app = new Vue({
el: "#app",
data: {
num1:1,
num2:2
},
components: {
cpn
},
})
</script>
</body>
</html>
O erro acima não pode alterar diretamente o valor nos adereços, ele pode ser alterado para o seguinte
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>组件通信-父子通信案例</title>
</head>
<body>
<!-- 父组件 -->
<div id="app">
<cpn :number1='num1' :number2='num2'></cpn>
</div>
<!-- 子组件 -->
<template id="cpn">
<div>
<h2>number1:{
{number1}}</h2>
<h2>number1:{
{dnumber1}}</h2>
<input type="text" v-model="dnumber1">
<h2>number2:{
{number2}}</h2>
<h2>number2:{
{dnumber2}}</h2>
<input type="text" v-model="dnumber2">
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 父传子:props
const cpn = {
template: "#cpn",
data() {
return {
dnumber1:this.number1,
dnumber2:this.number2
}
},
props:{
number1:[Number,String],
number2:[Number,String],
},
};
const app = new Vue({
el: "#app",
data: {
num1:1,
num2:2
},
components: {
cpn
},
})
</script>
</body>
</html>
Perceba o valor da ligação bidirecional dos componentes pai-filho.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>组件通信-父子通信案例</title>
</head>
<body>
<!-- 父组件 -->
<div id="app">
<h2>子组件</h2>
<cpn :number1='num1' :number2='num2'
@num1change="num1Change"
@num2change="num2Change"></cpn>
<h2>--------------</h2>
<h2>父组件{
{num1}}</h2>
<input type="text" v-model="num1" >
<h2>父组件{
{num2}}</h2>
<input type="text" v-model="num2">
</div>
<!-- 子组件 -->
<template id="cpn">
<div>
<h2>number1:{
{number1}}</h2>
<h2>dnumber1:{
{dnumber1}}</h2>
<input type="text" :value="dnumber1" @input="num1input">
<h2>number2:{
{number2}}</h2>
<h2>dnumber2:{
{dnumber2}}</h2>
<input type="text" :value="dnumber2" @input="num2input">
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 父传子:props
const cpn = {
template: "#cpn",
data() {
return {
dnumber1:this.number1,
dnumber2:this.number2
}
},
props:{
number1:[Number,String],
number2:[Number,String],
},
methods: {
num1input(event){
this.dnumber1 = event.target.value
this.$emit('num1change',this.dnumber1)
},
num2input(event){
this.dnumber2 = event.target.value
this.$emit('num2change',this.dnumber2)
}
},
};
const app = new Vue({
el: "#app",
data: {
num1:1,
num2:2
},
methods: {
num1Change(value){
this.num1=value
},
num2Change(value){
this.num1=value
}
},
components: {
cpn
},
})
</script>
</body>
</html>
Use o relógio para conseguir.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>组件通信-父子通信案例(watch实现)</title>
</head>
<body>
<!-- 父组件 -->
<div id="app">
<cpn :number1='num1' :number2='num2' @num1change="num1Change" @num2change="num2Change"></cpn>
<h2>父组件{
{num1}}</h2>
<input type="text" v-model="num1" >
<h2>父组件{
{num2}}</h2>
<input type="text" v-model="num2">
</div>
<!-- 子组件 -->
<template id="cpn">
<div>
<h2>{
{number1}}</h2>
<input type="text" v-model="dnumber1">
<h2>{
{number2}}</h2>
<input type="text" v-model="dnumber2">
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 父传子:props
const cpn = {
template: "#cpn",
data() {
return {
dnumber1:this.number1,
dnumber2:this.number2
}
},
props:{
number1:[Number,String],
number2:[Number,String],
},
watch: {
dnumber1(newValue){
this.dnumber1 = newValue
this.$emit('num1change',newValue)
},
dnumber2(newValue){
this.dnumber1 = newValue
this.$emit('num2change',newValue)
}
},
};
const app = new Vue({
el: "#app",
data() {
return {
num1:1,
num2:2,
}
},
methods: {
num1Change(value){
this.num1=value*10
},
num2Change(value){
this.num1=value*100
}
},
components: {
cpn
},
})
</script>
</body>
</html>
finalmente percebi
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<h2>子组件</h2>
<cpn :number1="num1" :number2="num2" @num1change="Num1change" @num2change="Num2change"></cpn>
<h2>--------------</h2>
<h2>父组件{
{num1}}</h2>
<input type="text" v-model="num1">
<h2>父组件{
{num2}}</h2>
<input type="text" v-model="num2">
</div>
<template id="cpn">
<div>
<h2>dnumber1:{
{dnumber1}}</h2>
<h2>number1:{
{number1}}</h2>
<input type="text" v-model="dnumber1"/>
<br />
<h2>dnumber2:{
{dnumber2}}</h2>
<h2>number2:{
{number2}}</h2>
<input type="text" v-model="dnumber2"/>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
/* 子组件 */
const cpn = {
template: '#cpn',
data() {
return {
dnumber1: this.number1,
dnumber2: this.number2
}
},
props: {
number1: {
type: [Number,String]
},
number2: {
type:[Number,String]
}
},
watch:{
dnumber1(n){
this.$emit('num1change', n/100)
},
dnumber2(n){
this.$emit('num2change', n*100)
},
number1(n){
this.dnumber1 = n*100
},
number2(n){
this.dnumber2 = n/100
}
}
}
/* 父组件 */
const app = new Vue({
el: "#app",
data() {
return {
num1: 1,
num2: 2
}
},
methods: {
Num1change(value) {
this.num1 = value
},
Num2change(value) {
this.num2 = value
}
},
computed: {
},
components: {
cpn
}
})
</script>
</body>
</html>
9. Acesso dos pais ao filho (filhos-ref)
Quando o componente pai acessa o componente filho, às vezes é necessário manipular diretamente os métodos ou propriedades do componente filho. Neste caso, $children
e são necessários $ref
.
<!-- 父组件 -->
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn ref="aaa"></cpn>
<button @click="btnClick" >按钮</button>
</div>
<!-- 子组件 -->
<template id="cpn">
<div>
我是子组件
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 父传子:props
const cpn = {
template: "#cpn",
data() {
return {
name:"我是子组件的name"
}
},
methods: {
showMessage(){
console.log("showMessage");
}
},
};
const app = new Vue({
el: "#app",
data() {
return {
message:"hello"
}
},
methods: {
btnClick(){
// 1.children
// console.log(this.$children[0].showMessage)
// for (let cpn of this.$children) {
// console.log(cpn.showMessage)
// }
// 2.$ref
console.log(this.$refs.aaa.name)
}
},
components: {
cpn
},
})
</script>
$children
Caminho
// 1.children
console.log(this.$children[0].showMessage)
for (let cpn of this.$children) {
console.log(cpn.showMessage)
}
Usando this.$children
subcomponentes diretos que obtêm diretamente a **instância atual, deve-se observar que $children
o pedido não é garantido, nem é responsivo. **Se você estiver tentando $children
vincular dados com , considere usar um array v-for
para gerar componentes filhos e usar Array como a fonte real.
Método $refs: ref é usado para registrar informações de referência para elementos ou subcomponentes. As informações de referência serão registradas no objeto $refs do componente pai. Se usado em um elemento DOM normal, a referência aponta para o elemento DOM; se usado em um componente filho, a referência aponta para a instância do componente:
O uso básico de ref é usado em elementos
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<p ref="p" @click="handelClick" id="ppp">hello</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
},
methods: {
handelClick(){
console.log(this.$refs.p);
const ppp = document.querySelector('#ppp')
console.log(ppp);
}
},
computed:{
}
})
</script>
</body>
</html>
Defina os subcomponentes primeiro
<cpn ref="aaa"></cpn>
ligue diretamente
O uso de ref em subcomponentes
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<counter ref="one" @change="handelChange"></counter>
<counter ref="two" @change="handelChange"></counter>
<div>total:{
{total}}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
Vue.component('counter',{
template:'<div @click="handelclick">{
{number}}</div>',
data(){
return {
number:0
}
},
methods:{
handelclick(){
this.number++;
this.$emit('change');
}
}
})
const app = new Vue({
el: "#app",
data: {
total:0
},
methods: {
handelChange(){
this.total = this.$refs.one.number + this.$refs.two.number
}
},
computed:{
}
})
</script>
</body>
</html>
<!-- ref可以调用组件中的数据 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<helloworld ref="hello"></helloworld>
<button @click="getHello">获取helloworld组件中的值</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
Vue.component('helloworld',{
template:'<div></div>',
data(){
return {
number:0
}
},
methods:{
handelclick(){
console.log('被调用了');
}
}
})
const app = new Vue({
el: "#app",
data: {
},
methods: {
getHello(){
this.$refs.hello.handelclick();
console.log(this.$refs.hello.number);
console.log(this.$refs.hello.$el.innerHTML);
}
},
computed:{
}
})
</script>
</body>
</html>
<!-- ref可以调用组件中的方法 -->
Isto é para componentes dinâmicos e funciona com base nas restrições do modelo dentro do DOM.
Funciona com base nas restrições de modelos dentro do DOM
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<table>
<tr is="row">
</tr>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script>
Vue.component('row',{
template:'<tr><td>111</td></tr>'
})
const app = new Vue({
el: "#app",
data() {
return {}
},
methods: {
},
computed:{
}
})
</script>
</body>
</html>
Componente componente dinâmico
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!-- <child-one></child-one>
<child-two></child-two> -->
<component :is="type"></component>
<button @click="handerClick">点击</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('child-one',{
template:'<div>child-one</div>'
})
Vue.component('child-two',{
template:'<div>child-two</div>'
})
const app = new Vue({
el:'#app',
data(){
return {
type:'child-one'
}
},
methods:{
handerClick(){
console.log('111');
this.type=this.type==='child-one'?'child-two':'child-one';
}
}
})
</script>
</body>
</html>
Este é o caso do site oficial de componentes dinâmicos
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<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="app">
<button v-for="(tab,index) in tabs":key="index" @click="handelclick(tab)" :class="getStyle(tab)">{
{tab}}</button>
<component :is="currentTabComponent"></component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('tab-home',{
template:'<div>child-one</div>'
})
Vue.component('tab-posts',{
template:'<div>child-two</div>'
})
Vue.component('tab-archive',{
template:'<div>child-three</div>'
})
const app = new Vue({
el:'#app',
data(){
return {
currentTab: "Home",
tabs: ["Home", "Posts", "Archive"]
}
},
methods:{
handelclick(tab){
this.currentTab = tab
},
getStyle(tab){
return ['tab-button',{active:this.currentTab===tab}]
}
},
computed:{
currentTabComponent(){
/* return `tab-${this.currentTab}`.toLowerCase() */
return "tab-"+this.currentTab.toLowerCase()
},
}
})
</script>
</body>
</html>