Vue - desarrollo de componentes

 Tabla de contenido

1. Uso básico de componentes.

1.1 Crear un objeto constructor de componentes

1.2 Registrar componentes

1.3 Usando componentes

2. Componentes globales y componentes locales

2.1 Componentes globales

2.2 Componentes parciales

3. La diferencia entre componentes principales y componentes secundarios.

4. Azúcar sintáctico para registrar componentes.

5. Escritura separada de plantillas de componentes.

5.1 etiqueta de secuencia de comandos

5.2 etiqueta de plantilla

6. Datos de los componentes

6.1 Problemas de almacenamiento

6.2 ¿Por qué los datos del componente deben ser una función?

7. El componente principal pasa datos al componente secundario.

7.1 Usando el atributo props, el componente principal pasa datos al componente secundario

7.2 Uso del atributo de accesorios

8. Comunicación de componentes

8.1 Paso de padre a hijo (Identificación de accesorios por parte de las jorobadas)

8.2 $emitir de hijo a padre

8.3 Caso de comunicación del componente padre-hijo

9. Acceso de los padres al niño (children-ref)


1. Uso básico de componentes.

​ Ejemplo de componente simple

<!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>

Los componentes son instancias de Vue reutilizables con un nombre: en este caso  my-cpn. Podemos  new Vue usar este componente como un elemento personalizado en una instancia raíz de Vue creada mediante:  <my-cpn></my-cpn>.

1.1 Crear un objeto constructor de componentes

template¿Dónde está el contenido del elemento DOM del componente?

1.2 Registrar componentes

  1. Registro global, aprobado  Vue.component .
  2. Matrícula parcial, aprobada  components:{cpnc:cpnc}.

1.3 Usando componentes

Utilice etiquetas html similares.

  <div id="app">
    <!-- 3.使用组件 -->
    <my-cpn></my-cpn>
    <my-cpn></my-cpn>
    <my-cpn></my-cpn>
    <cpnc></cpnc>
  </div>

2. Componentes globales y componentes locales

Hay dos formas de registrar componentes, una son componentes globales y la otra son componentes locales.

  <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 globales

Los componentes globales, que se pueden usar en múltiples instancias de vue, son similares a las variables globales.

Regístrate usando Vue.component('my-cpn', cpnc)el método y llama directamente <my-cpn></my-cpn>. my-cpnEs el nombre del componente global y cpnces el objeto del componente definido.

2.2 Componentes parciales

Los componentes locales solo se pueden usar en objetos montados por la instancia vue actual, similar a las variables locales, con alcance a nivel de bloque.

​ Cómo registrarse

    const app = new Vue({
      el:"#app",
      components:{//局部组件创建
        cpnc:cpnc
      }
    })

Utilice la misma forma que las variables globales y utilice <cpnc></cpnc>la llamada directamente. cpnc:cpncEl primer cpnc es el nombre dado al componente y el segundo es el objeto del componente definido. Si los dos tienen el mismo nombre, también puedes usar la sintaxis de es6 directamente:

components:{//局部组件创建
        cpnc
}

3. La diferencia entre componentes principales y componentes secundarios.

  <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>

En el código anterior, dos objetos componentes se definen cpn1y se registran usando componentes locales en cpn2el componente , y los registrados se usan en el componente , y luego los componentes locales se registran en la instancia vue y se llaman en el div montado por la instancia de vue y forma una relación de componente padre-hijo.cpn2cpn1templatecpn1cpn2cpn2cpn2cpn1

Nota: Un componente es una instancia de vue y los atributos de la instancia de vue también se pueden incluir en el componente, como datos, métodos, calculados, etc.

4. Azúcar sintáctico 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>

Al registrar un componente, no es necesario crear una instancia del objeto del componente, sino crear una instancia directamente al registrarlo. {}Es un objeto componente.

5. Escritura separada de plantillas de componentes.

5.1 etiqueta de secuencia de comandos

Utilice scriptetiquetas para definir la plantilla del componente y scriptel tipo de atención de la etiqueta es 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 plantilla

​ Utilice templateetiquetas para escribir contenido dentro de las etiquetas.

  <!-- 2.template标签 -->
  <template id="cpn2">
    <div>
      <h2>组件模板的分离写法</h2>
      <p>template标签</p>
    </div>
  </template>

Para llamar a la plantilla separada, usetemplate:'#cpn1'

  <script src="../js/vue.js"></script>
  <script>

    const app = new Vue({
      el: "#app",
      components: { //局部组件创建
        cpn1:{
          template:'#cpn1'
        },
        cpn2: {
          template: '#cpn2'
        }
      }
    })
  </script>

6. Datos de los componentes

6.1 Problemas de almacenamiento

Como se mencionó anteriormente, un componente vue es una instancia de vue y el componente vue correspondiente también tiene dataatributos para almacenar datos.

  <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>

templateUtilice los datos dentro del componente en msg.

6.2 ¿Por qué los datos del componente deben ser una función?

La idea de los componentes es la reutilización y definir componentes es, por supuesto, extraer elementos públicos comunes para su reutilización.

