VUE3 学习日记(三)

一、组件注册

组件注册分全局注册和局部注册  一个可以在全局都可以用的  一个是只能在局部用的

全局注册:使用app.component() 方法   我们可以在main.js的文件中  用app实例去注册组件 这样我们就可以在全局单文件里面使用这个组件 

缺点:全局注册在大型项目中使项目的依赖关系变得不那么明确。在父组件中使用子组件时,不太容易定位子组件的实现。和使用过多的全局变量一样,这可能会影响应用长期的可维护性

import MyComponent from './App.vue'

app.component('MyComponent', MyComponent)
也可以链式调用
app
  .component('ComponentA', ComponentA)
  .component('ComponentB', ComponentB)
  .component('ComponentC', ComponentC)

局部注册:局部注册的组件需要在使用它的父组件中显式引入  并且只能在该父组件中使用  并且这个方式 对tree-shaking更加友好

在使用 <script setup> 的单文件组件中,导入的组件可以直接在模板中使用,无需注册:
<script setup>
import ComponentA from './ComponentA.vue'
</script>

<template>
  <ComponentA />
</template>

组件名格式:

  1. PascalCase 是合法的 JavaScript 标识符。这使得在 JavaScript 中导入和注册组件都很容易,同时 IDE 也能提供较好的自动补全。

  2. <PascalCase /> 在模板中更明显地表明了这是一个 Vue 组件,而不是原生 HTML 元素。同时也能够将 Vue 组件和自定义元素 (web components) 区分开来。

二、Props

2.1 props声明

在使用 <script setup> 的单文件组件中,props 可以使用 defineProps() 宏来声明:

<script setup>
const props = defineProps(['foo'])

console.log(props.foo)
</script>

在没有使用 <script setup> 的组件中,prop 可以使用 props 选项来声明:

export default {
  props: ['foo'],
  setup(props) {
    // setup() 接收 props 作为第一个参数
    console.log(props.foo)
  }
}

除了使用字符串数组来声明 prop 外,还可以使用对象的形式:

// 使用 <script setup>
defineProps({
  title: String,
  likes: Number
})

// 非 <script setup>
export default {
  props: {
    title: String,
    likes: Number
  }
}

2.2 传递prop的细节

名字格式:声明的时候最好是用驼峰式  camelCase 形式 在模板上使用是用 kebab-case 形式

静态和动态prop  动态多了一个 v-bind 或者缩写 :

传递的值类型:number boolean array  object

可以使用一个对象绑定一个prop   这里只能用一个v-bind 如:

const post = {
  id: 1,
  title: 'My Journey with Vue'
}

<BlogPost v-bind="post" />

<BlogPost :id="post.id" :title="post.title" />

2.3 单向数据流

所所谓的单向数据流  就是不能回流去修改数据  所有的props都遵循着单向绑定原则  props因为父组件的更新而变化。比如 每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,这意味着你不应该在子组件中去更改一个 prop。

如果想要想通过子组件去修改props的话  只能通过子组件抛出一个事件去修改(后面会讲到)

2.4 prop校验  

 要声明对props的校验 你可以向defineProps() 宏提供一个带有props校验选项的对象  例如:

defineProps({
  // 基础类型检查
  // (给出 `null` 和 `undefined` 值则会跳过任何类型检查)
  propA: Number,
  // 多种可能的类型
  propB: [String, Number],
  // 必传,且为 String 类型
  propC: {
    type: String,
    required: true
  },
  // Number 类型的默认值
  propD: {
    type: Number,
    default: 100
  },
  // 对象类型的默认值
  propE: {
    type: Object,
    // 对象或数组的默认值
    // 必须从一个工厂函数返回。
    // 该函数接收组件所接收到的原始 prop 作为参数。
    default(rawProps) {
      return { message: 'hello' }
    }
  },
  // 自定义类型校验函数
  propF: {
    validator(value) {
      // The value must match one of these strings
      return ['success', 'warning', 'danger'].includes(value)
    }
  },
  // 函数类型的默认值
  propG: {
    type: Function,
    // 不像对象或数组的默认,这不是一个
    // 工厂函数。这会是一个用来作为默认值的函数
    default() {
      return 'Default function'
    }
  }
})

