学Vue3这一篇就够了!

news/2024/5/3 19:06:36/文章来源:https://blog.csdn.net/weixin_53333752/article/details/129967110

目录

  • 学习Vue的前提是掌握 HTML,CSS,Js中级知识
  • vue介绍
    • 声明式渲染
    • 条件与循环
    • 处理用户输入
    • 组件化应用构建
      • Vue与自定义元素的关系
  • 应用和组件实例
    • Vue实例
    • 根组件
    • 组件实例 property
    • 生命周期钩子
    • 实例的生命周期图
  • 模板语法
    • 插值
      • 文本
      • 原始 HTML
      • Attribute
      • 使用 JavaScript 表达式
    • 指令
      • 参数
      • 动态参数
      • 修饰符
    • 缩写
      • v-bind 缩写
      • v-on 缩写
  • Data Property 和方法
    • Data Property
  • 方法
      • 防抖和节流
  • 计算属性和侦听器
    • 计算属性
      • 计算属性缓存 vs 方法
    • 计算属性的 Setter
    • 侦听器
      • 计算属性 vs 侦听器
  • Class 与 Style 绑定
    • 绑定 HTML Class
      • 对象语法
      • 数组语法
      • 在组件上使用
    • 绑定内联样式
      • 对象语法
      • 数组语法
      • 多重值
  • 条件渲染
    • v-if
    • v-show
    • v-if vs v-show
  • 列表渲染
    • v-for
    • 维护状态
    • 显示过滤/排序后的结果
  • 事件处理
    • 多事件处理器
    • 按键修饰符
      • .exact 修饰符
      • 鼠标按钮修饰符
  • 表单输入绑定
    • 复选框 (Checkbox)
      • 单选框(radio)
  • 值绑定
    • 修饰符
      • .lazy
      • .number
      • .trim
  • 组件基础
    • 通过 Prop 向子组件传递数据
    • 功能快捷

学习Vue的前提是掌握 HTML,CSS,Js中级知识

vue介绍

Vue是一套用于构建用户界面的渐进式框架
(渐进式框架允许用最小的配置和功能逐渐添加更多的功能和插件)

声明式渲染

Vue的核心是一个允许采用简洁的模板语法来声明式的将数据渲染进DOM的系统

//test.html
<div id="app">{{ message }}
</div>//test.js
var app = new Vue({el: '#app',data: {message: 'Hello Vue!'}})//现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。//打开你的浏览器的 JavaScript 控制台,并修改 app.message 的值,你将看到上例相应地更新
//test.html
<div id="app-2"><span v-bind:title="message">鼠标悬停几秒钟查看此处动态绑定的提示信息!</span>
</div>
//test.js
var app2 = new Vue({el: '#app-2',data: {message: '页面加载于 ' + new Date().toLocaleString()}})
//   v-bind 被称为指令,指令带有前缀 v-,以表示它们是 Vue 提供的特殊 attribute(属性
//   它们会在渲染的 DOM 上应用特殊的响应式行为,在这里,该指令的意思是:“将这个元素节点的 title attribute 和 Vue 实例的 message property 保持一致”。
//   再次打开浏览器的 JavaScript 控制台,输入 app2.message = '新消息',就会再一次看到这个绑定了 title attribute 的 HTML 已经进行了更新

条件与循环

//test.html
<div id="app-3"><p v-if="seen">现在你看到我了</p>
</div>
//test.js
var app3 = new Vue({el: '#app-3',data: {seen: true}})
//在控制台输入 app3.seen = false,你会发现之前显示的消息消失了
//test.html
<div id="app-4"><ol><li v-for="todo in todos">{{ todo.text }}</li></ol>
</div>
//test.js
var app4 = new Vue({el: '#app-4',data: {todos: [{ text: '学习 JavaScript' },{ text: '学习 Vue' },{ text: '整个牛项目' }]}})//在控制台里,输入 app4.todos.push({ text: '新项目' }),你会发现列表最后添加了一个新项目。

v-for 指令可以绑定数组的数据来渲染一个项目列表

处理用户输入

可以用 v-on 指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法

//test.html
<div id="app-5"><p>{{ message }}</p><button v-on:click="reverseMessage">反转消息</button>
</div>
//test.js
var app5 = new Vue({el: '#app-5',data: {message: 'Hello Vue.js!'},methods: {reverseMessage: function () {this.message = this.message.split('').reverse().join('')}}})//在 reverseMessage 方法中,我们更新了应用的状态,但没有触碰 DOM——所有的 DOM 操作都由 Vue 来处理,你编写的代码只需要关注逻辑层面即可

Vue 还提供了 v-model 指令,它能轻松实现表单输入和应用状态之间的双向绑定。

//test.html
<div id="app-6"><p>{{ message }}</p><input v-model="message"></input>
</div>
//test.js
var app6 = new Vue({el: '#app-6',data: {message: 'Hello Vue!'}
})

组件化应用构建