<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>

En el código anterior se definen dos componentes cpn1y dos contadores.Aunque los datos usan funciones, para simular se usa una constante para devolver el conteo.cpn2con1data:{count:0}obj

Como se puede ver en la figura, aquellos que no usan funciones dataparecen compartir el mismo countatributo, mientras que aquellos que usan funciones datausan sus propios conteos. Al igual que las variables locales, tienen un alcance a nivel de bloque. Este nivel de bloque es el alcance de Componentes de vista.

Cuando reutilizamos componentes, definitivamente esperamos que cada componente use sus propias variables. Si realmente necesitamos usar las mismas variables, podemos registrar componentes globalmente o usar vuex para la gestión del estado.

7. El componente principal pasa datos al componente secundario.

7.1 Usando propsatributos, los componentes principales pasan datos a los componentes secundarios

Usar propspropiedades de componentes

const cpn = {
  template: "#cpn",
  props: { 
          cmessage: {
          type: String,
          default: 'zzzzz',
          required: true //在使用组件必传值
          }
  }
}

Pasar valor al 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 del atributo de accesorios

Escritura de matriz

props: ['cmovies', 'cmessage']

Escritura de objetos

  props: { 
          cmessage: {
          type: String,
          default: 'zzzzz',
          required: true //在使用组件必传值
          }
  }

Restricciones de tipo en atributos de accesorios

//1.类型限制(多个类使用数组)
cmovies:Array,//限制为数组类型
cmessage:String,//限制为Strin类型
cmessage:['String','Number']//限制为String或Number类型

El valor predeterminado del atributo de accesorios.

// 2.提供一些默认值,以及必传值
        cmessage: {
          type: String,
          default: 'zzzzz',//默认值
        }

El valor requerido del atributo de accesorios.

cmessage: {
          type: String,
          default: 'zzzzz',
          required: true //在使用组件必传值
        }

El tipo es Objeto/Matriz, el valor predeterminado debe ser una función

//El tipo es Objeto/Matriz, el valor predeterminado debe ser una función
cmovies: {
	type: Array,
	default () {
		return [1, 2, 3, 4]
	}
},

función de validación 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 integral

<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. Comunicación de componentes

8.1 Paso de padre a hijo (Identificación de accesorios por parte de las jorobadas)

​v-bind no admite el uso de camel case, por ejemplo, cUseres necesario cambiarlo a 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>

los accesorios reciben el tipo de referencia

<!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 Hijo y padre$emit

Los componentes secundarios pasan valores a los componentes principales mediante 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 un método en el subcomponente btnClick(item), use $emit, 'itemclick' es el nombre del evento y itemel valor pasado.

methods: {
        btnClick(item) {
          this.$emit('itemclick', item)
        }
      },

2. Escuche el evento de clic en el componente secundario y vuelva a llamar a este método.

  <div>
      <button v-for="(item, index) in categoties" :key="index" @click="btnClick(item)">{
   
   {item.name}}</button>
   </div>

3. Defina un método cpnClcik(item) en el componente principal

methods: {
	cpnClcik(item) {
		console.log('cpnClick'+item.name);
	}
},

4. Y llámelo en el componente principal (instancia de vue) <cpn @itemclick="cpnClcik"></cpn>( el elemento de btnClick se pasa de forma predeterminada sin escribir parámetros  ), y el componente principal escucha itemclickel evento pasado por el componente secundario con el nombre del evento.

<cpn @itemclick="cpnClcik"></cpn>


Escuche eventos de clics 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 comunicación del componente padre-hijo

<!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>

El error anterior no puede cambiar directamente el valor en los accesorios, se puede cambiar a lo siguiente

<!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>

Implemente el valor de la vinculación bidireccional de los componentes padre-hijo.

<!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>

Utilice el reloj para lograrlo.

<!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 me di cuenta
<!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. Acceso de los padres al niño (children-ref)

Cuando el componente principal accede al componente secundario, a veces es necesario manipular directamente el método o propiedad del componente secundario, en este caso, $childrenes necesario $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>

$childrenForma

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

Al utilizar this.$childrensubcomponentes directos que obtienen directamente la ** instancia actual, cabe señalar que  $children el orden no está garantizado ni responde. **Si intenta  $children vincular datos con , considere usar una matriz  v-for para generar componentes secundarios y use Array como fuente real.

Método $refs: ref se utiliza para registrar información de referencia para elementos o subcomponentes. La información de referencia se registrará en el objeto $refs del componente principal. Si se usa en un elemento DOM normal, la referencia apunta al elemento DOM; si se usa en un componente secundario, la referencia apunta a la instancia del componente:

El uso básico de ref se utiliza en 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>

Primero defina los subcomponentes

<cpn ref="aaa"></cpn>

llamar directamente

El uso de referencia en 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可以调用组件中的方法 -->

Esto es para componentes dinámicos y funciona según las restricciones de la plantilla dentro del DOM.

Funciona en base a las limitaciones de las plantillas dentro del 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 es el caso del sitio web 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>

Supongo que te gusta

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