vue组件总结

192 阅读5分钟
  • 组件: 可复用的vue实例、分装标签、样式和js代码
  • 组件化开发: 一个页面可能有一个或多个组件组成的完整的页面功能
    • 每个组件可以有自己独立的结构(template,style,script)

封装使用

sequenceDiagram
Alice->>John: Hello John, how are you?
John-->>Alice: Great!
Alice-)John: See you later!

image.png 1.定义组件

定义一个名为MyCom的组件,并在App.vue中使用它

目录
├── App.vue  # 在App.vue内部,导入并使用组件
└── MyCom.vue

2.注册组件

App.vue

// 局部注册组件

// 进入到当前组件内部
// 1. 导入组件
import 组件名 from './组件文件.vue'

// 2. 局部注册
export default {
   components: {
     组件名: 组件名
   }
}

3.使用组件

在当前页面中,当做标签来使用。

用scoped实现组件的私有样式

解决多个组件样式名相同, 冲突问题

默认组件style 中定义的样式是全局,存在相同名字覆盖的情况

解决方案

局部样式:在style标签上加上scoped属性

<stype scoped>
  h2 {} // 样式只会在当前组件内生效
</style>

/deep/深度作用选择符

当父子组件都使用了scoped的情况下,在父组件中控制子组件的样式

解决方案

父组件的选择器 /deep/ .子组件的选择器

.box /deep/ h2 {
   color: red;
 }

组件通信-父传子

image.png

image.png

单项数据流

  1. 在父传子的前提下,父组件的数据发生会通知子组件自动更新
  2. 子组件内部,不能直接修改父组件传递过来的props => props是只读的

PS: 父组件传给子组件的是一个对象,子组件修改对象的属性,是不会报错的,对象是引用类型, 互相更新;但不能改变引用地址

props的值不能重新赋值, 但是引用类型可以子改父

组件通信_子传父

image.png

image.png

vue组件生命周期

一个组件从 创建 到 销毁 的整个过程就是生命周期

生命周期函数(钩子函数):

vue 框架内置函数,随着组件的生命周期,自动 按次序 执行

四个阶段:

  • 初始化 => 创建组件   => beforeCreate | created
  • 挂载 => 渲染显示组件 =>  beforeMount | mouted
  • 更新 => 修改了变量 => 触发视图刷新 => beforeUpdate | updated
  • 销毁 => 切换页面 => 会把组件对象从内存删除 => beforeDestroy | destroyed

image.png

<template>
  <div>
    <ul id="myUl">
      <li v-for="(item, ind) in arr" :key="ind">{{ item }}</li>
    </ul>
    <button
      @click="arr.push(Math.random() * 10)"
    >
      增加一个元素
    </button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      msg: "我是变量",
      arr: [1, 2, 3, 4]
    }
  },
  beforeCreate () {
    // 1. 创建前
    console.log("beforeCreate --- 实例初始化前")
    console.log(this.msg) // undefined
  },
  created () { //发ajax 可以访问data中定义的数据
    // 2. 创建后=> 发送ajax请求
    console.log("created ---  实例初始化后")
    console.log(this.msg) // "我是变量"
    
    // 给对象添加属性
    this.timer = setInterval(()=>{
      console.log(Date.now())
    }, 1000)
    this.fn = ()=>{ console.log(Date.now())}
    document.addEventListener('mousemove', this.fn)
  },
  beforeMount () {
    // 3. 挂载前
    console.log("beforeMount --- vue的虚拟DOM, 挂载到真实的网页之前")
    console.log(document.getElementById("myUl")) // null
    // console.log(document.getElementById("myUl").children[1].innerHTML) // 报错
  },
  mounted () {  //可以访问dom元素
    // 4. 挂载后=> 操作dom
    console.log("mounted --- vue的虚拟DOM, 挂载到真实的网页上 ")
    // console.log(document.getElementById("myUl").children[1].innerHTML)
    console.log(document.querySelector('#myUl').children[1].innerText)
  },
  beforeUpdate () {
    // 5. 更新前
    console.log("beforeUpdate --- 数据更新, 页面更新前")
    // 比如点击新增数组元素, vue会触发此生命周期函数, 但是此时页面并未更新, 所以获取不到新增的li标签
    // console.log(document.getElementById("myUl").children[4].innerHTML) // 报错
  },
  updated () {
    // 6. 更新后
    console.log("updated --- 数据更新, 页面更新后")
    console.log(document.getElementById("myUl").children[4].innerHTML)
  },
  beforeDestroy () {
    // 7. 销毁前
     // (清除定时器 / 解绑js定义的事件)
    console.log("beforeDestroy --- 实例销毁之前调用")
  },
  destroyed () {  //清除定时器 取消事件绑定
    // document.removeEventListener('mousemove', 回调函数的名字)
    document.removeEventListener('mousemove', this.fn)
    // clearInterval(this.timer)
    // 8. 销毁后
    // (清除定时器 / 解绑js定义的事件)
    console.log("destroyed --- 销毁完成")
  }
};
</script>

