IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue3笔记 -> 正文阅读

[JavaScript知识库]vue3笔记

一、声明式渲染

声明式渲染
模板语法:就是在vue单文件里面写代码,然后通过声明式的方式将数据绑定到dom。然后被编译成js。经过优化后减少dom操作。
文本插值:{{}},
vue单文件组件:SFC,一种可复用代码组织形式。
声明式渲染:通过改变状态,触发html的更新渲染。
响应式状态:声明方式(reactive只适用于对象、数组,ref适合任何对象)

// reactive处理对象
const counter = reactive({
  count: 0
})
console.log(counter.count) // 0
// reactive处理数组
const a =reactive(['1', '2'])
a.push('1')
// ref处理字符串
const message = ref('Hello World!')
console.log(message.value) // "Hello World!"
1. 在 Vue 中,状态都是默认深层响应式的。这意味着即使在更改深层次的对象或数组,你的改动也能被检测到。
2. reactive 返回的是一个原始对象的 Proxy
3. reactive 响应式对象的属性赋值或解构,会失去响应性
4. reactive 不可以随意地“替换”一个响应式对象
5. ref 将传入参数的值包装为一个带 .value 属性的 ref 对象
6. ref 可以响应式地替换整个对象
7. ref 是模板渲染上下文的顶层属性时才适用自动“解包”
8. Vue 能够侦听响应式数组的变更方法,并在它们被调用时触发相关的更新push、pop、shift、unshift、splice、sort、reverse

二、Attribute 绑定

v-bind

<div v-bind:id="dynamicId"></div>
<div :id="dynamicId"></div>
<h1 :class="title">Make me red</h1> 
1. 绑定多个参数
const objectOfAttrs = {
  id: 'container',
  class: 'wrapper'
}
<div v-bind="objectOfAttrs"></div>
2. 使用 JavaScript 表达式
<div :id="`list-${id}`"></div>
3. 调用函数
{{ formatDate(date) }}
4. 动态参数
<a v-bind:[attributeName]="url"> ... </a>
5. 修饰
事件修饰符:.stop阻止冒泡,.prevent阻止默认事件,.self只触发它自己,.capture,.once,.passive
<form @submit.prevent="onSubmit">...</form>
v-model修饰符
.lazy 每次change事件后更新数据。
.number 自动转为数字。
.trim 去除前后空格。
6. class与style绑定
<div :class="{ active: isActive }"></div>
<div :class="[isActive ? activeClass : '', errorClass]"></div>
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
7. 透传 attribute 传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器, 禁用 Attributes 继承 inheritAttrs: false
<script>
// 使用普通的 <script> 来声明选项
export default {
  inheritAttrs: false
}
</script>

<script setup>
// ...setup 部分逻辑
</script>
8. 应用在内部的 <button> 上而不是外层的 <div> 上 v-bind="$attrs"
<div class="btn-wrapper">
  <button class="btn" v-bind="$attrs">click me</button>
</div>

事件监听

v-on

<button v-on:click="increment">{{ count }}</button>
<button @click="increment">{{ count }}</button>
1. 监听对象:ref、reactive对象、getter函数或多个数据源组成的数组。
const x = ref(0)
const y = ref(0)

// 单个 ref
watch(x, (newX) => {
  console.log(`x is ${newX}`)
})

// getter 函数
watch(
  () => x.value + y.value,
  (sum) => {
    console.log(`sum of x + y is: ${sum}`)
  }
)

// 多个来源组成的数组
watch([x, () => y.value], ([newX, newY]) => {
  console.log(`x is ${newX} and y is ${newY}`)
})
2. 不能直接侦听响应式对象的属性值
const obj = reactive({ count: 0 })

// 错误,因为 watch() 得到的参数是一个 number
watch(obj.count, (count) => {
  console.log(`count is: ${count}`)
})
// 正确
// 提供一个 getter 函数
watch(
  () => obj.count,
  (count) => {
    console.log(`count is: ${count}`)
  }
)	
3. watchEffect 在创建侦听器时,立即执行一遍回调
watchEffect(async () => {
  const response = await fetch(url.value)
  data.value = await response.json()
})
4. watch 只追踪明确侦听的数据源;watchEffect,则会在副作用发生期间追踪依赖
5. 如果想在侦听器回调中能访问被 Vue 更新之后的DOM,你需要指明 flush: 'post' 选项

