2021-06-18vue第三天

一、组件

(1)组件只有 导入并注册 后才能使用
(2)HTML对字母大小写不敏感。组件名、属性名使用短横线连接,就不要再用大写字母了。

1. 全局组件的注册

Vue.component(" 组件名称 ",{
  data:组件数据,
  template:组件模板内容
}
调用组件:<组件名称>

(1)组件中的 data 参数必须是 函数 ,同时这个函数要求返回一个对象。(因为函数可以形成闭包,保证每次组件调用时都有独立的数据。)
(2)组件模板 template 必须是 单个根元素。也就是所有模板内容都要放到一个大盒子内。
(3)组件模板 template 可以是 字符串,也可以是 ES6 的 模板字符串。(主要解决传统字符串不能随意换行的问题)
(4)组件可以在 HTML标签内调用(vue实例对象),也可以在其他组件的模板 template 中调用
(5)组件命名时,可以用 短横线连接,也可以用 驼峰式 命名法。
(6)组件调用时,如果是在HTML标签内调用(vue实例对象),组件名必须 转化为 短横线连接;如果是在其他组件的 template 中调用,也可以用驼峰式。
(7)组件可以重复使用多次 。因为data中返回的是一个对象,所以 每个组件中的数据是私有的,即每个实例可以维护一份被返回对象的独立的拷贝。
(8)自定义组件的注册要放到 vue实例对象 之前。vue实例对象也是组件

      
2. 局部组件的注册

components: {
   HelloWorld:{
      template: '

局部组件
',
    },
}

(1)在vue实例对象中添加 components 属性。components 是一个对象,属性名是 组件名,属性值是 配置对象
(2)和自定义局部指令、局部过滤器一样,局部组件只能在注册它的父组件内使用
也就是,在vue实例对象中注册的局部组件只能在vue实例对象中使用。其他的全局组件不能使用。

    
3. 组件统一注册为全局组件(重点)

(1)想要把多个组件注册为全局可用的子组件,直接在 main.js 中用 Import导入,然后用 Vue.component( ) 注册,代码很多,不合适。
(2)这里,我们把导入和注册的代码单独封装到一个工具组件中。在main.js里,使用 Vue.use( )方法 执行工具组件中的代码。
(3)Vue.use( )方法接收一个配置对象,对象里面有一个 install( vue )函数,参数Vue是 Vue实例对象。

首先在工具组件Component中执行组件的全局注册

// 该文件负责所有的公共的组件的全局注册  
// 1.导入组件
import PageTools from './PageTools'
export default {
  install(Vue) {
    //  2.全局注册组件
    Vue.component('PageTools', PageTools)
  }
}

然后在 main.js中调用工具组件Component,执行其中的代码。

import Component from '@/components'
Vue.use(Component) // 注册自己的插件

二、vue 调试工具的安装

三、组件之间的相互传值

1. 父组件向子组件传值 (自定义属性)

Vue.component("child",{
props:[ " title "],
template:"

{{ title }

}
在父组件中调用:< child v-bind:title=" title ">

① 父子组件的形成

  • 通过路由的 children 属性可以形成 父子组件 的关系;
  • 通过在父组件内 导入、注册、调用子组件也可以形成父子组件的关系;
  • 父组件调用子组件时,可以用 <子组件名称 />的形式,还可以用路由中学的的方式调用子组件。
    注意:使用 标签时,不仅要注册子组件,还要把子组件的名字在data中定义。

② 父组件调用子组件时,通过给子组件 【添加自定义属性】 的形式传值。

③ 父组件传值时, 可以是静态的,也可以 用 v-bind绑定父组件的data数据

④ 子组件在内部添加 【props】 属性来接收父组件传递的数据。props是一个 数组

⑤ 这样就可以在子组件模板 template 内使用传递的数据了。

props 数组中接收的数据,可以是 数据名称的字符串

props 数组中接收的数据也可以是一个对象,规定每个数据的类型、是否必须等。

props: {
   channel: {
      //可选数据类型
      type: [Object,Number,String],
      //是否必要
      required: true
      //默认值, 数组和对象必须用下面的方式定义
      default:function(){
          return {}
      }
       //校验规则,防止传入数据不符合要求导致代码崩溃。
      validator: function (value) {
        return value >= 0
      }
    } 
}

⑧ 在HTML标签中使用 属性名 时,必须转化为短横线连接;在 template 模板中可以使用驼峰式命名。

{{fmsg}}

⑨ 一个组件想要被 重用,某些数据就不要写在data中变成组件的私有数据,而是写在 props数组中,这样可以由父组件在调用时传入。

⑩ 父组件通过props传递给子组件的数据时异步执行的。比如父组件内点击表格中的某一行数据,可以把当前行的id传给弹出层子组件,但是弹出层子组件不能用props中的id发起Ajax请求获取数据,而是应该在子组件封装获取数据的方法,在父组件中调用子组件方法。

父组件渲染页面时,执行到子组件占位符时就会渲染子组件,不论子组件是否显示在页面上。但是此时props传递的数据还没传递给子组件。

this.$nextTick(() => { }) 是vue提供的方法,他会等待DOM元素更新之后再去执行后面的操作。

vue中数据和dom渲染是异步的(数据驱动视图是异步的),所以,要让dom结构随数据改变这样的操作,都应该放进 this.$nextTick() 的回调函数中。

created()中使用方法时,dom还没有渲染,如果此时在该钩子函数中进行dom赋值数据(或者其它dom操作),无异于徒劳,所以,此时this.$nextTick()就会被大量使用,而与created()对应的是mounted()的钩子函数则是在dom完全渲染后才开始渲染数据,所以在mounted()中操作dom基本不会存在渲染问题。

2. 组件之间传递的值的类型

① 字符串、数字型、布尔型、数组、对象。
② 子组件被调用时,父组件传递的 数字型布尔型的值,如果没有绑定 v-bind,则传递的是 字符串 类型。

   
3. 子组件向父组件传值 (自定义事件)

Vue.component('child', {
   template:
    "


      
    
",
});
调用子组件:

① 子组件的 props 属性使用原则:单向数据流。即在子组件中修改数据不会同步到父组件,而子组件的数据来自父组件,父组件的数据一旦发生变化,子组件的数据就白修改了。

② 具体来说:不要在子组件内修改数字型、布尔型、字符串数据,不能对数组、对象重新赋值,但是可以修改数组和对象的元素与属性。

③ 父组件在调用子组件时,给子组件注册 自定义事件,并在methods中声明事件的处理函数。

④ 在子组件的 template 模板中,用 this.$emit 触发自定义事件。(可以直接在template模板中绑定,也可以在methods中绑定。)事件的第一个参数是 事件名称,第二个参数是 想要传递的值

⑤ 如果传递多个值,可以用 对象 的形式。并且可以传递 事件对象$event

⑥ 父组件通过 $event 获取到子组件传递的值。

     
{{msg}}
4. 子组件对父组件的数据 【使用并修改】

如果子组件既要使用父组件中的数据,又要修改父组件的数据。

(1) 传统做法:

① 父组件调用子组件时,用v-bind绑定数据进行传递;子组件在props属性中接收。
② 子组件修改数据时,用$emit绑定方法;父组件监听此方法,并在事件函数中修改数据。

(2) 新方法:v-model(vue3.0有变化!!!)

① 父组件调用子组件时,用 v-model 绑定数据进行传递;子组件在props属性中接收。


② 子组件接收数据时,数据名称固定为 value
③ 子组件修改数据时,用$emit触发自定义事件,事件名称固定为 input父组件无需注册和声明此事件
④ 如果子组件想要修改数据名称和事件名称,则在组件内添加 model属性

model: {
    prop: 'data', //默认名称为value
    event: 'changeData'  //默认名称为input
  },
props:[ 'data' ],
methods:{
   handler( ){ this.$emit('changeData',newData)}
}

注意:v-model绑定数据只能用一次。

(3)新方法:.sync(vue3.0已删除!!!)

① 父组件传递数据时,在数据名称后面添加 .sync修饰符


② 此时,子组件就可以按照下面的格式修改这个数据,而父组件不用注册$emit的事件。

this.$emit('update:dialogVisible', false)

update: 是固定写法,参数false是修改的值。

(4)子组件中 this.$parent 可以获取到父组件的实例对象。
(5)vue3.0 v-model

父组件调用子组件时,用 v-model 绑定数据,子组件用 prop接收数据,
this.$emit("update:数据名",最新值) 进行修改。

5.父组件向后代子组件传值

通过 依赖注入 ,父组件声明数据,后代子组件接收数据并使用。当某个父组件的数据被多个子组件使用时使用这种方法。

① 父组件声明数据:

provide: function () {
    return {
      articleID: this.articleID
    }
  },

② 后代子组件接收数据

inject: {
    articleID: {
      type: [Number, String, Object],
      default: null
    }
  }
6. 兄弟组件传值(了解)

① 定义一个 事件中心

var hub = new Vue()

② 在接收数据的组件内,添加 mounted钩子函数 ,在mounted函数内书写 监听事件的函数。监听的事件处理的是本组件的数据
注意: 这里使用箭头函数是因为 this 指向的问题。

mounted: function() {
  hub.$on( '自定义事件名', (形参) => { });
}

③ 在传递数据的组件内,为HTML标签绑定事件 hub.$emit( '自定义事件名',传递的数据)。触发的是兄弟组件的事件。

handle: function(){
  hub.$emit( '自定义事件名',实参)
}

④ 在父组件内,给html元素绑定事件,通过 hub.$off( "自定义事件名") 销毁事件。


handle: function () {
   hub.$off('自定义事件名');
}

四、组件插槽

1. 组件插槽基本用法

通过组件插槽,可以在调用子组件时,向标签内填写内容。

① 在子组件的 template 模板中添加一个固定的标签 作为插槽。
② 在父组件中调用子组件时,可以向标签内填写内容,标签中的内容被传递到子组件插槽中,显示到页面。
③ 在父组件中调用子组件时,如果向标签内添加内容,则标签内的默认内容会被覆盖。

你好!
2.具名插槽 (重点)

具名插槽的两种使用情况:
(1)在项目中,想要给组件库中的组件,添加一些 自定义内容,组件本身会提供相应的 具名插槽 ,我们只需要使用插槽填充内容即可。
(2)对于自己写的组件,我们需要在子组件预留插槽位置,然后父组件调用时给插槽填充内容。

① 在子组件的 template 模板中,可以给 插槽标签 添加名字。

② 在父组件中调用子组件时,可以在标签内部 添加任意标签,并给这些标签添加slot名字后,标签内的内容就会被传递给子组件对应的具名插槽。


 

传递的内容


③ 如果想给一个具名插槽添加 多个标签的内容 的话,使用