细节:所有的prop的默认都是可选的 除非声明了requried:true

除 Boolean 外的未传递的可选 prop 将会有一个默认值 undefined

三、事件

3.1 触发与监听事件

在组件的模板中  可以直接使用 $emit  方法去触发自定义事件   然后用v-on(缩写为@)来监听事件,事件名可以用camelCase 形式命名的事件 但在父组件中可以使用 kebab-case 形式来监听 模板中我们也推荐使用 kebab-case 形式来编写监听器。

<!-- MyComponent -->
<button @click="$emit('someEvent')">click me</button>

//父组件
<MyComponent @some-event="callback" />
//或
<MyComponent @some-event.once="callback" />

3.2 事件参数

我们可以给$emit 提供一个额外的参数 :$emit('increaseBy', 1)   父组件在方法接收

3.3 声明触发事件

可以使用defineEmits()宏来声明它要触发的事件,$emit 方法不能在组件的 <script setup> 部分中使用  但是这个宏会返回一个相同作用的函数来使用    defineEmits() 宏不能在子函数中使用  它必须直接放置在 <script setup> 的顶级作用域下。

<script setup>
const emit = defineEmits(['inFocus', 'submit'])

function buttonClick() {
  emit('submit')
 emit('inFocus')
}
</script>

3.4 事件校验

要给事件添加校验 那么事件可以被赋值为一个函数 接收的参数就是报出事件时传入emit的内容 返回一个布尔值来表明事件是否合法。

<script setup>
const emit = defineEmits({
  // 没有校验
  click: null,

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

function submitForm(email, password) {
  emit('submit', { email, password })
}
</script>

四、v-model

4.1 用法 

当我们需要在父组件和子组件实现一个数据的双向绑定  则需要v-model   具体用法:

<!-- CustomInput.vue -->
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>

<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

//使用
<CustomInput v-model="searchText" />

4.2 v-model的参数

默认情况下 没有命名的时候  v-model在组件上都是使用modelValue 作为prop  并以update:modelVlaue 作为对应事件。我们可以通过给v-model指定一个参数来更改这些名字:

<MyComponent v-model:title="bookTitle" />
//在这个例子中,子组件应声明一个 title prop,
//并通过触发 update:title 事件更新父组件值:

<!-- MyComponent.vue -->
<script setup>
defineProps(['title'])
defineEmits(['update:title'])
</script>

<template>
  <input
    type="text"
    :value="title"
    @input="$emit('update:title', $event.target.value)"
  />
</template>

4.3 v-model 修饰符

在我们想自定义组件的v-model支持自定义的修饰符  比如  自定义个一个 capitalize,  它会自动将v-model绑定输入的字符串值第一个字母转为大写:

<MyComponent v-model.capitalize="myText" />

我们可以通过一个 modelModifiers prop在组件内访问到 有了这个prop  我们就可以编写一个处理函数来改变抛出的值  下面是实现方法:

<script setup>
const props = defineProps({
  modelValue: String,
  modelModifiers: { default: () => ({}) }
})

const emit = defineEmits(['update:modelValue'])

function emitValue(e) {
  let value = e.target.value
  if (props.modelModifiers.capitalize) {
    value = value.charAt(0).toUpperCase() + value.slice(1)
  }
  emit('update:modelValue', value)
}
</script>

<template>
  <input type="text" :value="modelValue" @input="emitValue" />
</template>

对于又有参数又有修饰符的 v-model 绑定 生成的prop 是 arg + "Modifiers"  比如:

<MyComponent v-model:title.capitalize="myText">

声明
const props = defineProps(['title', 'titleModifiers'])
defineEmits(['update:title'])

console.log(props.titleModifiers) // { capitalize: true }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值