Vue.js3.0

Vue.js 3.0

javaScript 相关

Symbol() 是 JavaScript 中的一个原始数据类型,用于创建唯一的、不可变的值。

安装npm install @vue/cli -g

本地node安装vue 工具用于创建项目

命令行输入 vue ui ,根据网址在线创建

​基础语法

​语法

1、取值双大括号 {{}}

生命周期

​组合式API

创建应用

import { createApp } from ‘vue’
​​import { createApp } from “vue”; import App from “./App.vue”; const app = createApp(App); 挂载 其他组件  router 、store app.use(router).use(store); //最后 app.mount(“#el”);
.mount() 方法应该始终在整个应用配置和资源注册完成后被调用。同时请注意,不同于其他资源注册方法,它的返回值是根组件实例而非应用实例。

​数据和方法

​function/箭头函数
​使用箭头函数定义方法时并不会创建函数作用域,因此this也不会指向其父级实例,此时的this会向上追踪。当找到某个函数作用域时,this将指向该函数的父级实例;否则,this将指向浏览器的内置对象Windows。

​watch更注重于处理数据变化时的业务逻辑,而computed更注重于衍生数据

​DOM渲染

​选项优先级
​选项的优先级 el、template、render三个选项的功能是一致的——获取实例模板(指定或是创建)。然而,当实例同时存在这三个选项时,Vue将如何处理呢? render>template>el

​封装复用

计算属性

创建一个只读的计算属性 ref:

const count = ref(1)
const plusOne = computed(() => count.value + 1)

console.log(plusOne.value) // 2

plusOne.value++ // 错误

创建一个可写的计算属性 ref:

const count = ref(1)
const plusOne = computed({
get: () => count.value + 1,
set: (val) => {
count.value = val - 1
}
})

plusOne.value = 1
console.log(count.value) // 0

侦听器

侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数。

watch 的第一个参数可以是不同形式的“数据源”:它可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组
你不能直接侦听响应式对象的属性值 ,因为属性值不为响应式监听,使用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})
})

watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。

watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确

watchEffect

对于这种只有一个依赖项的例子来说,watchEffect() 的好处相对较小。但是对于有多个依赖项的侦听器来说,使用 watchEffect() 可以消除手动维护依赖列表的负担。此外,如果你需要侦听一个嵌套数据结构中的几个属性,watchEffect() 可能会比深度侦听器更有效,因为它将只跟踪回调中被使用到的属性,而不是递归地跟踪所有的属性。

const todoId = ref(1)
const data = ref(null)

watch(todoId, async () => {
const response = await fetch(
https://jsonplaceholder.typicode.com/todos/${todoId.value}
)
data.value = await response.json()
}, { immediate: true })

简化
watchEffect(async () => {
const response = await fetch(
https://jsonplaceholder.typicode.com/todos/${todoId.value}
)
data.value = await response.json()
})

修饰符

.lazy
默认情况下,v-model 会在每次 input 事件后更新数据 (IME 拼字阶段的状态例外)。你可以添加 lazy 修饰符来改为在每次 change 事件后更新数据
.number
如果你想让用户输入自动转换为数字,你可以在 v-model 后添加 .number 修饰符来管理输入

如果该值无法被 parseFloat() 处理,那么将返回原始值。

number 修饰符会在输入框有 type=“number” 时自动启用。

.trim
如果你想要默认自动去除用户输入内容中两端的空格,你可以在 v-model 后添加 .trim 修饰符:
.prevent
.prevent修饰符可以用于阻止元素的默认行为,例如防止表单提交或链接页面跳转时重新加载页面。

当使用@click.prevent修饰符时,点击事件将不会触发默认行为(例如将链接打开或提交表单),而只会执行绑定的方法。
点击按钮将调用submitForm方法来提交表单,而不会触发按钮的默认行为,即重新加载页面

事件修饰符 .passive、.capture 和 .once

Prop 逐级透传问题,定义全局参数

provide 和 inject 可以帮助我们解决这一问题。 [1] 一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

父组件提供者 提供key,value

,提供的响应式状态使后代组件可以由此和提供者建立响应式的联系。
import { ref, provide } from ‘vue’

const count = ref(0)
provide(‘key’, count)

Provide​除了在一个组件中提供依赖,我们还可以在整个应用层面提供依赖:
import { createApp } from ‘vue’
const app = createApp({})
app.provide(/* 注入名 / ‘message’, / 值 */ ‘hello!’)
在应用级别提供的数据在该应用内的所有组件中都可以注入。这在你编写插件时会特别有用,因为插件一般都不会使用组件形式来提供值。

import { inject } from ‘vue’

const message = inject(‘message’,‘这是默认值’)

当提供 / 注入响应式的数据时,建议尽可能将任何对响应式状态的变更都保持在供给方组件中。这样可以确保所提供状态的声明和变更操作都内聚在同一个组件内,使其更容易维护。

有的时候,我们可能需要在注入方组件中更改数据。在这种情况下,我们推荐在供给方组件内声明并提供一个更改数据的方法函数

响应性

import { toRefs, toRef } from ‘vue’