表单绑定

v-model

<input v-model="text">
v-model="text" 是v-bind:value="text" 和v-on:input="onInput" 的语法缩写
<input :value="text" @input="onInput">
自定义组件
<CustomInput v-model="searchText" />
<!-- CustomInput.vue -->
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>

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

条件渲染

v-if、v-else、v-else-if、v-show

<h1 v-if="awesome">Vue is awesome!</h1>
若 awesome 更改为假值 (Falsy),它将被从 DOM 中移除。
1. v-show 仅切换了该元素上名为 display 的 CSS 属性。
2. v-show 不支持在 <template> 元素上使用,也不能和 v-else 搭配使用。

列表渲染

v-for

<ul>
  <li v-for="todo in todos" :key="todo.id">
    {{ todo.text }}
  </li>
</ul>
更新列表:
1. 在源数组上调用变更方法: todos.value.push(newTodo)
2. 使用新的数组替代原数组: todos.value = todos.value.filter(/* ... */)
3. v-for 来遍历一个对象的所有属性
4. v-if 比 v-for 的优先级更高。这意味着 v-if 的条件将无法访问到 v-for 作用域内定义的变量别名
5. Vue 默认按照“就地更新”的策略来更新通过 v-for 渲染的元素列表。当数据项的顺序改变时,Vue 不会随之移动 DOM 元素的顺序,而是就地更新每个元素。重用和重新排序现有的元素,你需要为每个元素对应的块提供一个唯一的 key attribute

计算属性

computed
如果在模板中写太多逻辑,会让模板变得臃肿,难以维护
computed() 方法期望接收一个 getter 函数,返回值为一个计算属性 ref

const filteredTodos = computed(() => {
  // 根据 `todos.value` & `hideCompleted.value`
  // 返回过滤后的 todo 项目
})

const fullName = computed({
  // getter
  get() {
    return firstName.value + ' ' + lastName.value
  },
  // setter
  set(newValue) {
    // 注意:我们这里使用的是解构赋值语法
    [firstName.value, lastName.value] = newValue.split(' ')
  }
})

1. 计算属性值会基于其**响应式依赖**被缓存;方法调用总是会在重渲染发生时再次执行函数
2. 通过同时提供 getter 和 setter 来创建可写计算属性

生命周期和模板引用

<p ref="p">hello</p>
const p = ref(null)

import { onMounted } from 'vue'

onMounted(() => {
  // 此时组件已经挂载。
})
onMounted 组件完成初始渲染并创建dom节点后。
当调用 onMounted 时,Vue 会自动将回调函数注册到当前正被初始化的组件实例上。这意味着这些钩子应当在组件初始化时被同步注册

侦听器

watch

import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newCount) => {
  // 没错,console.log() 是一个副作用
  console.log(`new count is: ${newCount}`)
})
watch() 可以直接侦听一个 ref
watch() 也可以侦听其他类型的数据源

组件

import ChildComp from './ChildComp.vue'
<ChildComp />

1. 创建.vue 文件。这就是单文件组件。
import { ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    return { count }
  },
  template: `
    <button @click="count++">
      You clicked me {{ count }} times.
    </button>`
  // 或者 `template: '#my-template-element'`
}
2. 动态组件
<component :is="tabs[currentTab]"></component>
3. 全局注册
// app.component();全局注册,但并没有被使用的组件无法在生产打包时被自动移除 (也叫“tree-shaking”)
// 全局注册在大型项目中使项目的依赖关系变得不那么明确
4. 异步组件
// 在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件
import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent(() =>
  import('./components/MyComponent.vue')
)
// ... 像使用其他一般组件一样使用 `AsyncComp`
// 异步组件可以使用 app.component() 全局注册:
app.component('MyComponent', defineAsyncComponent(() =>
  import('./components/MyComponent.vue')
))
const AsyncComp = defineAsyncComponent({
  // 加载函数
  loader: () => import('./Foo.vue'),

  // 加载异步组件时使用的组件
  loadingComponent: LoadingComponent,
  // 展示加载组件前的延迟时间,默认为 200ms
  delay: 200,

  // 加载失败后展示的组件
  errorComponent: ErrorComponent,
  // 如果提供了一个 timeout 时间限制,并超时了
  // 也会显示这里配置的报错组件,默认值是:Infinity
  timeout: 3000
})
6. 

