Vue - desenvolvimento de componentes

 Índice

1. Uso básico de componentes

1.1 Crie um objeto construtor de componente

1.2 Cadastrar componentes

1.3 Usando componentes

2. Componentes globais e componentes locais

2.1 Componentes globais

2.2 Componentes parciais

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

Etiqueta de script 5.1

5.2 etiqueta de modelo

6. Dados dos 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

7.2 Uso do atributo props

8. Comunicação de componentes

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

templateonde está o conteúdo do elemento DOM do componente.

1.2 Cadastrar componentes

  1. Registro global, aprovado  Vue.component .
  2. 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:cpncO 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 cpn1e registrados usando componentes locais no cpn2componente , 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.cpn2cpn1templatecpn1cpn2cpn2cpn2cpn1

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 scripta tag para definir o modelo do componente, e scripto 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 templatetags 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, usetemplate:'#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 dataatributos 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>

templateUse 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 cpn1e dois contadores. Embora os dados utilizem funções, para simular , uma constante é utilizada para retornar a contagem.cpn2con1data:{count:0}obj

Como pode ser visto na figura, aqueles que não usam funções dataparecem compartilhar o mesmo countatributo, enquanto aqueles que usam funções datausam 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 propsatributos, os componentes pai passam dados para componentes filhos

Usando propspropriedades 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, cUserele 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 itemo 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 itemclicko 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, $childrene 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>

$childrenCaminho

// 1.children
console.log(this.$children[0].showMessage)
for (let cpn of this.$children) {
    console.log(cpn.showMessage)
}

Usando this.$childrensubcomponentes 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>

Acho que você gosta

Origin blog.csdn.net/m0_46461853/article/details/126240185
Recomendado
Clasificación