参考:
https://cn.vuejs.org/guide/introduction.html
https://blog.csdn.net/weixin_42371679/article/details/112408800
vue是一个js库,它基于标准html、css和js,并提供了一套声明式的、组件化的编程模型,可高效的开发用户界面。
简单应用举例
我们只需引入vue.min.js就可以使用vue。在这个例子中,我们引入vue.min.js,并使用vue来操作dom
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vue</title> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> </head> <body> <div id="app"> <p>{{ message }}</p> </div> <script> new Vue({ el: '#app', data: { message: 'Hello Vue.js!' } }) </script> </body> </html>
这里,我们创建了一个vue实例用于挂载这个dom。运行结果如下
1 一些概念
1.1 单文件组件SFC
在vue中,我们可以创建一个.vue文件来创建一个组件,称为单文件组件。它的格式类似html格式,并且把js、html、css封装在同一个文件里,如下是一个例子
demo.vue
<script> export default { data() { return { count: 0 } } } </script> <template> <button @click="count++">Count is: {{ count }}</button> </template> <style scoped> button { font-weight: bold; } </style>
1.2 选项式API和组合式API
vue组件可以按照两种不同的风格来写:选项式 API 和组合式 API
选项式API是一个对象,该对象包含了data、methods、mounted等属性,这些属性都会暴露在函数内部的this上,这个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
<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>
2 使用vue脚手架创建vue项目
D:\2022\front\vue>npm init vue@latest Need to install the following packages: create-vue@latest Ok to proceed? (y) y Vue.js - The Progressive JavaScript Framework √ Project name: ... vue-project √ 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 Scaffolding project in D:\2022\front\vue\vue-project... Done. Now run: cd vue-project npm install npm run dev D:\2022\front\vue>
安装依赖并启动项目
> cd vue-project > npm install > npm run dev
3 html中直接使用ES模块导入和使用vue
现在绝大多数浏览器都支持ES,下面的例子,我们使用了<script type="module">,并且导入vue
<div id="app">{{ message }}</div> <script type="module"> import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js' createApp({ data() { return { message: 'Hello Vue!' } } }).mount('#app') </script>
这个例子,我们不需要使用构建工具构建,直接在浏览器中打开即可
4 import maps
上面例子中,我们使用url导入vue,其实我们可以指定vue的多个源,通过<script type="importmap">设定
<script type="importmap"> { "imports": { "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js" } } </script> <div id="app">{{ message }}</div> <script type="module"> import { createApp } from 'vue' createApp({ data() { return { message: 'Hello Vue!' } } }).mount('#app') </script>
5 根组件
每个应用都需要一个根组件,其他组件作为子组件
import { createApp } from 'vue' // 从一个单文件组件中导入根组件 import App from './App.vue' const app = createApp(App)
比如上例,根组件是App.vue,然后我们将这个组件作为createApp()的参数,createApp()作用是创建应用实例。
6 挂载
模板
<div id="app"></div>
js
app.mount('#app')
我们应该这么理解,我们创建了一个应用实例app,然后我们有一个html中的挂载点,我们将这个应用实例挂载到html的挂载点中。其中这个挂载点称为挂载容器。
当在未采用构建流程中使用vue时,可以在挂载容器中直接书写根组件模板
容器
<div id="app"> <button @click="count++">{{ count }}</button> </div>
js
import { createApp } from 'vue' const app = createApp({ data() { return { count: 0 } } }) app.mount('#app')
当根组件没有template选项时,Vue 将自动使用容器的 innerHTML 作为模板
7 模板语法
vue使用一种基于html的模板语法,使我们能够声明式的将vue组件实例的数据绑定到dom树上。而且所有的vue模板可以看做合法的html文档,即使没有vue引擎,浏览器也能够正常解析它,只不过其中的{{}}绑定的数据不能够被替换罢了。
在底层,vue会将模板编译为优化了的js代码。结合响应式系统,当vue应用状态发生变更时,vue将会重新渲染这些dom。
7.1 模板中的数据绑定形式
文本插值
<span>Message: {{ msg }}</span>
文本插值是最基本的数据绑定形式,其语法为{{}},双大括号标签会被替换为组件实例中 msg 属性的值。同时每次模板中 msg 属性更改时它也会同步更新
原始html
如果我们想向模板中插入原始html标签(比如<span style="color: red">This should be red.</span>),需要使用v-html属性
<p>Using text interpolation: {{ rawHtml }}</p>//错误 <p>Using v-html directive: <span v-html="rawHtml"></span></p>//正确
这里我们做的事情简单来说就是:在当前组件实例上,将此元素的 innerHTML 与 vue组件实例的rawHtml 属性保持同步。span 的内容将会被替换为 rawHtml 属性的值,插值为纯 HTML——数据绑定将会被忽略
html属性绑定
如果需要绑定html标签的属性,需要如下操作
<div v-bind:id="dynamicId"></div>
上例中,将div元素的id属性和vue组件实例的dynamicId属性绑定在一起,如果vue组件实例的dynamicId是null或undefined,那么div元素的id属性将会被移除
因为v-bind非常常用,所以简写形式如下
<div :id="dynamicId"></div>
如果vue组件实例中的属性包含多个值,例如如下
data() { return { objectOfAttrs: { id: 'container', class: 'wrapper' } } }
通过不带参数的 v-bind,你可以将它们绑定到模板的单个元素上
<div v-bind="objectOfAttrs"></div>
使用js表达式
表达式都会以组件为作用域解析执行。
{{ number + 1 }} {{ ok ? 'YES' : 'NO' }} {{ message.split('').reverse().join('') }} <div :id="`list-${id}`"></div>
在vue中javascript表达式可以被用于如下场景:
在文本插值中放到{{}}内部
在vue指令(v-开头的特殊属性)的属性值中
7.2 vue指令
vue指令是以v-开头的特殊属性。
指令的值必须是一个javascript表达式(除少数几个例外)。
一个指令的作用是在其表达式的值发生变化时,响应式的更新dom。
<p v-if="seen">Now you see me</p>
这里v-if指令会基于seen表达式的值来移除/插入该<p>元素。
指令参数
<a v-on:click="doSomething"> ... </a> <!-- 简写 --> <a @click="doSomething"> ... </a>
上例中,指令v-on的参数是click,参数值是doSomething。
动态参数
<a v-bind:[attributeName]="url"> ... </a> <!-- 简写 --> <a :[attributeName]="url"> ... </a>
在指令的参数上可以使用一个javascript表达式,这个表达式放到[]中,称为动态参数。上例中attributeName会作为一个javascript表达式被动态的执行,计算得到的值会被用作最终的参数。举例来说,如果attribteName表达式的值是href,则这个绑定就等价于v-bind:href
相似的还可以将一个函数绑定到动态的事件名称上
<a v-on:[eventName]="doSomething"> ... </a> <!-- 简写 --> <a @[eventName]="doSomething">
如果eventName表达式的值是focus,就等价于v-on:focus
修饰符
这里的修饰符指的是指令参数的修饰符
<form @submit.prevent="onSubmit">...</form>
上例中,.prevent就是修饰符,这个修饰符会告知v-on指令对触发的事件调用e.preventDefault()
8 响应式
8.1 状态
我们以选项式API为例
用 data 选项来声明组件的响应式状态。此选项的值应为返回一个对象的函数。Vue 将在创建新组件实例的时候调用此函数,并将函数返回的对象用响应式系统进行包装。此对象的所有顶层属性都会被代理到组件实例 (即方法和生命周期钩子中的 this) 上。
export default { data() { return { count: 1 } }, // `mounted` 是生命周期钩子,之后我们会讲到 mounted() { // `this` 指向当前组件实例 console.log(this.count) // => 1 // 数据属性也可以被更改 this.count = 2 } }
组件实例上的属性仅在实例首次创建时被添加,因此你需要确保它们都出现在 data 函数返回的对象上,如果值暂时未准备好,必要时可以使用null、undefined等占位。
8.2 方法
要为组件添加方法,我们需要用到 methods 选项。它应该是一个包含所有方法的对象
export default { data() { return { count: 0 } }, methods: { increment() { this.count++ } }, mounted() { // 在其他方法或是生命周期中也可以调用方法 this.increment() } }
vue自动为methods中的方法绑定了永远指向组件实例的this。需要注意的是,methods中的方法不能使用箭头函数,因为箭头函数没有自己的this上下文
export default { methods: { increment: () => { // 反例:无法访问此处的 `this`! } } }
模板上访问方法
<button @click="increment">{{ count }}</button>
8.3 DOM更新时机
当我们修改了响应式状态之后,dom会自动更新,但是,vue更新dom有自己的节奏,按照固定的时间周期更新。如果我们想访问更新后的dom,需要使用如下方式
import { nextTick } from 'vue' export default { methods: { increment() { this.count++ nextTick(() => { // 访问更新后的 DOM }) } } }
8.4 computed
export default { data() { return { author: { name: 'John Doe', books: [ 'Vue 2 - Advanced Guide', 'Vue 3 - Basic Guide', 'Vue 4 - The Mystery' ] } } }, computed: { // 一个计算属性的 getter publishedBooksMessage() { // `this` 指向当前组件实例 return this.author.books.length > 0 ? 'Yes' : 'No' } } }
模板中的应用
<p>Has published books:</p> <span>{{ publishedBooksMessage }}</span>
在模板中使用计算属性的方式和使用一般属性的方式并无二致。Vue 会检测到 this.publishedBooksMessage 依赖于 this.author.books,所以当 this.author.books 改变时,任何依赖于 this.publishedBooksMessage 的绑定都将同时更新
computed属性缓存和方法比较
上例中,我们如果定义一个方法,同样可以达到一样的效果
// 组件中 methods: { calculateBooksMessage() { return this.author.books.length > 0 ? 'Yes' : 'No' } }
模板中调用方法
<p>{{ calculateBooksMessage() }}</p>
但是methods和computed是有区别的。computed属性是当状态属性发生变化时,触发computed属性的计算,然后缓存,如果状态属性没有变化,则会一直使用这个缓存。而methods会每次都会被调用
可写computed属性
computed属性默认是只读的。我们可以通过提供setter来使其可写。
export default { data() { return { firstName: 'John', lastName: 'Doe' } }, computed: { fullName: { // getter get() { return this.firstName + ' ' + this.lastName }, // setter set(newValue) { // 注意:我们这里使用的是解构赋值语法 [this.firstName, this.lastName] = newValue.split(' ') } } } }
现在当你再运行 this.fullName = 'John Doe' 时,setter 会被调用而 this.firstName 和 this.lastName 会随之更新
8.5 绑定class
<div :class="{ active: isActive }"></div>
如果isActive=true的话,渲染结果是
<div :class=‘active’></div>
我们也可以在一个class上绑定多个值
data() { return { isActive: true, hasError: false } }
配合如下模板
<div class="static" :class="{ active: isActive, 'text-danger': hasError }" ></div>
渲染结果为
<div class="static active"></div>
另外,一种更简便的方式是我们可以直接绑定一个对象
data() { return { classObject: { active: true, 'text-danger': false } } }
模板
<div :class="classObject"></div>
绑定数组
data() { return { activeClass: 'active', errorClass: 'text-danger' } }
模板
<div :class="[activeClass, errorClass]"></div>
渲染结果
<div class="active text-danger"></div>
8.6 绑定内联样式
:style 支持绑定 JavaScript 对象值,对应的是 HTML 元素的 style 属性
data() { return { activeColor: 'red', fontSize: 30 } }
对应的模板
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
8.7 条件渲染
v-if指令用于条件性的渲染一块内容。
<h1 v-if="awesome">Vue is awesome!</h1>
另外还有v-else和v-else-if
<button @click="awesome = !awesome">Toggle</button> <h1 v-if="awesome">Vue is awesome!</h1> <h1 v-else>Oh no 标签:count,vue,解读,Vue,文档,组件,data,模板 From: https://www.cnblogs.com/zhenjingcool/p/16804289.html