组合式函数

组合式函数:用 Vue 的组合式 API 来封装和复用有状态逻辑的函数。

// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'

// 按照惯例,组合式函数名以“use”开头
export function useMouse() {
  // 被组合式函数封装和管理的状态
  const x = ref(0)
  const y = ref(0)

  // 组合式函数可以随时更改其状态。
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  // 一个组合式函数也可以挂靠在所属组件的生命周期上
  // 来启动和卸载副作用
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  // 通过返回值暴露所管理的状态
  return { x, y }
}

<script setup>
import { useMouse } from './mouse.js'

const { x, y } = useMouse()
</script>

<template>Mouse position is at: {{ x }}, {{ y }}</template>

1. 组合式 API 会给予你足够的灵活性,让你可以基于逻辑问题将组件代码拆分成更小的函数

Props

子组件可以通过 props 从父组件接受动态数据

<!-- ChildComp.vue -->
<script setup>
const props = defineProps({
  msg: String
})
</script>

<ChildComp :msg="greeting" />
1. 单向数据流 props 都遵循着单向绑定原则 props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递
2. Prop 逐级透传 多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据 
<script setup>
import { provide } from 'vue'

provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
</script>
<script setup>
import { inject } from 'vue'

const message = inject('message')
</script>
3. 当提供 / 注入响应式的数据时,建议尽可能将任何对响应式状态的变更都保持在供给方组件中
<!-- 在供给方组件内 -->
<script setup>
import { provide, ref } from 'vue'

const location = ref('North Pole')

function updateLocation() {
  location.value = 'South Pole'
}

provide('location', {
  location,
  updateLocation
})
</script>
4. 如果你想确保提供的数据不能被注入方的组件更改,你可以使用 readonly()
<script setup>
import { ref, provide, readonly } from 'vue'

const count = ref(0)
provide('read-only-count', readonly(count))
</script>
5. 

Emits

子组件还可以向父组件触发事件

<script setup>
// 声明触发的事件
const emit = defineEmits(['response'])

// 带参数触发
emit('response', 'hello from child')

</script>

<ChildComp @response="(msg) => childMsg = msg" />
1. 使用$emit
<button @click="$emit('someEvent')">click me</button>

2. 

插槽

1.默认插槽
<FancyButton>
  Click me! <!-- 插槽内容 -->
</FancyButton>
// FancyButton.vue
<button class="fancy-btn">
  <slot></slot> <!-- 插槽出口 -->
</button>
2. 通过使用插槽,<FancyButton> 组件更加灵活和具有可复用性。现在组件可以用在不同的地方渲染各异的内容,但同时还保证都具有相同的样式。
3. 默认内容
<button type="submit">
  <slot>
    Submit <!-- 默认内容 -->
  </slot>
</button>
4. 具名插槽
<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

<BaseLayout>
  <template #header>
    <h1>Here might be a page title</h1>
  </template>

  <template #default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template>

  <template #footer>
    <p>Here's some contact info</p>
  </template>
</BaseLayout>
5. 作用域插槽
<!-- <MyComponent> 的模板 -->
<div>
  <slot :text="greetingMessage" :count="1"></slot>
