Vue初探

上一次学前端已经是大二暑假了,先顺一遍introduction

to be continued 不希望有continued了

开始

简介

什么是Vue

  • 用于构建用户界面的js框架
  • 提供一套声明式组件化的编程模型
  • 核心功能
    • 声明式渲染
      • 基于html的模板语法
      • 声明式描述最终输出的html和js状态之间的关系
    • 响应性
      • 自动跟踪js状态并在发生变化时响应式更新DOM

单文件组件SFC

.vue文件将一个组件的逻辑(js),模板(html)和样式(css)封装在一个文件里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
<button @click="count++"> Count is: {{ count }} </button>
</template>

<style scoped>
button {
font-weight: bold;
}
</style>

API风格

选项式API

  • 用多个组件选项描述组件逻辑
    • data
      • 一个必须定义的属性
      • 一个返回对象的函数,对象中定义的属性会成为组件实例的响应式数据
      • 响应式数据可被模板和组件方法访问和操作
    • methods
      • 一个对象
      • 定义组件实例的方法
      • 方法可被模板或其他方法调用,也可访问组件的响应式数据
    • mounted
      • 生命周期hook之一
      • 组件实例被创建并插入到DOM中时,mounted hook就会被调用
      • 执行一些初始化操作
  • 选项定义的属性暴露在函数内部的this(指向当前的组件实例)上
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script>
export default {
data() {
return {
count: 0
}
},

methods: {
increment() {
this.count++
}
},

mounted() {
console.log(`The initial count is ${this.count}.`)
}
}
</script>

<template>
<button @click="increment"> Count is: {{ count }} </button>
</template>

组合式API

  • 使用导入的API函数来描述组件逻辑
  • 通常与<script setup>搭配使用,setup attribute是一个标识,表示需要在编译时进行一些处理(如导入和顶层变量/函数都能在模板中直接使用)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script setup>
import { ref, onMounted } from 'vue'

const count = ref(0)

function increment() {
count.value++
}

onMounted(() => {
console.log(`The initial count is ${count.value}`)
})
</script>

<template>
<button @click="increment"> Count is: {{ count }} </button>
</template>

基础

Vue应用

  • 应用实例:通过createApp函数创建,传入一个组件

    1
    2
    3
    4
    5
    import { createApp } from 'vue'

    const app = createApp({
    /* 根组件选项 */
    })
  • 根组件:传入createApp的组件,使用单文件组件可以从文件直接导入

    1
    2
    3
    4
    5
    import { createApp } from 'vue'

    import App from './App.vue'

    const app = createApp(App)

    组件可嵌套

    1
    2
    3
    4
    5
    6
    7
    8
    App (root component)
    ├─ TodoList
    │ └─ TodoItem
    │ ├─ TodoDeleteButton
    │ └─ TodoEditButton
    └─ TodoFooter
    ├─ TodoClearButton
    └─ TodoStatistics
  • 应用挂载:应用实例在调用mount后才会渲染

    • mount方法接收一个容器参数,一个实际的DOM元素是一个CSS选择器字符串
    • mount方法应该在应该始终在整个应用配置和资源注册完成后被调用

示例

1
2
3
4
5
6
7
8
9
10
<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
<!-- …… -->
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
1
2
3
4
5
6
7
8
// main.js

import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
  • 应用根组件内容渲染在容器元素里

  • 放在body中的script标签在html解析完成后执行

DOM中的根组件模板

  • 根组件模板通常是组件的一部分,但也可以直接通过在挂载容器内编写模板来单独提供
  • 根组件未设置template选项时,Vue自动选择使用容器的innerHTML作为模板(容器里的标签,我理解的)
1
2
3
4
5
<div id="app">
<button @click="count++">
{{ count }}
</button>
</div>
1
2
3
4
5
6
7
8
9
10
11
import { createApp } from 'vue'

const app = createApp({
data() {
return {
count: 0
}
}
})

app.mount('#app')

应用配置

  • config:应用实例的config对象可以用于配置应用级选项,如定义一个应用的错误处理器

    1
    2
    3
    app.config.errorHandler = (err) => {
    /* 错误处理 */
    }
  • 一些方法注册范围内可用资源,如注册一个组件

    1
    app.component('TodoDeleteButton', TodoDeleteButton)

    使得TodoDeleteButton在应用的任何地方可用

多个应用实例

createApp允许一个页面多个应用共存

1
2
3
4
5
6
7
8
9
const app1 = createApp({
/* ... */
})
app1.mount('#container-1')

const app2 = createApp({
/* ... */
})
app2.mount('#container-2')

模板语法

  • 文本插值:双大括号标签会被替换为相应组件实例中msg属性的值,msg属性更新值也会同步更新

    1
    <span> Message: {{ msg }} </span>
  • 原始HTML:双大括号将数据解释为纯文本,使用v-html插入HTML

    1
    2
    3
    <p>
    Using v-html direction: <span v-html="rawHtml"></span>
    </p>
    • v-html:指令,v-前缀,为渲染的DOM应用特殊的响应式行为
      • 在当前组件实例上,将此元素的innerHTML与rawHtml属性保持同步
      • span的内容将会被替换为rawHtml属性的值,插值为纯HTML,数据绑定被忽略
  • Attribute绑定:响应式绑定attribute

    1
    <div v-bind:id="dynamicId"></div>
    • v-bind指示元素的id attribute和组件的dynamicId属性保持一致

    • 简写

      1
      <div :id="dynamicId"></div>
    • 同名简写:attribute名与绑定的js值名称一样

      1
      <div :id></div>
    • 布尔型Attribute:依据true/false值来决定attribute是否应该存在于该元素上

      1
      2
      3
      <button :disabled="isButtonDisabled">
      Button
      </button>
    • 动态绑定多个值:通过不带参数的v-bind将包含多个attribute的对象绑定到单个元素上

      1
      2
      3
      4
      5
      6
      7
      8
      data() {
      return {
      objectOfAttrs: {
      id: 'container',
      class: 'wrapper'
      }
      }
      }
      1
      <div v-bind="objectOfAttrs"></div>
  • 使用JS表达式:所有数据绑定都支持完整的JS表达式,如

    1
    2
    3
    {{ number + 1 }}
    {{ ok ? 'YES' : 'NO' }}
    {{ message.split('').reverse().join('') }}
    1
    <div :id="`list-${id}`"></div>

    模板内,JS表达式可以被用于以下场景

    • 文本插值(大括号中)
    • 任何Vue指令(v-开头的特殊attribute)attribute的值中

    注意

    • 绑定仅支持单一表达式:即一段能求值的JS代码,以下无效

      1
      2
      {{ var a = 1 }}
      {{ if (ok) { return message } }}
    • 调用函数:可以在绑定的表达式中使用一个组件暴露的方法

      1
      2
      3
      <time :title="toTitleDate(date)" :datatime="date">
      {{ formatData(date) }}
      </time>

      绑定在表达式中的方法在组件每次更新时都会调用,所以不该产生任何副作用

    • 受限的全局访问:模板中的表达式将被沙盒化,仅能够访问到有限的全局对象列表


Vue初探
http://akaieurus.github.io/2024/07/02/vue初探/
作者
Eurus
发布于
2024年7月2日
许可协议