Vue3入门 | 青训营笔记

98 阅读7分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 22 天

API

Vue项目由多个单文件组件组成,单文件组件将这个组件的JavaScript(script标签中)HTML(template标签中)CSS(style标签中)封装到一个后缀为.vue的文件中。组件有以下两种书写风格:

选项式API

使用包含多个选项的对象来组成逻辑,选项所定义的属性都会暴露在指向当前组件的this上。

组合式API

使用导入(import)的API函数来描述组件逻辑。

基础

应用

创建应用

每个应用都通过VuecreateApp函数创建,应用可以保存在变量中。 传入createApp函数的是一个组件,这个组件作为根组件,其它组件可以作为子组件。 组件可以从单文件组件直接导入。

import App from './App.vue'

const app = createApp(App)

应用实例会暴露多个方法和对象。

挂载应用

应用被创建之后可以只有在调用了.mount()方法挂载到一个容器( DOM元素或者CSS选择器的字符串)上之后才可以被渲染。注意

<div id="app"></div>
app.mount('#app')

注意把js脚本文件放在html的最后,因为需要挂载到前面的元素上。

可以创建多个应用让其分别挂载到页面的不同位置,每个应用都有自己的用于配置和全局资源的作用域。

模板语法

文本插值

Vue可以使双大括号替换为相应组件中msg 属性的值。

<span>{{ msg }}</span>

msg还可以是JavaScript的表达式,但这个表达式必须是可以求值的(即把return加在前面也合法),相当于表达式返回一个值赋给msg。 attribute的值并不支持双大括号语法(Mustache语法)。

指令

指令是带有v-前缀的特殊attribute。

某些指令可能需要一个参数(attribute),在指令名后通过:隔开。指令参数可以是JavaScript表达式,在一对[]中,尽量不去使用大写。 指令还可以具有修饰符(.开头的特殊后缀),表明指令需要以特殊的方式被绑定。 值可以是JavaScript的表达式,也可以是组件中暴露的函数。

指令的任务是在状态改变时响应式的更新DOM。

v-html

如果msg的值为HTML,就不能使用{{}}这种方法,双大括号会将数据解释为纯文本。 插入HTML需要使用v-html指令。

<script>
export default {
  data() {
    return {
      msg: '<span style="color: red">Red msg'
    }
  }
}
</script>

<template>
  <p><span v-html="msg"></span></p>
</template>

v-bind

名字:参数.修饰符=值 v-bind指令用于响应式的绑定一个attribute。此时的属性值会随着vid进行改变。

<div v-bind:id="vid"><div/>

或者使用简写语法。

<div :id="vid"><div/>

可以通过不带参数的v-bind,将一个包含多个attribute的对象绑定到一个元素上。

data() {
  return {
    atts: {
      id: "aid",
      class: "aclass"
    }
  }
}
<div v-bind="atts"><div/>

当绑定的值为null或者undefined,这个attribute将会被移除。感觉可以用来搭配属性选择器。

响应式基础

DOM的更新并不是同步的,无论状态发生了多少次改变,每个组件直到下一次时机都只更新一次。

组合式

可以通过reactive()函数(接受一个对象作为参数)或者ref()方法创建响应式的对象(其实是Proxy对象即对象的代理)或者数组。

reactive()

必须用通过setup()函数将定义的响应式对象返回,才能使其被暴露到模板中。定义操作也是在这个函数中完成的。 还可以在setup()函数中定义并返回响应式的函数。

import { reactive } from 'vue'

export default {
  setup() {
	const state = reactive( { x: 0} )

	function fc() {
		//...
	}

	return {
	  x,
	  fc
	}
  }
}

默认导出/导出必须位于模块或文件的顶层。

还可以借助<script setup>,只需在里面进行定义即可,也不需要export default

但是reactive不支持原生类型,而且替换响应式对象会导致初始化的响应式链接丢失。

ref()

ref()会将传入的参数转换为带.value属性的对象并返回,使用value属性对值进行访问。 当ref被作为顶层属性使会自动进行解包,就不需要.value属性了。但是集合类型的元素不会被解包。

选项式

选项式API用data(值为返回一个对象的函数)选项声明组件的响应式状态,之后用this进行访问。

export default {
  data {
    return {
      state: 0
    }
  }
}

计算属性

可以使用计算属性来描述依赖响应式状态的复杂逻辑。 相比与方法计算属性值会基于响应式状态进行缓存,因为方法会在重新渲染时执行函数,而计算属性只要响应式状态不发生改变就不会执行getter。

组合式

计算属性的创建需要借助于computed()方法,接受一个getter函数,返回一个计算属性ref。 如果想要改变属性的值,可以在创建计算属性时同时传入一个setter函数。

<script>
import { ref } from 'vue'

const fname = ref("qg")
const lname = ref("xx")

const name = computed({
  get() {
    return fname.value + ' ' + lname.value 
  },
  set(n) {
    [fname.value, lname.value] = n.split(' ')
  }
})
</script> 

想使用普通属性一样使用name:使用值name.value,重新赋值name.value = jq yy。因为是响应式的,fname和lname属性也会随之改变。

选项式

通过computed选项,可以只添加具有get功能的函数,也可以添加同时具有getter和setter的对象。

<script>
export default {
  data() {
    return {
      fname: "qg",
      lname: "xx"
    }
  },

  computed: {
    name: {
      get() {
        return this.fname + ' ' + this.lname
      },
      set(n) {
        [this.fname, this.lname] = n.split(' ')
      }
    }
  }
}
</script>

class与style绑定

这需要使用v-bind指令对其进行绑定,指令可以和原有的属性共存。

class

可以和动态字符串、对象、数组进行绑定。

表达式:

<div :class="isActive ? CActive : ''"></div>