export default {
setup(props) {
// 将 props 转为一个其中全是 ref 的对象,然后解构
const { title } = toRefs(props)
// title 是一个追踪着 props.title 的 ref
console.log(title.value)

// 或者,将 `props` 的单个属性转为一个 ref
const title = toRef(props, 'title')

}
}

深层响应性

reactive
import { reactive } from ‘vue’

const obj = reactive({
nested: { count: 0 },
arr: [‘foo’, ‘bar’]
})

function mutateDeeply() {
// 以下都会按照期望工作
obj.nested.count++
obj.arr.push(‘baz’)
}

  • shallowReactive()是 reactive() 的浅层作用形式

  • reactive() 返回的是一个原始对象的 Proxy,它和原始对象是不相等的

  • reactive() API 有两条限制:

仅对对象类型有效(对象、数组和 Map、Set 这样的集合类型),而对 string、number 和 boolean 这样的 原始类型 无效。

因为 Vue 的响应式系统是通过属性访问进行追踪的,因此我们必须始终保持对该响应式对象的相同引用。这意味着我们不可以随意地“替换”一个响应式对象,因为这将导致对初始引用的响应性连接丢失:

  • reactive() 的种种限制归根结底是因为 JavaScript 没有可以作用于所有值类型的 “引用” 机制。

  • TIP 不推荐使用 reactive() 的泛型参数,因为处理了深层次 ref 解包的返回值与泛型参数的类型不同。

toRefs()
  • 将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。
toRef()
  • 基于响应式对象上的一个属性,创建一个对应的 ref。这样创建的 ref 与其源属性保持同步:改变源属性的值将更新 ref 的值,反之亦然
ref
Vue 提供了一个 ref() 方法来

允许我们创建可以使用
任何值类型的响应式 ref

  • import { ref } from ‘vue’

const count = ref(0)

ref() 将传入参数的值包装为一个带 .value 属性的 ref 对象
和响应式对象的属性类似,ref 的 .value 属性也是响应式的。同时,当值为对象类型时,会用 reactive() 自动转换它的 .value
  • const objectRef = ref({ count: 0 })

// 这是响应式的替换
objectRef.value = { count: 1 }

  • ref() 让我们能创造一种对任意值的 “引用”,并能够在不丢失响应性的前提下传递这些引用。这个功能很重要,因为它经常用于将逻辑提取到 组合函数 中
ef 在模板中的解包​

当 ref 在模板中作为顶层属性被访问时,它们会被自动“解包”,所以不需要使用 .value

  • 当一个 ref 被嵌套在一个响应式对象中,作为属性被访问或更改时,它会自动解包,因此会表现得和一般的属性一样

  • 只有当嵌套在一个深层响应式对象内时,才会发生 ref 解包。当其作为浅层响应式对象的属性被访问时不会解包。

toRow
const foo = {}

const reactiveFoo = reactive(foo)

console.log(toRaw(reactiveFoo) === foo) // true

  • 这是一个可以用于临时读取而不引起代理访问/跟踪开销,或是写入而不触发更改的特殊方法。不建议保存对原始对象的持久引用,请谨慎使用

单文件组件

1、组件名应该采用单词大写开头的驼峰命名法,例如"TodoList"。

2、组件应该在一个单独的文件中进行定义,文件名应该与组件名相同,并以.vue为后缀。

当不使用构建步骤时,一个 Vue 组件以一个包含 Vue 特定选项的 JavaScript 对象来定义:

import { ref } from ‘vue’

export default {
setup() {
const count = ref(0)
return { count }
},
template:
// 或者 template: '#my-template-element'
}

当使用构建步骤时,我们一般会将 Vue 组件定义在一个单独的 .vue 文件中,这被叫做单文件组件 (简称 SFC):

defineProps 是一个仅

const props = defineProps([‘title’])
console.log(props.title)

传递 props,

接收任意类型的 JavaScript 值作为 props

如果你没有使用

export default {
props: [‘title’],
setup(props) {
console.log(props.title)
}
}

defineProps() 和 defineEmits()

const props = defineProps({
foo: String
})

const emit = defineEmits([‘change’, ‘delete’])
// setup 代码


@enlarge-text=“postFontSize += 0.1”
/>

子组件可以通过调用内置的 $emit 方法,通过传入事件名称来抛出一个事件:

vue

{{ title }}

defineEmits 仅可用于
  • export default defineComponent({
    emits: [‘update:value’],

props: {
value: {
type: String,
required: true
}
},

setup(props, { emit }) {
function onInput(event) {
emit(‘update:value’, event.target.value);
}

return {
  onInput
};

}
});

插槽,组件要接收模板内容

为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。

实例

Click me!


  * 
渲染作用域
插槽内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件模板中定义的

插槽内容无法访问子组件的数据。Vue 模板中的表达式只能访问其定义时所处的作用域,这和 JavaScript 的词法作用域规则是一致的。换言之:

父组件模板中的表达式只能访问父组件的作用域;子组件模板中的表达式只能访问子组件的作用域。

默认内容
Submit
具名插槽
插槽带有name名称
  • 使用时指定,v-slot 有对应的简写 #


  *