组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。几乎任意类型的应用界面都可以抽象为一个组件树
在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例。

// 定义名为 todo-item 的新组件
Vue.component('todo-item', {template: '<li>这是个待办项</li>'
})var app = new Vue(...)
//现在你可以用它构建另一个组件模板:
<ol><!-- 创建一个 todo-item 组件的实例 --><todo-item></todo-item>
</ol>
但是这样会为每个待办项渲染同样的文本,
我们应该能从父作用域将数据传到子组件才对。
可以修改一下组件的定义,使之能够接受一个 prop:
Vue.component('todo-item', {// todo-item 组件现在接受一个// "prop",类似于一个自定义 attribute。// 这个 prop 名为 todo。props: ['todo'],template: '<li>{{ todo.text }}</li>'
})

可以使用 v-bind 指令将待办项传到循环输出的每个组件中:

//test.html
<div id="app-7"><ol><!--现在我们为每个 todo-item 提供 todo 对象todo 对象是变量,即其内容可以是动态的。我们也需要为每个组件提供一个“key”,稍后再作详细解释。--><todo-itemv-for="item in groceryList"v-bind:todo="item"v-bind:key="item.id"></todo-item></ol>
</div>
//test.js
Vue.component('todo-item', {props: ['todo'],template: '<li>{{ todo.text }}</li>'})var app7 = new Vue({el: '#app-7',data: {groceryList: [{ id: 0, text: '猫' },{ id: 1, text: '狗' },{ id: 2, text: '为什么不能狗在前面' }]}})

在一个大型应用中,有必要将整个应用程序划分为组件,以使开发更易管理。在后续教程中我们将详述组件,不过这里有一个 (假想的) 例子,以展示使用了组件的应用模板是什么样的:

<div id="app"><app-nav></app-nav><app-view><app-sidebar></app-sidebar><app-content></app-content></app-view>
</div>

Vue与自定义元素的关系

Vue 组件非常类似于自定义元素——它是 Web 组件规范的一部分,这是因为 Vue 的组件语法部分参考了该规范。例如 Vue 组件实现了 Slot API 与 is attribute.
虽然 Vue 内部没有使用自定义元素,不过在应用使用自定义元素、或以自定义元素形式发布时,依然有很好的互操作性。Vue CLI 也支持将 Vue 组件构建成为原生的自定义元素。

应用和组件实例

Vue实例

每个 Vue 应用都是通过用 createApp 函数创建一个新的应用实例开始的:

const app = Vue.createApp({ /* 选项 */ })
app.component('SearchInput', SearchInputComponent)
app.directive('focus', FocusDirective)
app.use(LocalePlugin)
该应用实例是用来在应用中注册“全局”组件的。
我们将在后面的指南中详细讨论,

应用实例暴露的大多数方法都会返回该同一实例,允许链式

Vue.createApp({}).component('SearchInput', SearchInputComponent).directive('focus', FocusDirective).use(LocalePlugin)

根组件

传递给 createApp 的选项用于配置根组件。当我们挂载应用时,该组件被用作渲染的起点

一个应用需要被挂载到一个 DOM 元素中。例如,如果我们想把一个 Vue 应用挂载到 <div id="app"></div>
,我们应该传递 #app:
const RootComponent = { /* 选项 */ }
const app = Vue.createApp(RootComponent)
const vm = app.mount('#app')
与大多数应用方法不同的是,mount 不返回应用本身。
相反,它返回的是根组件实例

虽然没有完全遵循 MVVM 模型 (opens new window),但是 Vue 的设计也受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的缩写) 这个变量名表示组件实例。
尽管本页面上的所有示例都只需要一个单一的组件就可以,但是大多数的真实应用都是被组织成一个嵌套的、可重用的组件树。举个例子,一个 todo 应用组件树可能是这样的:
在这里插入图片描述每个组件将有自己的组件实例 vm。对于一些组件,如 TodoItem,在任何时候都可能有多个实例渲染。这个应用中的所有组件实例将共享同一个应用实例。
现在,你只需要明白根组件与其他组件没什么不同,配置选项是一样的,所对应的组件实例行为也是一样的

组件实例 property

在 data 中定义的 property 是通过组件实例暴露的:

const app = Vue.createApp({data() {return { count: 4 }}
})const vm = app.mount('#app')console.log(vm.count) // => 4

还有各种其他的组件选项,可以将用户定义的 property 添加到组件实例中,例如 methods,props,computed,inject 和 setup。
组件实例的所有 property,无论如何定义,都可以在组件的模板中访问。

Vue 还通过组件实例暴露了一些内置 property,如 $attrs 和 $emit。这些 property 都有一个 $ 前缀,以避免与用户定义的 property 名冲突。

生命周期钩子

每个组件在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

比如 created 钩子可以用来在一个实例被创建之后执行代码:

Vue.createApp({data() {return { count: 1}},created() {// `this` 指向 vm 实例console.log('count is: ' + this.count) // => "count is: 1"}
})

也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mounted、updated 和 unmounted。生命周期钩子的 this 上下文指向调用它的当前活动实例。
不要在选项 property 或回调上使用箭头函数,比如 created: () => console.log(this.a) 或 vm.$watch(‘a’, newValue => this.myMethod())。因为箭头函数并没有 this,this 会作为变量一直向上级词法作用域查找,直至找到为止,经常导致 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之类的错误。

实例的生命周期图

不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。
在这里插入图片描述

模板语法

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层组件实例的数据。所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。
在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应性系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。

如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,直接写渲染 (render) 函数,使用可选的 JSX 语法。

插值

文本

数据绑定最常见的形式就是使用“Mustache”(双大括号) 语法的文本插值:

<span>Message: {{ msg }}</span>
无论何时,绑定的组件实例上 msg 属性发生了改变,插值处的内容都会更新。

原始 HTML

双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用v-html 指令:
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

这个 span 的内容将会被替换成为 property 值 rawHtml,直接作为 HTML——会忽略解析 property 值中的数据绑定。注意,你不能使用 v-html 来复合局部模板,因为 Vue 不是基于字符串的模板引擎。反之,对于用户界面 (UI),组件更适合作为可重用和可组合的基本单位。

在你的站点上动态渲染任意的 HTML 是非常危险的,因为它很容易导致 XSS 攻击 (opens new window)。请只对可信内容使用 HTML 插值,绝不要将用户提供的内容作为插值。

Attribute

Mustache 语法不能在 HTML attribute 中使用 ,然而,可以使用 v-bind 指令:

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

对于布尔 attribute (它们只要存在就意味着值为 true),v-bind 工作起来略有不同,

<button v-bind:disabled="isButtonDisabled">按钮</button>
如果 isButtonDisabled 的值是 nullundefined,则 disabled attribute 甚至不会被包含在渲染出来的 <button> 元素中

使用 JavaScript 表达式

对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。每个绑定都只能包含单个表达式

指令

指令 (Directives) 是带有 v- 前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式 (v-for 和 v-on 是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。回顾我们在介绍中看到的例子:

<p v-if="seen">现在你看到我了</p>
v-if 指令将根据表达式 seen 的值的真假来插入/移除 <p> 元素。

参数

一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind 指令可以用于响应式地更新 HTML

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

v-on 指令,它用于监听 DOM 事件:

<a v-on:click="doSomething"> ... </a>
这里参数是监听的事件名。我们也会更详细地讨论事件处理

动态参数

可以在指令参数中使用 JavaScript 表达式,方法是用方括号括起来

<a v-bind:[attributeName]="url"> ... </a>
这里的 attributeName 会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,如果你的组件实例有一个 data property attributeName,其值为 "href",那么这个绑定将等价于 v-bind:href。

还可以使用动态参数为一个动态的事件名绑定处理函数:

<a v-on:[eventName]="doSomething"> ... </a>
当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus

修饰符

修饰符 (modifier) 是以半角句号.指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。

<form v-on:submit.prevent="onSubmit">...</form>
.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()

缩写

v-bind: (属性绑定)简写为 :
v-on : (事件绑定)简写为 @
v-model(双向绑定)

v-bind 缩写

v-bind的基本用法是动态更新HTML元素上的属性,如id,class,href,src等。

<!-- 完整语法 -->
<a v-bind:href="url"> ... </a><!-- 缩写 -->
<a :href="url"> ... </a><!-- 动态参数的缩写 -->
<a :[key]="url"> ... </a>

v-on 缩写

<!-- 完整语法 -->
<a v-on:click="doSomething"> ... </a><!-- 缩写 -->
<a @click="doSomething"> ... </a><!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>

: 与 @ 对于 attribute 名来说都是合法字符,在所有支持 Vue 的浏览器都能被正确地解析。而且,它们不会出现在最终渲染的标记中。缩写语法是完全可选的

之后将在示例中使用缩写,因为这是 Vue 开发者最常用的用法。

Data Property 和方法

Data Property

组件的 data 选项是一个函数。它应该返回一个对象,然后 Vue 会通过响应性系统将其包裹起来,并以 $data 的形式存储在组件实例中。该对象的任何顶级 property 也直接通过组件实例暴露出来:

const app = Vue.createApp({data() {return { count: 4 }}
})const vm = app.mount('#app')console.log(vm.$data.count) // => 4
console.log(vm.count)       // => 4// 修改 vm.count 的值也会更新 $data.count
vm.count = 5
console.log(vm.$data.count) // => 5// 反之亦然
vm.$data.count = 6
console.log(vm.count) // => 6

这些实例 property 仅在实例首次创建时被添加,所以你需要确保它们都在 data 函数返回的对象中。必要时,要对尚未提供所需值的 property 使用 null、undefined 或其他占位的值。。

Vue 使用 $ 前缀通过组件实例暴露自己的内置 API。它还为内部 property 保留 _ 前缀。避免使用这两个字符开头的的顶级 data property 名称

方法

用 methods 选项向组件实例添加方法,它应该是一个包含所需方法的对象:

const app = Vue.createApp({data() {return { count: 4 }},methods: {increment() {// `this` 指向该组件实例this.count++}}
})const vm = app.mount('#app')console.log(vm.count) // => 4vm.increment()console.log(vm.count) // => 5

这些 methods 和组件实例的其它所有 property 一样可以在组件的模板中被访问。在模板中,它们通常被当做事件监听使用:

<button @click="increment">Up vote</button>
点击 <button> 时,会调用 increment 方法。

从模板调用的方法不应该有任何副作用,比如更改数据或触发异步进程。如果想这么做,应该换做生命周期钩子

防抖和节流

Vue 没有内置支持防抖和节流,但可以使用 Lodash (opens new window) 等库来实现

如果某个组件仅使用一次,可以在 methods 中直接应用防抖:

<script src="https://unpkg.com/lodash@4.17.20/lodash.min.js"></script>
<script>Vue.createApp({methods: {// 用 Lodash 的防抖函数click: _.debounce(function() {// ... 响应点击 ...}, 500)}}).mount('#app')
</script>

但是,这种方法对于可复用组件有潜在的问题,因为它们都共享相同的防抖函数。为了使组件实例彼此独立,可以在生命周期钩子的 created 里添加该防抖函数:

app.component('save-button', {created() {// 用 Lodash 的防抖函数this.debouncedClick = _.debounce(this.click, 500)},unmounted() {// 移除组件时,取消定时器this.debouncedClick.cancel()},methods: {click() {// ... 响应点击 ...}},template: `<button @click="debouncedClick">Save</button>`
})

计算属性和侦听器

计算属性

对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性。

//.html
<div id="computed-basics"><p>Has published books:</p><span>{{ publishedBooksMessage }}</span>
</div>
//.js
Vue.createApp({data() {return {author: {name: 'John Doe',books: ['Vue 2 - Advanced Guide','Vue 3 - Basic Guide','Vue 4 - The Mystery']}}},computed: {// 计算属性的 getterpublishedBooksMessage() {// `this` 指向 vm 实例return this.author.books.length > 0 ? 'Yes' : 'No'}}
}).mount('#computed-basics')
这里声明了一个计算属性 publishedBooksMessage。尝试更改应用程序 data 中 books 数组的值,你将看到 publishedBooksMessage 如何相应地更改
可以像普通属性一样将数据绑定到模板中的计算属性。Vue 知道 vm.publishedBookMessage 依赖于 vm.author.books,因此当 vm.author.books 发生改变时,所有依赖 vm.publishedBookMessage 绑定也会更新。而且最妙的是我们已经声明的方式创建了这个依赖关系:计算属性的 getter 函数没有副作用,这使得更易于测试和理解。

计算属性缓存 vs 方法

我们可以通过在表达式中调用方法来达到同样的效果:

//.html
<p>{{ calculateBooksMessage() }}</p>//.js
// 在组件中
methods: {calculateBooksMessage() {return this.author.books.length > 0 ? 'Yes' : 'No'}
}
可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。
然而,不同的是计算属性是基于它们的反应依赖关系缓存的。
计算属性只在相关响应式依赖发生改变时它们才会重新求值。
这就意味着只要 author.books 还没有发生改变,
多次访问 publishedBookMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

计算属性的 Setter

计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:

computed: {fullName: {// getterget() {return this.firstName + ' ' + this.lastName},// setterset(newValue) {const names = newValue.split(' ')this.firstName = names[0]this.lastName = names[names.length - 1]}}
}

侦听器

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。

//.html
<div id="watch-example"><p>Ask a yes/no question:<input v-model="question" /></p><p>{{ answer }}</p>
</div>
//.js
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script>const watchExampleVM = Vue.createApp({data() {return {question: '',answer: 'Questions usually contain a question mark. ;-)'}},watch: {// whenever question changes, this function will runquestion(newQuestion, oldQuestion) {if (newQuestion.indexOf('?') > -1) {this.getAnswer()}}},methods: {getAnswer() {this.answer = 'Thinking...'axios.get('https://yesno.wtf/api').then(response => {this.answer = response.data.answer}).catch(error => {this.answer = 'Error! Could not reach the API. ' + error})}}}).mount('#watch-example')
</script>
使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,
并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

计算属性 vs 侦听器

Vue 提供了一种更通用的方式来观察和响应当前活动的实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。

//.html
<div id="demo">{{ fullName }}</div>
//.js
const vm = Vue.createApp({data() {return {firstName: 'Foo',lastName: 'Bar',fullName: 'Foo Bar'}},watch: {firstName(val) {this.fullName = val + ' ' + this.lastName},lastName(val) {this.fullName = this.firstName + ' ' + val}}
}).mount('#demo')

上面代码是命令式且重复的。将它与计算属性的版本进行比较:

const vm = Vue.createApp({data() {return {firstName: 'Foo',lastName: 'Bar'}},computed: {fullName() {return this.firstName + ' ' + this.lastName}}
}).mount('#demo')

Class 与 Style 绑定

操作元素的 class 列表和内联样式是数据绑定的一个常见需求。
它们都是 attribute,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。

绑定 HTML Class

对象语法

我们可以传给 :class (v-bind:class 的简写) 一个对象,以动态地切换 class:

//.html
<div :class="{ active: isActive }"></div>
表示 active 这个 class 存在与否将取决于数据 property isActive 的 truthiness 

:class 指令也可以与普通的 class attribute 共存

数组语法

可以把一个数组传给 :class,以应用一个 class 列表:

//.html
<div :class="[activeClass, errorClass]"></div>//.js
data() {return {activeClass: 'active',errorClass: 'text-danger'}
}
如果你想根据条件切换列表中的 class,可以使用三元表达式:
<div :class="[isActive ? activeClass : '', errorClass]"></div>在数组语法中也可以使用对象语法:
<div :class="[{ active: isActive }, errorClass]"></div>

在组件上使用

当你在带有单个根元素的自定义组件上使用 class attribute 时,这些 class 将被添加到该元素中。此元素上的现有 class 将不会被覆盖。

//.html
<div id="app"><my-component class="baz boo"></my-component>
</div>
//.js
const app = Vue.createApp({})app.component('my-component', {template: `<p class="foo bar">Hi!</p>`
})
渲染结果:<p class="foo bar baz boo">Hi</p>
对于带数据绑定 class 也同样适用:<my-component :class="{ active: isActive }"></my-component>
当 isActive 为 truthy[1] 时,HTML 将被渲染成为:<p class="foo bar active">Hi</p>

如果你的组件有多个根元素,你需要定义哪些部分将接收这个类。可以使用 $attrs 组件属性执行此操作

//.html
<div id="app"><my-component class="baz"></my-component>
</div>
//.js
const app = Vue.createApp({})app.component('my-component', {template: `<p :class="$attrs.class">Hi!</p><span>This is a child component</span>`
}

绑定内联样式

对象语法

:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case

//.html
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
直接绑定到一个样式对象通常更好,这会让模板更清晰:
<div :style="styleObject"></div>
//.js
data() {return {styleObject: {color: 'red',fontSize: '13px'}}
}
对象语法常常结合返回对象的计算属性使用

数组语法

:style 的数组语法可以将多个样式对象应用到同一个元素上:

<div :style="[baseStyles, overridingStyles]"></div>

在 :style 中使用需要 (浏览器引擎前缀) vendor prefixes(opens new window) 的 CSS property 时,如 transform,Vue 将自动侦测并添加相应的前缀。

多重值

可以为 style 绑定中的 property 提供一个包含多个值的数组,常用于提供多个带前缀的值

这样写只会渲染数组中最后一个被浏览器支持的值。
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex

条件渲染

v-if

v-if指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。**

<div v-if="type === 'A'"></div>
<div v-else-if="type === 'B'"></div>
<div v-else-if="type === 'C'"></div>
<div v-else>Not A/B/C</div>

v-show

<h1 v-show="ok">Hello!</h1>

不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS property display。

注意,v-show 不支持 元素,也不支持 v-else

v-if vs v-show

v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块

v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好

不推荐同时使用 v-if 和 v-for,当 v-if 与 v-for 一起使用时,v-if 具有比 v-for 更高的优先级

列表渲染

v-for

用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。

v-for你也可以提供第二个的参数为 property 名称 (也就是键名 key):还可以用第三个参数作为索引

//.html
<li v-for="(value, name, index) in myObject">{{ index }}. {{ name }}: {{ value }}
</li>//.js
Vue.createApp({data() {return {myObject: {title: 'How to do lists in Vue',author: 'Jane Doe',publishedAt: '2016-04-10'}}}
}).mount('#v-for-object')

可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:

<div v-for="item of items"></div>

维护状态

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute:

<div v-for="item in items" :key="item.id"><!-- content -->
</div>

建议尽可能在使用 v-for 时提供 key attribute
不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。

显示过滤/排序后的结果

有时想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。

//.html
<li v-for="n in evenNumbers">{{ n }}</li>
//.js
data() {return {numbers: [ 1, 2, 3, 4, 5 ]}
},
computed: {evenNumbers() {return this.numbers.filter(number => number % 2 === 0)}
}

在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个方法:

//.html
<ul v-for="numbers in sets"><li v-for="n in even(numbers)">{{ n }}</li>
</ul>
//.js
data() {return {sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]}
},
methods: {even(numbers) {return numbers.filter(number => number % 2 === 0)}
}

类似于 v-if,你也可以利用带有 v-for 的 来循环渲染一段包含多个元素的内容。比如:

<ul><template v-for="item in items"><li>{{ item.msg }}</li><li class="divider" role="presentation"></li></template>
</ul>

不推荐在同一元素上使用 v-if 和 v-for

当它们处于同一节点,v-if 的优先级比 v-for 更高,这意味着 v-if 将没有权限访问 v-for 里的变量

可以把 v-for 移动到 标签中来修正:

<template v-for="todo in todos"><li v-if="!todo.isComplete">{{ todo }}</li>
</template>

在自定义组件上,你可以像在任何普通元素上一样使用 v-for
然而,任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要使用 props:

<my-componentv-for="(item, index) in items":item="item":index="index":key="item.id"
></my-component>

不自动将 item 注入到组件里的原因是,这会使得组件与 v-for 的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。

事件处理

使用 v-on 指令 (通常缩写为 @ 符号) 来监听 DOM 事件,并在触发事件时执行一些 JavaScript。用法为 v-on:click=“methodName” 或使用快捷方式 @click=“methodName”

v-on 还可以接收一个需要调用的方法名称。

//.html
<div id="event-with-method"><!-- `greet` 在下面定义的方法名 --><button @click="greet">Greet</button>
</div>
//.js
Vue.createApp({data() {return {name: 'Vue.js'}},methods: {greet(event) {// `this` 内部 `methods` 指向当前活动实例alert('Hello ' + this.name + '!')// `event` 是原生 DOM eventif (event) {alert(event.target.tagName)}}}
}).mount('#event-with-method')

也可以在内联 JavaScript 语句中调用方法

<div id="inline-handler"><button @click="say('hi')">Say hi</button><button @click="say('what')">Say what</button>
</div>
//.js
Vue.createApp({methods: {say(message) {alert(message)}}
}).mount('#inline-handler')

有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法:

//.html
<button @click="warn('Form cannot be submitted yet.', $event)">Submit
</button>
//.js
methods: {warn(message, event) {// now we have access to the native eventif (event) {event.preventDefault()}alert(message)}
}

多事件处理器

//.html
<button @click="one($event), two($event)">Submit
</button>
//.js
methods: {one(event) {//},two(event) {//}
}

在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

//.html
!-- 阻止单击事件继续传播 -->
<a @click.stop="doThis"></a><!-- 提交事件不再重载页面 -->
<form @submit.prevent="onSubmit"></form><!-- 修饰符可以串联 -->
<a @click.stop.prevent="doThat"></a><!-- 只有修饰符 -->
<form @submit.prevent></form><!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div @click.capture="doThis">...</div><!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div @click.self="doThat">...</div>

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
不像其它只能对原生的 DOM 事件起作用的修饰符,.once 修饰符还能被用到自定义的组件事件上。如果你还没有阅读关于组件的文档,现在大可不必担心。
不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你不想阻止事件的默认行为。

按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 或者 @ 在监听键盘事件时添加按键修饰符:

<!-- 只有在 `key``Enter` 时调用 `vm.submit()` -->
<input @keyup.enter="submit" />
可以直接将 KeyboardEvent.key (opens new window) 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。
<input @keyup.page-down="onPageDown" />
处理函数只会在 $event.key 等于 'PageDown' 时被调用

Vue 为最常用的键提供了别名:

.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right

可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。

.ctrl
.alt
.shift
.meta

在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。

.exact 修饰符

.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button><!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button><!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

鼠标按钮修饰符

.left
.right
.middle

这些修饰符会限制处理函数仅响应特定的鼠标按钮

表单输入绑定

用v-model指令在表单,,元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素
v-model本质上只是语法糖,负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。

v-model会忽略所有的表单元素的value,checked,selected的初始值而总是将当前活动实例的数据作为数据来源,通过js在组件的data选项中声明初始值
v-model在内部为不同的输入元素使用不同的property并抛出不同的事件:
text和textarea元素使用value property和inout事件
checkbox和radio使用checked property和change事件
select字段将value作为prop并将change作为事件

v-model 不会在输入法组织文字过程中得到更新。如果你也想处理这个过程,请使用 input 事件。

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

复选框 (Checkbox)

//单个复选框
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>
//多个复选框
<div id="v-model-multiple-checkboxes"><input type="checkbox" id="jack" value="Jack" v-model="checkedNames" /><label for="jack">Jack</label><input type="checkbox" id="john" value="John" v-model="checkedNames" /><label for="john">John</label><input type="checkbox" id="mike" value="Mike" v-model="checkedNames" /><label for="mike">Mike</label><br /><span>Checked names: {{ checkedNames }}</span>
</div>
//.js
Vue.createApp({data() {return {checkedNames: []}}
}).mount('#v-model-multiple-checkboxes')

单选框(radio)

//.html
<div id="v-model-radiobutton"><input type="radio" id="one" value="One" v-model="picked" /><label for="one">One</label><br /><input type="radio" id="two" value="Two" v-model="picked" /><label for="two">Two</label><br /><span>Picked: {{ picked }}</span>
</div>
//.js
Vue.createApp({data() {return {picked: ''}}
}).mount('#v-model-radiobutton')

值绑定

对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值)

<!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" value="a" /><!-- `toggle`truefalse -->
<input type="checkbox" v-model="toggle" /><!-- 当选中第一个选项时,`selected` 为字符串 "abc" -->
<select v-model="selected"><option value="abc">ABC</option>
</select>

有时我们可能想把值绑定到当前活动实例的一个动态 property 上,这时可以用 v-bind 实现,此外,使用 v-bind 可以将输入值绑定到非字符串

修饰符

.lazy

在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步
可以添加 lazy 修饰符,从而转为在 change 事件_之后_进行同步

<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" />

.number

自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:

<input v-model.number="age" type="number" />

.trim

自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符

<input v-model.trim="msg" />

组件基础

创建一个 Vue 组件的示例:

// 创建一个Vue 应用
const app = Vue.createApp({})// 定义一个名为 button-counter 的新全局组件
app.component('button-counter', {data() {return {count: 0}},template: `<button @click="count++">You clicked me {{ count }} times.</button>`
})

在典型的 Vue 应用程序中,我们使用单个文件组件而不是字符串模板
可以将组件进行任意次数的复用,每用一次组件,就会有一个它的新实例被创建
通常一个应用会以一颗嵌套的组件树来组织,例如,可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。至此,我们的组件都只是通过 component 全局注册的:

const app = Vue.createApp({})app.component('my-component-name', {// ... 选项 ...
})

通过 Prop 向子组件传递数据

Prop 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个 property。为了给博文组件传递一个标题,我们可以用一个 props 选项将其包含在该组件可接受的 prop 列表中:

//.html
<div id="blog-post-demo" class="demo">
//prop 被注册之后,你就可以像这样把数据作为一个自定义 attribute 传递进来<blog-post title="My journey with Vue"></blog-post><blog-post title="Blogging with Vue"></blog-post><blog-post title="Why Vue is so fun"></blog-post>
</div>
//.js
const app = Vue.createApp({})
app.component('blog-post', {
//一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 propprops: ['title'],template: `<h4>{{ title }}</h4>`
})app.mount('#blog-post-demo')

功能快捷

撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
TOC语法后生成一个完美的目录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_283616.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux驱动开发——字符设备

目录 Linux设备分类 字符设备驱动基础 字符设备驱动框架 虚拟串口设备 Linux设备分类 Linux系统根据驱动程序实现的模型框架将设备驱动分为下面三种。 (1)字符设备驱动:设备对数据的处理是按照字节流的形式进行的&#xff0c;可以支持随机访问&#xff0c;也可以不支持随…

抽象类,接口

抽象类&#xff1a;当父类的某些方法&#xff0c;需要声明&#xff0c;但是又不确定如何实现时&#xff0c;可以将其声明为抽象方法&#xff0c;那么这个类就是抽象类。 package com.hspedu.abstract_;public class Abstract01 {public static void main(String[] args) {} } a…

Linux 操作系统原理 — PCIe 总线标准

目录 文章目录目录总线系统PCIe 总线PCIe 总线的传输速率PCIe 总线的架构PCIe 外设PCIe 设备的枚举过程PCIe 设备的编址方式BDF&#xff08;Bus-Device-Function&#xff09;编号BAR&#xff08;Base Address Register&#xff09;地址Linux 上的 PCIe 设备查看 PCIe 设备的 BD…

算法强化--两数之和

hi,大家好,今天为大家带来一道题目,求两数之和 题目 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一…

Python 进阶指南(编程轻松进阶):三、使用 Black 工具来格式化代码

原文&#xff1a;http://inventwithpython.com/beyond/chapter3.html 代码格式化是将一组规则应用于源代码&#xff0c;从而使得代码风格能够简洁统一。虽然代码格式对解析程序的计算机来说不重要&#xff0c;但代码格式对于可读性是至关重要的&#xff0c;这是维护代码所必需的…

【剑指offer|4.从尾到头打印单链表】

0.从尾到头打印单链表 单链表&#xff1a;一般给的都是无头节点的 另外&#xff1a;在面试中&#xff0c;如果我们打算修改输入的数据&#xff0c;则最好问一下面试官是不是允许修改 下面这种先把链表节点的值按链表序放到数组中&#xff0c;然后来一个算法库中的reverse属实有…

一文懂KL散度KL Divergence

本文翻译自https://naokishibuya.medium.com/demystifying-kl-divergence-7ebe4317ee68 KL散度中的KL全称是Kullback-Leibler&#xff0c;分别表示Solomon Kullback和Richard A.Leibler这两个人。 一、KL散度的定义 KL散度表明概率分布Q和概率分布P之间的相似性&#xff0c;由…

ARM Linux 内核启动1 —— 汇编阶段

一、Makefile分析 1、Makefile 分析 (1) kernel 的 Makefile 写法和规则等&#xff0c;和 uboot 的 Makefile 是一样的&#xff0c;甚至 Makefile 中的很多内容都是一样的。 (2) kernel 的 Makefile 比 uboot 的 Makefile 要复杂&#xff0c;这里我们并不会一行一行的详细分析…

【20】核心易中期刊推荐——计算机科学电子通信(EI索引)

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…

进阶C语言:文件操作

文件操作不仅仅是我们使用鼠标用来操作文件的各项功能&#xff0c;还可以使用C语言来操作文件的内容&#xff0c;可以使用C语言来对文件的读、写、拷贝...等等&#xff0c;话不多说&#xff0c;直接开始&#xff1a; 目录 1.为什么要使用文件 2.什么是文件 2.1程序文件 2.…

蓝桥杯【第14届省赛】Python B组

本题解不一定正确&#xff0c;欢迎大家指正 A&#xff1a;2023 【问题描述】 请求出在 12345678 至 98765432 中&#xff0c;有多少个数中完全不包含 2023 。 完全不包含 2023 是指无论将这个数的哪些数位移除都不能得到 2023 。 例如 20322175&#xff0c;33220022 都完全不包…

python实现获取当前目录下的树形结构

python实现获取当前目录下的树形结构 程序实现 在有些Linux上自带了tree命令来一树状结构显示一个目录&#xff0c;但是在有些linux上没有自带这个程序&#xff0c;所以这里用python写了一个小程序来实现这个功能&#xff0c;代码如下&#xff1a; import osdef print_tree(…

共模电感(扼流圈) 差模电感(扼流圈)

共模电感 共模电感&#xff0c;也叫共模扼流圈。常用于电脑的开关电源&#xff0c;过滤共模的电磁干扰信号。 共模电感器由软磁铁芯&#xff08;铁氧体磁芯&#xff09;和两组同相绕制的线圈组成。对于共模信号&#xff0c;由于两组线圈产生的磁场不是抵消。而是相互叠加&…

存量市场之下,电商之战深入腹地且逻辑未变

纵然是在流量依然见顶的大背景下&#xff0c;电商行业的竞争并未结束。无论是以百亿补贴为代表的烧钱策略&#xff0c;还是以跨境出海为代表的规模策略&#xff0c;几乎都是这样一种现象的直接体现。种种迹象表明&#xff0c;未来的电商行业&#xff0c;依然会有新的战役发生。…

Hadoop集群环境搭建与应用回顾

文章目录一、 实训项目名称二、 学习情况小结三、 项目中用到的知识点四、 实训项目中负责功能板块五、 实训项目实现六、 实训项目过程中遇到的问题及解决方法七、实训体会与心得一、 实训项目名称 Hadoop集群环境搭建与应用 二、 学习情况小结 实操一部分&#xff1a; 通…

linux 服务器 docker 安装 nacos 2.0.3

docker 镜像 https://registry.hub.docker.com/r/nacos/nacos-server/tags 1.下载nacos镜像 这里下载的是2.0.3 docker pull nacos/nacos-server:2.0.32.查看镜像是否下载成功 如下图 docker images3.创建文件夹 注&#xff1a; 自定义创建&#xff0c;用于把docker内部的文件…

【基金学习】基金的相关计算题目

文章目录一、基金收益计算1. 累计收益/持有收益2. 年化收益/年化收益率3. 涨跌幅4. 分红二、风险计算1. 贝塔系数2. 波动率三、费用计算1. 托管费2. 管理费3. 销售服务费4. 申购/赎回费一、基金收益计算 1. 累计收益/持有收益 累计收益 持仓金额 - 本金 累计收益率 &#xf…

TCP 的 NACK 与 SACK

可靠传输&#xff0c;一旦丢包&#xff0c;必然 HoL blocking&#xff0c;NACK 和 SACK 必须二选一驱动重传&#xff1a; NACK&#xff1a;receiver 主动通告没有收到的报文&#xff0c;sender 收到后重传。 SACK&#xff1a;receiver 主动通告收到的报文&#xff0c;sender …

一文带你深入了解算法笔记中的前缀与差分(附源码)

&#x1f4d6;作者介绍&#xff1a;22级树莓人&#xff08;计算机专业&#xff09;&#xff0c;热爱编程&#xff1c;目前在c&#xff0b;&#xff0b;阶段&#xff0c;因为最近参加新星计划算法赛道(白佬)&#xff0c;所以加快了脚步&#xff0c;果然急迫感会增加动力>——…

笔记本上就能跑的 LLM 好使吗?GPT4ALL 体验

是骡子是马&#xff0c;牵出来遛遛正名看到这个标题&#xff0c;你可能会觉得是噱头。谁不知道 ChatGPT 模型有 1750 亿以上的参数&#xff0c;别说是在笔记本电脑上跑&#xff0c;就是使用高性能 GPU 的台式机&#xff0c;也无法带得动啊。老老实实调用 API 不好吗&#xff1f…