【初学vue3笔记】

本文详细介绍了Vue3中的几个重要新特性,包括Teleport的使用,解决了模态框定位问题;片段支持,允许组件有多个根节点;事件处理的改变,强调kebab-case事件名的使用;以及如何处理v-model修饰符。此外,还提到了<style scoped>中对全局规则和插槽内容样式的控制。
摘要由CSDN通过智能技术生成

【初学vue3笔记】

值得注意的新特性

1. Teleport

Teleport 是什么?它解决的是什么问题?用法?

Teleport 是一种能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术

应用场景:一个常见的场景是创建一个包含全屏模式的组件。在大多数情况下,你希望模态框的逻辑存在于组件中,但是模态框的定位很快就很难通过 CSS 来解决,或者需要更改组件组合。

类似这种结构

<body>
  <div style="position: relative;">
    <h3>Tooltips with Vue 3 Teleport</h3>
    <div>
      <modal-button></modal-button>
    </div>
  </div>
</body>

const app = Vue.createApp({});


//modal-button 组件:
app.component('modal-button', {
  template: `
    <button @click="modalOpen = true">
        Open full screen modal!
    </button>

    <div v-if="modalOpen" class="modal">
      <div>
        I'm a modal! 
        <button @click="modalOpen = false">
          Close
        </button>
      </div>
    </div>
  `,
  data() {
    return { 
      modalOpen: false
    }
  }
})

该组件将有一个 button 元素来触发模态框的打开,以及一个具有类 .modal 的 div 元素,它将包含模态的内容和一个用于自关闭的按钮。
模态框是在深度嵌套的 div 中渲染的,而模态框的 position:absolute 以父级相对定位的 div 作为引用。
而Teleport 提供了一种干净的方法,允许我们控制在 DOM 中哪个父节点下呈现 HTML
使用如下

app.component('modal-button', {
  template: `
    <button @click="modalOpen = true">
        Open full screen modal! (With teleport!)
    </button>

    <teleport to="body">
      <div v-if="modalOpen" class="modal">
        <div>
          I'm a teleported modal! 
          (My parent is "body")
          <button @click="modalOpen = false">
            Close
          </button>
        </div>
      </div>
    </teleport>
  `,
  data() {
    return { 
      modalOpen: false
    }
  }
})

参数使用
to - string 必须是有效的查询选择器或 HTMLElement

<!-- 正确 -->
<teleport to="#some-id" />
<teleport to=".some-class" />
<teleport to="[data-teleport]" />

<!-- 错误 -->
<teleport to="h1" />
<teleport to="some-string" />

disabled - boolean 此可选属性可用于禁用 teleport 的功能,这意味着其插槽内容将不会移动到任何位置,而是在您在周围父组件中指定了 teleport 的位置渲染。

<teleport to="#popup" :disabled="displayVideoInline">
  <video src="./my-movie.mp4">
</teleport>

2. 片段

在 2.x 中,不支持多根组件,当用户意外创建多根组件时会发出警告,因此,为了修复此错误,许多组件被包装在一个 div 中。

<!-- Layout.vue -->
<template>
  <div>
    <header>...</header>
    <main>...</main>
    <footer>...</footer>
  </div>
</template>

在 3.x 中,组件现在可以有多个根节点!但是,这确实要求开发者明确定义属性应该分布在哪里。

<!-- Layout.vue -->
<template>
  <header>...</header>
  <main v-bind="$attrs">...</main>
  <footer>...</footer>
</template>

3. 触发组件选项

不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称。
举个例子,如果触发一个 camelCase(驼峰式) 命名的事件:

this.$emit('myEvent')

则监听这个名字的 kebab-case(短横线命名) 版本是不会有任何效果的:

<!-- 没有效果 -->
<my-component @my-event="doSomething"></my-component>

不同于组件和 prop,事件名不会被用作一个 JavaScript 变量名或 property 名,所以就没有理由使用 camelCase(驼峰式) 或 PascalCase(帕斯卡命名法) 了。
并且 v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 @myEvent 将会变成 @myevent——导致 myEvent 不可能被监听到。
因此,推荐始终使用 kebab-case(短横线命名) 的事件名

自定义事件
可以通过 emits 选项在组件上定义已发出的事件。

app.component('custom-form', {
  emits: {
    // 没有验证
    click: null,

    // 验证submit 事件
    submit: ({ email, password }) => {
      if (email && password) {
        return true
      } else {
        console.warn('Invalid submit event payload!')
        return false
      }
    }
  },
  methods: {
    submitForm() {
      this.$emit('submit', { email, password })
    }
  }
})

v-model 参数
通过利用以特定 prop 和事件为目标的能力,正如我们之前在 v-model 参数中所学的那样,我们现在可以在单个组件实例上创建多个 v-model 绑定。

<user-name
  v-model:first-name="firstName"
  v-model:last-name="lastName"
></user-name>

const app = Vue.createApp({})

app.component('user-name', {
  props: {
    firstName: String,
    lastName: String
  },
  template: `
    <input 
      type="text"
      :value="firstName"
      @input="$emit('update:firstName', $event.target.value)">

    <input
      type="text"
      :value="lastName"
      @input="$emit('update:lastName', $event.target.value)">
  `
})

处理 v-model 修饰符
在 2.x 中,我们对组件 v-model 上的 .trim 等修饰符提供了硬编码支持。但是,如果组件可以支持自定义修饰符,则会更有用。
在 3.x 中,添加到组件 v-model 的修饰符将通过 modelModifiers prop 提供给组件:

当我们学习表单输入绑定时,我们看到 v-model 有内置修饰符——.trim、.number 和 .lazy。但是,在某些情况下,你可能还需要添加自己的自定义修饰符。

让我们创建一个示例自定义修饰符 capitalize,它将 v-model 绑定提供的字符串的第一个字母大写。

在下面的示例中,我们创建了一个组件,其中包含默认为空对象的 modelModifiers prop。

请注意,当组件的 created 生命周期钩子触发时,modelModifiers prop 包含 capitalize,其值为 true——因为它被设置在 v-model 绑定 v-model.capitalize=“bar”。

<my-component v-model.capitalize="bar"></my-component>


app.component('my-component', {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  template: `
    <input type="text" 
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)">
  `,
  created() {
    console.log(this.modelModifiers) // { capitalize: true }
  }
})

现在我们已经设置了 prop,我们可以检查 modelModifiers 对象键并编写一个处理器来更改发出的值。在下面的代码中,每当 input 元素触发 input 事件时,我们都将字符串大写。

<div id="app">
  <my-component v-model.capitalize="myText"></my-component>
  {{ myText }}
</div>

const app = Vue.createApp({
  data() {
    return {
      myText: ''
    }
  }
})

app.component('my-component', {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  methods: {
    emitValue(e) {
      let value = e.target.value
      if (this.modelModifiers.capitalize) {
        value = value.charAt(0).toUpperCase() + value.slice(1)
      }
      this.$emit('update:modelValue', value)
    }
  },
  template: `<input
    type="text"
    :value="modelValue"
    @input="emitValue">`
})

app.mount('#app')

4.单文件组件 <style scoped> 现在可以包含全局规则或只针对插槽内容的规则
示例

< style  scoped > 
/* 深度选择器 */ 
:: v-deep (. foo ) {}
 /* 简写 */ 
: deep (. foo ) {}

/* 定位槽内容 */ 
:: v-slotted (. foo ) {}
 /* 简写 */ 
: slotted (. foo ) {}

/* 一次性全局规则 */ 
:: v-global (. foo ) {}
 /* 简写 */ 
: global (. foo ) {}
 </ style >
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值