vue笔记
# vue.js
# Es6语法
变量声明:
var声明的变量没有区块的概念,可以跨块访问
let变量只能在区块作用域中访问,不能跨块访问
async
和 await
是 JavaScript 中用于处理异步操作的关键字。
首先,我们来看看什么是异步操作。在 JavaScript 中,有一些操作可能需要花费一些时间才能完成,例如网络请求或定时器。这些操作被称为异步操作,因为它们不会立即完成。
async
和 await
关键字让我们能够以更直观和易于理解的方式处理这些异步操作。
async
:这个关键字用于声明一个函数是异步的。异步函数总是返回一个 promise。如果函数的返回值不是一个 promise,那么 JavaScript 会自动将其包装成 promise。await
:这个关键字只能在async
函数中使用。它会暂停当前的异步函数,等待 promise 完成(即等待 promise 变为 resolved 或 rejected 状态),然后返回 promise 的结果值(如果 promise 是 resolved 的)或抛出错误(如果 promise 是 rejected 的)。
这是一个简单的例子:
async function fetchUser(userId) {
const response = await fetch(`https://api.example.com/users/${userId}`);
const user = await response.json();
return user;
}
2
3
4
5
在这个例子中,fetchUser
函数是一个异步函数,它使用 await
关键字等待 fetch
函数的结果。当 fetch
函数返回一个 promise 时,await
会暂停 fetchUser
函数的执行,直到 promise 完成。然后,它会继续执行 fetchUser
函数,并使用 promise 的结果值。
# 基础知识
Vue.config:全局配置
可通过Vue.config.productionTip = false
阻止 vue 在启动时生成生产提示。
favicon.ico:网站图标,放在根目录下
# MVVM
- M:模型(Model) :对应data 中的数据
- V:视图(View) :模板
- VM:视图模型(ViewModel) : Vue 实例对象
因此一般用vm命名Vue 实例对象
5.data中所有的属性,最后都出现在了vm身上。
6.vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。
# 创建Vue容器
Vue.createApp()
方法返回vue的app实例,mount之后为根组件实例
子组件:
app.component('botton-component',{...})
为app添加一个组件,第一个参数为组件名,第二个参数与根组件相同,该组件可直接在挂在的html容器中使用:<botton-component></botton-component>
这种方式为全局组件,必须在mount之前定义
局部组件是写在组件配置中的,只有该组件能使用。
Vue.createApp({
data() {
return {
msg: null,
list:[]
}
},
computed:{
newdate(){
if (this.list.length == 0) return null
return this.formatDate(this.list[this.list.length-1].time)
}
},
components:{
'child-component':child-component
},
methods:{
submit(){
if (this.msg) {
this.list.push({
text:this.msg,
time: Date.now()
})
this.msg = null
}
},
formatDate(value){
let date = new Date(value);
let year = date.getFullYear();
let month = date.getMonth() + 1 +'';
let day = date.getDate() +'';
let hour = date.getHours() +'';
let minute = date.getMinutes() +'';
let second = date.getSeconds() +'';
return `${year}-${month.padStart(2,'0')}-${day.padStart(2,'0')} ${hour.padStart(2,'0')}:${minute.padStart(2,'0')}:${second.padStart(2,'0')}`
}
}
}).mount("#app")
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 模版语法
# 插值表达式
# 文本插值
最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法 (即双大括号):
template
<span>Message: {{ msg }}</span>
双大括号标签会被替换为相应组件实例中 (opens new window) msg
属性的值。同时每次 msg
属性更改时它也会同步更新。
# 使用 JavaScript 表达式
至此,我们仅在模板中绑定了一些简单的属性名。但是 Vue 实际上在所有的数据绑定中都支持完整的 JavaScript 表达式:
template
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div :id="`list-${id}`"></div>
2
3
4
5
6
7
这些表达式都会被作为 JavaScript ,以当前组件实例为作用域解析执行。
在 Vue 模板内,JavaScript 表达式可以被使用在如下场景上:
- 在文本插值中 (双大括号)
- 在任何 Vue 指令 (以
v-
开头的特殊 attribute) attribute 的值中
# 单一表达式
每个绑定仅支持单一表达式,也就是一段能够被求值的 JavaScript 代码。一个简单的判断方法是是否可以合法地写在 return
后面。
因此,下面的例子都是无效的:
template
<!-- 这是一个语句,而非表达式 -->
{{ var a = 1 }}
<!-- 条件控制也不支持,请使用三元表达式 -->
{{ if (ok) { return message } }}
2
3
4
5
# 调用函数
可以在绑定的表达式中使用一个组件暴露的方法:
template
<time :title="toTitleDate(date)" :datetime="date">
{{ formatDate(date) }}
</time>
2
3
TIP:绑定在表达式中的方法在组件每次更新时都会被重新调用,因此不应该产生任何副作用,比如改变数据或触发异步操作。
# 内置指令 (opens new window)
指令是带有 v-
前缀的特殊 attribute。Vue 提供了许多内置指令 (opens new window),包括上面我们所介绍的 v-bind
和 v-html
。
指令 attribute 的期望值为一个 JavaScript 表达式 (除了少数几个例外,即之后要讨论到的 v-for
、v-on
和 v-slot
)。一个指令的任务是在其表达式的值变化时响应式地更新 DOM。
绑定标签属性v-bind(缩写为:)
<span v-bind:title="message"> 11 </span>
v-bind是单向绑定,数据只能从data中传入,而不能从dom中传出
若为布尔属性且不存在,则该标签title不会渲染在span中
绑定表单类元素v-model
<input type="text" v-model:value="name">
缩写为:
<input type="text" v-model="name"><br/>
v-model是双向绑定,dom和data中的数据同步
v-if
(opens new window)和v-show
<p v-if="seen">Now you see me</p>
这里,v-if
指令会基于表达式 seen
的值的真假来移除/插入该 <p>
元素,该元素不会被渲染。
v-show
的元素会被渲染,但只是隐藏该元素。
v-for
基于原始数据多次渲染元素或模板块。
期望的绑定值类型:Array | Object | number | string | Iterable
详细信息
指令值必须使用特殊语法 alias in expression
为正在迭代的元素提供一个别名:
<div v-for="item in items">
{{ item.text }}
</div>
2
3
或者,你也可以为索引指定别名 (如果用在对象,则是键值):
<div v-for="(item, index) in items"></div>
<div v-for="(value, key) in object"></div>
<div v-for="(value, name, index) in object"></div>
2
3
v-for
的默认方式是尝试就地更新元素而不移动它们。要强制其重新排序元素,你需要用特殊 attribute key
来提供一个排序提示:
<div v-for="item in items" :key="item.id">
{{ item.text }}
</div>
2
3
v-for
也可以用于 Iterable Protocol (opens new window) 的实现,包括原生 Map
和 Set
。
- 使用v-on:xxx 或 @xxx 绑定事件(缩写为@)
1.事件的回调需要配置在methods对象中,最终会在vm上;
2.methods中配置的函数,不要用箭头函数!否则this就不是vm了;
3.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
4.@click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参;
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<!-- <button v-on:click="showInfo">点我提示信息</button> -->
<button @click="showInfo1">点我提示信息1(不传参)</button>
<button @click="showInfo2($event,66)">点我提示信息2(传参)</button>
</div>
2
3
4
5
6
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
},
methods:{
showInfo1(event){
// console.log(event.target.innerText)
// console.log(this) //此处的this是vm
alert('同学你好!')
},
showInfo2(event,number){
console.log(event,number)
// console.log(event.target.innerText)
// console.log(this) //此处的this是vm
alert('同学你好!!')
}
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 属性
# data
data属性有两种写法:
new Vue({
el:'#root',
//data的第一种写法:对象式
/* data:{
name:'尚硅谷'
} */
//data的第二种写法:函数式
data(){
console.log('@@@',this) //此处的this是Vue实例对象
return{
name:'尚硅谷'
}
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Vue会通过响应式系统将data包裹起来,以$data
存储在组件示例中。注意,在挂载后调用组件添加的变量是没有响应输赢的。
const vm=app.mount('#app')
console.log(vm.$data.count)
console.log(vm.count)
2
3
4
# 计算属性
推荐使用计算属性来描述依赖响应式状态的复杂逻辑
<script setup>
import { reactive, computed } from 'vue'
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
})
// 一个计算属性 ref
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})
</script>
<template>
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 侦听器
计算属性允许我们声明性地计算衍生值。然而在有些情况下,我们需要在状态变化时执行一些“副作用”:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态。
<script setup>
import { ref, watch } from 'vue'
const question = ref('')
const answer = ref('Questions usually contain a question mark. ;-)')
// 可以直接侦听一个 ref
watch(question, async (newQuestion, oldQuestion) => {
if (newQuestion.indexOf('?') > -1) {
answer.value = 'Thinking...'
try {
const res = await fetch('https://yesno.wtf/api')
answer.value = (await res.json()).answer
} catch (error) {
answer.value = 'Error! Could not reach the API. ' + error
}
}
})
</script>
<template>
<p>
Ask a yes/no question:
<input v-model="question" />
</p>
<p>{{ answer }}</p>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
注意,你不能直接侦听响应式对象的属性值,例如:
const obj = reactive({ count: 0 })
// 错误,因为 watch() 得到的参数是一个 number
watch(obj.count, (count) => {
console.log(`count is: ${count}`)
})
2
3
4
5
6
这里需要用一个返回该属性的 getter 函数:
// 提供一个 getter 函数
watch(
() => obj.count,
(count) => {
console.log(`count is: ${count}`)
}
)
2
3
4
5
6
7
# 深层侦听器
直接给 watch()
传入一个响应式对象,会隐式地创建一个深层侦听器——该回调函数在所有嵌套的变更时都会被触发:
const obj = reactive({ count: 0 })
watch(obj, (newValue, oldValue) => {
// 在嵌套的属性变更时触发
// 注意:`newValue` 此处和 `oldValue` 是相等的
// 因为它们是同一个对象!
})
obj.count++
2
3
4
5
6
7
8
9
相比之下,一个返回响应式对象的 getter 函数,只有在返回不同的对象时,才会触发回调:
watch(
() => state.someObject,
() => {
// 仅当 state.someObject 被替换时触发
}
)
2
3
4
5
6
你也可以给上面这个例子显式地加上 deep
选项,强制转成深层侦听器:
watch(
() => state.someObject,
(newValue, oldValue) => {
// 注意:`newValue` 此处和 `oldValue` 是相等的
// *除非* state.someObject 被整个替换了
},
{ deep: true }
)
2
3
4
5
6
7
8