axios基本使用

// 1. 导入axios
import axios from 'axios'
// 2. 使用1
axios({
  method: '请求方式', // get post
  url: '请求地址',
  data: {    // 拼接到请求体的参数,  post请求的参数
    xxx: xxx,
  },
  params: {  // 拼接到请求url的参数, get请求的参数
   	xxx: xxx 
  }
}).then(res => {
  console.log(res.data) // 后台返回的结果
}).catch(err => {
  console.log(err) // 后台报错返回
})


// 2. 使用2 async await
function async fn(){
  try {
    const res = await axios.get('地址')
    
  } catch (err) {
    console.log('err', err)
  }
}

$refs使用

可以用来获取dom或组件实例对象

数据变化而导致的dom更新是异步的

<template>
  <div>
    <h1 ref="myH1">ref获取原生dom</h1>
    <button @click="fn">点击修改上面内容</button>
  </div>
</template>

<script>
export default {
  methods: {
    fn() {
      console.log(this.$refs.myH1); // <h1></h1> 原生DOM标签
      this.$refs.myH1.innerHTML = "改内容了";
    }
  }
}
</script>

nextTick使用

dom是异步更新的, $nextTick可以等待dom更新后触发此方法

image.png

props校验

普通格式:

props: ["propA", "propB"]。没有类型检查

高阶格式:

-   props:{  
            属性名: { type: 类型 
            required:  
            default: '' || ()=> [] 
            validator: val =>{}}
        }

props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }

动态组件

多个组件使用同一个挂载点,并可以动态切换,这就是动态组件

格式

<component :is="变量名"></component>

  • is只能是动态属性, :is="组件注册后的标签名 字符串或data变量"
  • 不能直接拿注册标签名赋值使用
  • vue内置component组件,配合is属性,设置要显示的组件标签名字

keep-alive

使用内置的keep-alive组件,可以让包裹的组件保存在内存中不被销毁

<keep-alive>
    <!-- vue内置的组件component, 可以动态显示组件 -->
    <component :is="comName"></component>
</keep-alive>
  • keep-alive可以提高组件的性能,内部包裹的标签不会被销毁和重新创建、触发激活和非激活的生命周期方法
  • 他会让被缓存的组件多出两个钩子
    • activated 激活
    • deactivated 失去激活

指定缓存

语法

  1. include="组件名1,组件名2..."
  2. include="['组件名1', '组件名2']"

默认插槽

  1. 组件通过插槽传入自定义结构
  2. 用于实现组件内容的分发,通过slot标签,可以接收写在组件标签内内容
  3. vue提供组件插槽能力,允许开发者在封装组件时,把不确定的部分定义为插槽

格式

在定义组件时,在template中用slot来占个坑

使用时,将组件之间的内容来填坑 image.png

具名插槽

1.  slot有可以设置多个
2.  定义组件时:slot的name属性起插槽名
3  使用组件时, template配合#插槽名传入具体html标签或组件

定义: <slot name="xxx">

使用:

-   <template #xxx></template>;
-   <template v-slot:xxx></template>

image.png

  • 传入的标签可以分别派发给不同的slot位置

  • v-slot一般跟template标签使用 (template是html5新出标签内容模板元素, 不会渲染到页面上, 一般被vue解析为内部标签)

  • v-bind可以省略成 :    

  • v-on: 可以省略成 @  

  • v-slot: 可以简化成 #

插槽作用域

  1. 创建子组件, 准备slot, 在slot上绑定属性和子组件值
  2. 使用子组件, 传入自定义标签, 用template和v-slot="自定义变量名"
  3. 自定义变量名会自动绑定slot上所有属性, 就可以使用子组件内值, 并替换slot位置

image.png

自定义指令

扩展标签额外的功能

v-xxx, 自定义指令, 获取原生DOM, 自定义操作

<template>
  <div>
    <input type="text" v-focus />
  </div>
</template>

<script>
export default {
  // 注册
  directives: {
    focus: { // 自定义指令名
        inserted(el,binding){ // 固定配置项 - 当指令插入到标签自动触发此函数
            el.focus()
        }
    }
  }
}
</script>

传值和更新


directives:{
 "color":{
    inserted(el,binding){  // 插入时触发此函数,v-color="theColor",theColor会自动保存在binding.value中
      el.style.color = binding.value
    },
    updata(el,binding){  // 更新绑定的变量时触发此函数
      el.style.color = binding.value 
    }
  }
}
 <p v-color = "theColor" @click = "changeColor">使用v-color指令控制颜色,点击变色</p>
 
 <script>
   data(){
    return {
     theColor:"red"
    }
   },
   methods:{
    changeColor() {
     this.theColor = "blue"
    }
   }
 </script>