</div>
<MyComponent v-slot="slotProps">
  {{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
6. 具名作用域插槽
<MyComponent>
  <template #header="headerProps">
    {{ headerProps }}
  </template>

  <template #default="defaultProps">
    {{ defaultProps }}
  </template>

  <template #footer="footerProps">
    {{ footerProps }}
  </template>
</MyComponent>
<slot name="header" message="hello"></slot>

7. 

自定义指令

自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑
组件是主要的构建模块,而组合式函数则侧重于有状态的逻辑

<script setup>
// 在模板中启用 v-focus
const vFocus = {
  mounted: (el) => el.focus()
}
</script>

<template>
  <input v-focus />
</template>

1. 局部注册
export default {
  setup() {
    /*...*/
  },
  directives: {
    // 在模板中启用 v-focus
    focus: {
      /* ... */
    }
  }
}
2. 全局注册
const app = createApp({})

// 使 v-focus 在所有组件中都可用
app.directive('focus', {
  /* ... */
})
TIP
3. 指令钩子
const myDirective = {
  // 在绑定元素的 attribute 前
  // 或事件监听器应用前调用
  created(el, binding, vnode, prevVnode) {
    // 下面会介绍各个参数的细节
  },
  // 在元素被插入到 DOM 前调用
  beforeMount(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都挂载完成后调用
  mounted(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件更新前调用
  beforeUpdate(el, binding, vnode, prevVnode) {},
  // 在绑定元素的父组件
  // 及他自己的所有子节点都更新后调用
  updated(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载前调用
  beforeUnmount(el, binding, vnode, prevVnode) {},
  // 绑定元素的父组件卸载后调用
  unmounted(el, binding, vnode, prevVnode) {}
}
4. 插件
插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码
import { createApp } from 'vue'

const app = createApp({})

app.use(myPlugin, {
  /* 可选的选项 */
})
一个插件可以是一个拥有 install() 方法的对象
const myPlugin = {
  install(app, options) {
    // 配置此应用
  }
}

Transition

是一个内置组件,这意味着它在任意别的组件中都可以被使用,无需注册
进入或离开可以由以下的条件之一触发:

由 v-if 所触发的切换
由 v-show 所触发的切换
由特殊元素 切换的动态组件

<button @click="show = !show">Toggle</button>
<Transition>
  <p v-if="show">hello</p>
</Transition>
/* 下面我们会解释这些 class 是做什么的 */
.v-enter-active,
.v-leave-active {
  transition: opacity 0.5s ease;	
}

.v-enter-from,
.v-leave-to {
  opacity: 0;
}
你可以通过监听 <Transition> 组件事件的方式在过渡过程中挂上钩子函数
<Transition
  @before-enter="onBeforeEnter"
  @enter="onEnter"
  @after-enter="onAfterEnter"
  @enter-cancelled="onEnterCancelled"
  @before-leave="onBeforeLeave"
  @leave="onLeave"
  @after-leave="onAfterLeave"
  @leave-cancelled="onLeaveCancelled"
>
  <!-- ... -->
</Transition>
// 在元素被插入到 DOM 之前被调用
// 用这个来设置元素的 "enter-from" 状态
function onBeforeEnter(el) {}

// 在元素被插入到 DOM 之后的下一帧被调用
// 用这个来开始进入动画
function onEnter(el, done) {
  // 调用回调函数 done 表示过渡结束
  // 如果与 CSS 结合使用,则这个回调是可选参数
  done()
}

// 当进入过渡完成时调用。
function onAfterEnter(el) {}
function onEnterCancelled(el) {}

// 在 leave 钩子之前调用
// 大多数时候,你应该只会用到 leave 钩子
function onBeforeLeave(el) {}

// 在离开过渡开始时调用
// 用这个来开始离开动画
function onLeave(el, done) {
  // 调用回调函数 done 表示过渡结束
  // 如果与 CSS 结合使用,则这个回调是可选参数
  done()
}

// 在离开过渡完成、
// 且元素已从 DOM 中移除时调用
function onAfterLeave(el) {}

// 仅在 v-show 过渡中可用
function onLeaveCancelled(el) {}


是一个内置组件,用于对 v-for 列表中的元素或组件的插入、移除和顺序改变添加动画效果。

<TransitionGroup name="list" tag="ul">
  <li v-for="item in items" :key="item">
    {{ item }}
  </li>
</TransitionGroup>
.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

KeepAlive

是一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例。

<component :is="activeComponent" />
	

Teleport

是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。

<Teleport> 接收一个 to prop 来指定传送的目标。to 的值可以是一个 CSS 选择器字符串,也可以是一个 DOM 元素对象。这段代码的作用就是告诉 Vue“把以下模板片段传送到 body 标签下”。
<button @click="open = true">Open Modal</button>

<Teleport to="body">
  <div v-if="open" class="modal">
    <p>Hello from the modal!</p>
    <button @click="open = false">Close</button>
  </div>
</Teleport>

单文件组件

Vue 的单文件组件是一种特殊的文件格式,使我们能够将一个 Vue 组件的模板、逻辑与样式封装在单个文件中

前端开发的关注点不是完全基于文件类型分离的。前端工程化的最终目的都是为了能够更好地维护代码。关注点分离不应该是教条式地将其视为文件类型的区别和分离,仅仅这样并不够帮我们在日益复杂的前端应用的背景下提高开发效率。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:19:49  更:2022-11-05 00:23:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 18:28:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码