Vue学习笔记04

66 阅读2分钟

组件进阶

v-model 原理

语法糖:v-model本质上是 value属性和input事件的一层包装 v-model的作用:

  1. 提供数据的双向绑定数据发生了改变,页面会自动变 v-bind:value
  2. 页面输入改变 ,数据会自动变化 v-on:input

v-model给组件使用

v-model相当于给父组件添加了:value=""和@input=""

<template>
  <div>
    <add-table v-model="num"></add-table>
    <!-- 相当于做了以下步骤 -->
    <!-- <add-table :value="num" @input="input"></add-table> -->
    <h2>父组件的num:{{ num }}</h2>
  </div>
</template>

<script>
import addTable from "./components/add-table.vue";
export default {
  components: {
    "add-table": addTable,
  },
  data() {
    return {
      num: 100,
    };
  },
  // 不用再给methods写input事件,v-model自动把传过来的值赋给value
};
</script>

<style>
</style>

子组件中props的"value"和$emit中的"input"是固定单词,不能修改

<template>
  <div>
    <h2>子组件的num:{{ value }}</h2>
    <button @click="fn">改为300</button>
  </div>
</template>

<script>
export default {
  props: ["value"],   // value是固定的写法
  methods: {
    fn() {
      this.$emit("input", 300);     // input是固定的写法
    },
  },
};
</script>

<style>
</style>

ref 和 $refs

作用:利用 ref 和 $refs 可以用于 获取 dom 元素,或者组件实例 步骤:

  1. 给目标标签添加ref属性,ref="任意名字aaa"
  2. 通过 this.$refs.aaa,获取组件内容
    1. 通过this.$refs.aaa.属性/方法,可以调用组件里的属性/方法
<template>
  <div>
    <input type="text" ref="inputA" />
    <button @click="fn">获取</button>
  </div>
</template>

<script>
export default {
  methods: {
    fn() {
      // 调用方法
      this.$refs.inputA.focus();
    },
  },
};
</script>

$nextTick

问题:当数据发生改变时,由于Vue更新DOM是异步的,无法即是获取更新后的DOM内容 解决方案:nextTick,等DOM更新完毕再执行语法:在对应函数中,在数据更新的代码之后写this.nextTick,等DOM更新完毕再执行 语法:在对应函数中,在数据更新的代码之后写this.nextTick(callback)

<template>
  <div>
    <input type="text" ref="inputA" v-show="showInput" />
    <button @click="fn">获取</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      showInput: false,
    };
  },
  methods: {
    fn() {
      this.showInput = true;
      // 如果没有$nextTick,此时vue识别到的v-show还是false的状态
      this.$nextTick(() => {
        console.log(this.$refs.inputA);
      });
    },
  },
};
</script>

同一个组件多次调用,数据不会相互影响

<template>
  <div>
    <Subject-table ref="count"></Subject-table>
    <Subject-table ref="count2"></Subject-table>
    <Subject-table ref="count3"></Subject-table>
    <button @click="fn">123</button>
  </div>
</template>

<script>
import subjectTable from './components/subject-table.vue'
export default {
  components: {
    "Subject-table":subjectTable
  },
  methods: {
    fn() {
      console.log(this.$refs.count.num);		// 当其中某一个数据改变时,其他的数据不会跟着变化
      console.log(this.$refs.count2.num);
      console.log(this.$refs.count3.num);
    }
  }
}
</script>

<style>

</style>

动态组件

定义:可以改变的组件 使用场景:多组件同一位置, 切换显示的需求 基本语法:

  1. <component + :is=" (哪个组件)">
  2. 修改 is 属性绑定的值 => 切换组件

props校验

作用:提高 子组件被使用时 的稳定性,防止props传值类型等传错

props: {参数名:类型,},
// 类型错误能允许,但是报错

插槽

使用场景:要在页面中显示一个对话框, 封装成一个组件

基本语法

  1. 子组件内用占位
  2. 使用时,给子组件标签内容传入标签替换slot
<!-- 子组件 -->
<template>
  <div>
      <h1>友情提醒</h1>
      <slot></slot>
      <button>关闭</button>
  </div>
</template>

<!-- 父组件 -->
<template>
  <div>
    <tang-chuang>
      <h3>请输入正确的技师号码</h3>
      <h3>请输入正确的技师号码</h3>
    </tang-chuang>
  </div>
</template>

具名插槽

使用场景:需要传多个插槽 步骤

  1. 子组件中的slot添加一个name属性,slot的可以添加默认内容,如果父组件没有传则显示默认内容
  2. 父组件中在子组件标签内容写<template v-slot:任意名>插入的内容
    1. 其中v-slot:任意名 可以简写为#任意名
<!-- 子组件 -->
<template>
  <div>
    <!-- 插槽内的是默认内容,不传则会显示 -->
    <slot name="title"><h1>友情提示</h1></slot>
    <slot name="body"></slot>
    <slot name="footer"></slot>
  </div>
</template>

<!-- 父组件 -->
<template>
  <div>
    <tang-chuang>
      <template v-slot:title>
        <h1>标题</h1>
      </template>
      <!-- 可以简写 -->
      <template #body>
        <h1>内容</h1>
      </template>
      <template #footer>
        <button>关闭</button>
      </template>
      </tang-chuang>
  </div>
</template>

作用域插槽

定义:定义 slot 插槽的同时, 是可以传值的。给插槽上可以绑定数据,将来使用组件时可以用。 使用场景: 步骤

  1. 把弹窗组件的标题用一个变量存储

    1. 如:dialogTitle: "友情提示"
  2. 在弹窗组件内部,给插槽传参数

    1. 如:
    2. 会得到obj = { dialogTitle: "友情提示" }
  3. 在父组件,在对应插槽接受传过来的参数

    1. 如:<template #title="obj">
  4. 在父组件插槽内,使用参数

    1. {{ obj.title }}

<template>
  <div>
    <!-- 2.传参 -->
    <slot name="title" :title="dialogTitle">
      <h1>默认提示</h1>
    </slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 1.存值
      dialogTitle: "友情提示",
    };
  },
};
</script>
<template>
  <div>
    <tang-chuang>
      <!-- 3.用一个obj接收 -->
      <template #title="obj">
        <!-- 4.使用 -->
        <h1 :style="{ color: 'red' }">{{ obj.title }}</h1>
      </template>
    </tang-chuang>
  </div>
</template>

<script>
import tangchuang from "./components/tang-chuang.vue";
export default {
  components: {
    "tang-chuang": tangchuang,
  },
};
</script>
</style>