对象:

<div class="1" :class="{ active: isActive, 'text-danger': hasError }"></div>
<script setup>
const classObject = reactive({
  active: true,
  'text-danger': false
})
</script>

<template>
<div :class="classObject"></div>
</template>

数组:

<script setup>
const CActive = ref('active')
const CError = ref('text-danger')
</script>

<div :class="[CActive, CError]"></div>

表达式也和对象也可以作为数组的元素。

在使用组件时,class会和组件模板的class合并。

style

可以直接和对象或数组进行绑定。

<script setup>
const styleObject = reactive({
  color: 'red',
  display: 'block'
})
</script>

<template>
<div :style="styleObject"></div>
</template>
<script setup>
const colorVal = ref('red')
const fontSize = ref(20)
</script>

<template>
<div :style="{ color: colorVal, fontSize: fontSize + 'px' }"></div>
</template>

绑定的样式属性可以具有多个值,会选择浏览器支持的最后一个值。

<div :style="{ :style: ['-webkit-box', 'flex']}"></div>

:style支持自动前缀,使用了浏览器特殊前缀的属性时,会自动加上。

渲染

条件渲染

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

用类似于if-else的条件语句来进行条件渲染,当表达式为真值时才会被渲染。

<div v-if="type === 1"></div>
<div v-else-if="type === 2"></div>
<div v-else></div>

如果需要同时切换多个元素,可以把v-if指令放在<template>上。

v-show

v-show指令会在DOM渲染中保留该元素,仅会切换display属性。

列表渲染

在对列表进行渲染时可以使用v-for指令基于数组或对象来渲染。 v-for指令类似于for-in语句。

<script setup>
const items = ref([{msg: '1'}, {msg: '2'}])
</script>

<li v-for="(item, index) in items" :key="item.id">
  {{ index}} {{item.msg}}
</li>

通过绑定key来管理状态。

<script>
const items = reactive({
  title: "",
  arguments: "",
  auther: ""
})
</script>

<ul>
  <li v-for="(value, key, index) in items" :key="item.id">
    {{ index }}. {{ key }}: {{ value }}
  </li>
</ul>

在使用组件时必须通过绑定才能使用数据。

<Component 
  v-for="(item, index) in items"
  :item="item" :index="index" :key="item.id"
/>

事件处理

通过使用v-on指令来监听DOM实践。 v-on:事件="事件处理器"@事件="事件处理器" 事件处理器可以是JavaScript语句或者方法。

使用方法时会自动传递一个原生事件(在方法定义时要准备名为event的参数,使用时不需要传入),也可以自定义传入的参数来代替默认的事件。

<script setup>
function greet(event) { 
  if (event) {
	alert(event.target.tagName)
  }
</script>

<template>
  <button @click="greet">Greet</button>
</template>

在处理器中访问DOM事件时需要传入$event变量。

<script setup>
function greet(msg, event) { 
  if (event) {
	event.preventDefault()
  }
  alert(msg)
</script>

<template>
  <button @click="greet('greet', $event)">Greet</button>
</template>

修饰符

通过给v-on指令增加修饰符可以规定事件的触发。

条件修饰符

.once时间只触发一次。 .prevent组织事件默认行为。 …… 修饰符可以使用链式书写。

按键修饰符

.enter.tap …… 系统按键修饰符:.ctrl.alt.shift.meta可以和其它按键修饰符组合触发事件 .exact规定触发事件所需的确定组合的修饰符。

表单输入绑定

在把表单得到的value同步给JavaScript的变量时可以使用v-model指令。 v-model的值是要进行更新的响应式变量。

使用v-bind响应式绑定+v-on事件处理:

<script setup>
import { ref } from 'vue'

const message = ref('')
</script>

<template>
  <p>Message is: {{ message }}</p>
	<input :value="message" @input="event => message = event.target.value" placeholder="edit me" />
</template>

使用v-model指令:

<script setup>
import { ref } from 'vue'

const message = ref('')
</script>

<template>
  <p>Message is: {{ message }}</p>
	<input v-model="message" placeholder="edit me" />
</template>

值绑定

文本、单选按钮、选择器默认传递的都是value属性的值,复选框传递的是true/false。 文本、单选按钮、选择器可以通过v-bind绑定value传递响应式的值,复选款可以绑定true-valuefalse-value在为true/false时传递绑定的值。

v-model指令也可以添加修饰符。

  • .trim:去除两端空格
  • .number转换为数字
  • .lazy每次change事件后更新数据

声明周期

通过注册声明周期钩子,可以在特定阶段运行代码。

侦听器

使用watch函数可以创建数据源响应式状态发生改变时调用回调函数的侦听器。侦听器的创建必须用同步语句。侦听器创建时会返回一个函数,这个函数可以用于停止侦听器。

第一个参数被称作数据源,可以时响应式对象、ref、getter(用来代替响应式对象的属性值)、数组。

添加{deep: true} 可以创建深层的侦听器,嵌套发生变换就会触发回调。

添加{immediate: true} ,可以让回调在创建时立即执行。 使用watchEffec函数,为其传入一个回调函数作为参数,不需要明确指定源,也不需要额外添加 { immediate: true} ,回调会立即执行。但要和使用watch一样创建响应式状态,watchEffect会自动跟踪一切可以访问的响应式属性作为源,并在源发生改变时执行回调。

添加{flush: post},可以让回调访问更新之后的DOM,因为默认会先执行侦听器回调。也可以使用 watchPostEffect函数。

模板引用

<script>定义一个空的ref,并在元素中为其增加ref属性,值与定义的ref同名,在被挂载之后,就能得到这个模板的引用。

<script setup>
import { ref } from 'vue'
const input = ref(null)
</script>

<template>
<input ref="input" />
</template>