vue学习笔记1

API 风格

Vue 的组件可以按两种不同的风格书写:选项式 API组合式 API

选项式 API (Options API)

使用选项式 API,我们可以用包含多个选项的对象来描述组件的逻辑,例如 datamethodsmounted。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。

<script>
export default {
  // data() 返回的属性将会成为响应式的状态
  // 并且暴露在 `this` 上
  data() {
    return {
      count: 0
    }
  },

  // methods 是一些用来更改状态与触发更新的函数
  // 它们可以在模板中作为事件监听器绑定
  methods: {
    increment() {
      this.count++
    }
  },

  // 生命周期钩子会在组件生命周期的各个不同阶段被调用
  // 例如这个函数就会在组件挂载完成后被调用
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>

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

组合式 API (Composition API)

通过组合式 API,我们可以使用导入的 API 函数来描述组件逻辑。在单文件组件中,组合式 API 通常会与 [](https://cn.vuejs.org/api/sfc-script-setup.html) 搭配使用。这个 `setup` attribute 是一个标识,告诉 Vue 需要在编译时进行一些处理,让我们可以更简洁地使用组合式 API。比如, 中的导入和顶层变量/函数都能够在模板中直接使用。

下面是使用了组合式 API 与 `` 改造后和上面的模板完全一样的组件:

<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>

该选哪一个?

两种 API 风格都能够覆盖大部分的应用场景。它们只是同一个底层系统所提供的两套不同的接口。实际上,选项式 API 是在组合式 API 的基础上实现的!关于 Vue 的基础概念和知识在它们之间都是通用的。

选项式 API 以“组件实例”的概念为中心 (即上述例子中的 this),对于有面向对象语言背景的用户来说,这通常与基于类的心智模型更为一致。同时,它将响应性相关的细节抽象出来,并强制按照选项来组织代码,从而对初学者而言更为友好。

组合式 API 的核心思想是直接在函数作用域内定义响应式状态变量,并将从多个函数中得到的状态组合起来处理复杂问题。这种形式更加自由,也需要你对 Vue 的响应式系统有更深的理解才能高效使用。相应的,它的灵活性也使得组织和重用逻辑的模式变得更加强大。

组合式 API FAQ 章节中,你可以了解更多关于这两种 API 风格的对比以及组合式 API 所带来的潜在收益。

如果你是使用 Vue 的新手,这里是我们的大致建议:

  • 在学习的过程中,推荐采用更易于自己理解的风格。再强调一下,大部分的核心概念在这两种风格之间都是通用的。熟悉了一种风格以后,你也能够很快地理解另一种风格。
  • 在生产项目中:
    • 当你不需要使用构建工具,或者打算主要在低复杂度的场景中使用 Vue,例如渐进增强的应用场景,推荐采用选项式 API。
    • 当你打算用 Vue 构建完整的单页应用,推荐采用组合式 API + 单文件组件。

创建一个 Vue 应用

前提条件

  • 熟悉命令行
  • 已安装 16.0 或更高版本的 Node.js

在本节中,我们将介绍如何在本地搭建 Vue 单页应用。创建的项目将使用基于 Vite 的构建设置,并允许我们使用 Vue 的单文件组件 (SFC)。

确保你安装了最新版本的 Node.js,然后在命令行中运行以下命令 (不要带上 > 符号):

> npm init vue@latest

这一指令将会安装并执行 create-vue,它是 Vue 官方的项目脚手架工具。你将会看到一些诸如 TypeScript 和测试支持之类的可选功能提示:

✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add Cypress for both Unit and End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes

Scaffolding project in ./<your-project-name>...
Done.

如果不确定是否要开启某个功能,你可以直接按下回车键选择 No。在项目被创建后,通过以下步骤安装依赖并启动开发服务器:

> cd <your-project-name>
> npm install
> npm run dev

你现在应该已经运行起来了你的第一个 Vue 项目!请注意,生成的项目中的示例组件使用的是组合式 API 和 ``,而非选项式 API。下面是一些补充提示:

当你准备将应用发布到生产环境时,请运行:

> npm run build

此命令会在 ./dist 文件夹中为你的应用创建一个生产环境的构建版本。关于将应用上线生产环境的更多内容,请阅读生产环境部署指南

根组件

我们传入 createApp 的对象实际上是一个组件,每个应用都需要一个“根组件”,其他组件将作为其子组件。

如果你使用的是单文件组件,我们可以直接从另一个文件中导入根组件。

import { createApp } from 'vue'
// 从一个单文件组件中导入根组件
import App from './App.vue'

const app = createApp(App)

虽然本指南中的许多示例只需要一个组件,但大多数真实的应用都是由一棵嵌套的、可重用的组件树组成的。例如,一个待办事项 (Todos) 应用的组件树可能是这样的:

App (root component)
├─ TodoList
│  └─ TodoItem
│     ├─ TodoDeleteButton
│     └─ TodoEditButton
└─ TodoFooter
   ├─ TodoClearButton
   └─ TodoStatistics

我们会在指南的后续章节中讨论如何定义和组合多个组件。在那之前,我们得先关注一个组件内到底发生了什么。

模板语法

最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法 (即双大括号):

<span>Message: {{ msg }}</span>

双大括号标签会被替换为相应组件实例中 msg 属性的值。同时每次 msg 属性更改时它也会同步更新。

Attribute 绑定

双大括号不能在 HTML attributes 中使用。想要响应式地绑定一个 attribute,应该使用 v-bind 指令

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

v-bind 指令指示 Vue 将元素的 id attribute 与组件的 dynamicId 属性保持一致。如果绑定的值是 null 或者 undefined,那么该 attribute 将会从渲染的元素上移除。

简写

因为 v-bind 非常常用,我们提供了特定的简写语法:

template

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

开头为 : 的 attribute 可能和一般的 HTML attribute 看起来不太一样,但它的确是合法的 attribute 名称字符,并且所有支持 Vue 的浏览器都能正确解析它。此外,他们不会出现在最终渲染的 DOM 中。简写语法是可选的,但相信在你了解了它更多的用处后,你应该会更喜欢它。

接下来的指引中,我们都将在示例中使用简写语法,因为这是在实际开发中更常见的用法。

布尔型 Attribute

布尔型 attribute 依据 true / false 值来决定 attribute 是否应该存在于该元素上。disabled 就是最常见的例子之一。

v-bind 在这种场景下的行为略有不同:

<button :disabled="isButtonDisabled">Button</button>

isButtonDisabled真值或一个空字符串 (即 ``) 时,元素会包含这个 disabled attribute。而当其为其他假值时 attribute 将被忽略。

动态绑定多个值

如果你有像这样的一个包含多个 attribute 的 JavaScript 对象:

const objectOfAttrs = {
  id: 'container',
  class: 'wrapper'
}

通过不带参数的 v-bind,你可以将它们绑定到单个元素上:

<div v-bind="objectOfAttrs"></div>

使用 JavaScript 表达式

至此,我们仅在模板中绑定了一些简单的属性名。但是 Vue 实际上在所有的数据绑定中都支持完整的 JavaScript 表达式:

{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

{{ message.split('').reverse().join('') }}

<div :id="`list-${id}`"></div>

这些表达式都会被作为 JavaScript ,以当前组件实例为作用域解析执行。

在 Vue 模板内,JavaScript 表达式可以被使用在如下场景上:

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

仅支持表达式

每个绑定仅支持单一表达式,也就是一段能够被求值的 JavaScript 代码。一个简单的判断方法是是否可以合法地写在 return 后面。

因此,下面的例子都是无效的:

<!-- 这是一个语句,而非表达式 -->
{{ var a = 1 }}

<!-- 条件控制也不支持,请使用三元表达式 -->
{{ if (ok) { return message } }}

调用函数

可以在绑定的表达式中使用一个组件暴露的方法:

<span :title="toTitleDate(date)">
  {{ formatDate(date) }}
</span>

指令 Directives

指令是带有 v- 前缀的特殊 attribute。Vue 提供了许多内置指令,包括上面我们所介绍的 v-bindv-html

指令 attribute 的期望值为一个 JavaScript 表达式 (除了少数几个例外,即之后要讨论到的 v-forv-onv-slot)。一个指令的任务是在其表达式的值变化时响应式地更新 DOM。以 v-if 为例:

<p v-if="seen">Now you see me</p>

这里,v-if 指令会基于表达式 seen 的值的真假来移除/插入该 `` 元素。

参数 Arguments

某些指令会需要一个“参数”,在指令名后通过一个冒号隔开做标识。例如用 v-bind 指令来响应式地更新一个 HTML attribute:

<a v-bind:href="url"> ... </a>

<!-- 简写 -->
<a :href="url"> ... </a>

这里 href 就是一个参数,它告诉 v-bind 指令将表达式 url 的值绑定到元素的 href attribute 上。在简写中,参数前的一切 (例如 v-bind:) 都会被缩略为一个 : 字符。

另一个例子是 v-on 指令,它将监听 DOM 事件:

<a v-on:click="doSomething"> ... </a>

<!-- 简写 -->
<a @click="doSomething"> ... </a>

这里的参数是要监听的事件名称:clickv-on 有一个相应的缩写,即 @ 字符。我们之后也会讨论关于事件处理的更多细节。

动态参数

同样在指令参数上也可以使用一个 JavaScript 表达式,需要包含在一对方括号内:

<!--
注意,参数表达式有一些约束,
参见下面“动态参数值的限制”与“动态参数语法的限制”章节的解释
-->
<a v-bind:[attributeName]="url"> ... </a>

<!-- 简写 -->
<a :[attributeName]="url"> ... </a>

这里的 attributeName 会作为一个 JavaScript 表达式被动态执行,计算得到的值会被用作最终的参数。举例来说,如果你的组件实例有一个数据属性 attributeName,其值为 "href",那么这个绑定就等价于 v-bind:href

相似地,你还可以将一个函数绑定到动态的事件名称上:

<a v-on:[eventName]="doSomething"> ... </a>

<!-- 简写 -->
<a @[eventName]="doSomething">

在此示例中,当 eventName 的值是 "focus" 时,v-on:[eventName] 就等价于 v-on:focus

动态参数值的限制

动态参数中表达式的值应当是一个字符串,或者是 null。特殊值 null 意为显式移除该绑定。其他非字符串的值会触发警告。

动态参数语法的限制

动态参数表达式因为某些字符的缘故有一些语法限制,比如空格和引号,在 HTML attribute 名称中都是不合法的。例如下面的示例:

<!-- 这会触发一个编译器警告 -->
<a :['foo' + bar]="value"> ... </a>

如果你需要传入一个复杂的动态参数,我们推荐使用计算属性替换复杂的表达式,也是 Vue 最基础的概念之一,我们很快就会讲到。

当使用 DOM 内嵌模板 (直接写在 HTML 文件里的模板) 时,我们需要避免在名称中使用大写字母,因为浏览器会强制将其转换为小写:

<a :[someAttr]="value"> ... </a>

上面的例子将会在 DOM 内嵌模板中被转换为 :[someattr]。如果你的组件拥有 “someAttr” 属性而非 “someattr”,这段代码将不会工作。单文件组件内的模板受此限制。

修饰符 Modifiers

修饰符是以点开头的特殊后缀,表明指令需要以一些特殊的方式被绑定。例如 .prevent 修饰符会告知 v-on 指令对触发的事件调用 event.preventDefault()

<form @submit.prevent="onSubmit">...</form>

之后在讲到 v-onv-model 的功能时,你将会看到其他修饰符的例子。

最后,在这里你可以直观地看到完整的指令语法:

指令语法图

响应式基础

事件和动态绑定

v-once 修饰的数据会不受响应式的影响,保持不变

@click 是 v-on:click 的语法糖,就是动态绑定事件

v-html 是将内容渲染为html代码,展示出来就是一个 h2的hello

<!--   msg = <h2>hello</h2>    -->
<p v-html="msg"></p>

选项式API

<script>
export default {
    data: function () {
        return {
            num: 0,
            uname: "张三"
        }
    },
    methods: {
        changeUname: function () {
            this.uname = '李四'
        }
    }
}
</script>

<template>
    <div>
        <p>{{ num }}</p>
        <button @click="num++">num++</button>
        <!--    数据随着uname改变动态修改    -->
        <p>{{ uname }}</p>
        <!--    v-once:当数据改变时,插值处的内容不会更新    -->
        <p v-once>{{ uname }}</p>
 		<!--    两种方式都可以修改uname    -->
        <button @click="changeUname">改变名字</button>
        <button @click="uname='李四'">改变名字</button>
    </div>
</template>

组合式API

<script setup>
import { ref } from 'vue'
const num = ref(0)
const uname = ref('张三')

function changeUname {
    this.uname = '李四'
}
</script>

<template>
    <div>
        <p>{{ num }}</p>
        <button @click="num++">num++</button>
        <!--    数据随着uname改变动态修改    -->
        <p>{{ uname }}</p>
        <!--    v-once:当数据改变时,插值处的内容不会更新    -->
        <p v-once>{{ uname }}</p>
 		<!--    两种方式都可以修改uname    -->
        <button @click="changeUname">改变名字</button>
        <button @click="uname='李四'">改变名字</button>
    </div>
</template>

v-bind 以及 v-on

选项式API

<script>
export default {
    data: function () {
        return {
            msg: '<h2>标题</h2>',
            img: 'http://static.runoob.com/images/demo/demo2.jpg',
            id: 'd1',
            attributeName: 'id',
            mouseEvent: 'click'
        }
    },
    methods: {
        changeUname: function () {
            this.uname = '李四'
        },
        changeId: function () {
            this.id = "d2"
        }
    }
}
</script>

<template>
    <div>
        <!--    v-html让内容以html展示    -->
        <p v-html="msg"></p>
        <!--    v-bing动态绑定属性    -->
        <img :src="img" alt="">
        <p :id="id">p标签</p>
        <button @click="changeId">修改颜色</button>
        <button @click="id='list'+'d1'">修改颜色</button>
        <!--    等价于上面的 @click    -->
        <button v-on:click="changeId">修改颜色</button>
        <!--    v-bing动态绑定属性id,将attributeName的值改为id的值    -->
        <p v-bind:[attributeName]="id">p标签</p>
        <button v-on:click="attributeName='class'">修改颜色</button>
        
        <!--    动态绑定事件,刚开始是click点击事件,点击修改事件按钮后就变成了悬浮事件    -->
        <button @[mouseEvent]="attributeName='id'">修改颜色</button>
        <button @click="mouseEvent='mouseover'">修改事件</button>
    </div>
</template>

<style>
#d1 {
    color: red;
}
#d2 {
    color: blue;
}
.d1 {
    color: yellow;
}
</style>

组合式API

<script setup>
import { ref } from 'vue'
const msg = ref('<h2>标题</h2>')
const img = ref('http://static.runoob.com/images/demo/demo2.jpg')
const id = ref('d1'),
const attributeName = ref('id')
const mouseEvent = ref('click')

function changeId () {
    this.id = "d2"
}
</script>

<template>
    <div>
        <!--    v-html让内容以html展示    -->
        <p v-html="msg"></p>
        <!--    v-bing动态绑定属性    -->
        <img :src="img" alt="">
        <p :id="id">p标签</p>
        <button @click="changeId">修改颜色</button>
        <button @click="id='list'+'d1'">修改颜色</button>
        <!--    等价于上面的 @click    -->
        <button v-on:click="changeId">修改颜色</button>
        <!--    v-bing动态绑定属性id,将attributeName的值改为id的值    -->
        <p v-bind:[attributeName]="id">p标签</p>
        <button v-on:click="attributeName='class'">修改颜色</button>
        
        <!--    动态绑定事件,刚开始是click点击事件,点击修改事件按钮后就变成了悬浮事件    -->
        <button @[mouseEvent]="attributeName='id'">修改颜色</button>
        <button @click="mouseEvent='mouseover'">修改事件</button>
    </div>
</template>

<style>
#d1 {
    color: red;
}
#d2 {
    color: blue;
}
.d1 {
    color: yellow;
}
</style>

参考文档

参考链接:vue官网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值