前言
按照官网的线路走啊走~~~
创建实例
vue2x 和 vue3x 创建实例的区别
vue2x:创建实例通过new Vue()
vue3x:通过调用createApp这个api返回一个应用实例,可以链式调用其他方法。借用官网的例子。
<div id="counter">
{{ message }}
</div>
// vue2用法
var app = new Vue({
el: '#counter',
data: {
message: 'Hello Vue!'
}
})
// vue3用法
const Counter = {
data() {
return {
counter: 0
}
}
}
Vue.createApp(Counter).mount('#counter')
指令
模板语法
- v-once
仅渲染一次元素和组件,后续重新渲染时,元素/组件及其子组件将被忽略,不再发生改变。主要用于优化更新性能。
<template>
<div>
<div>{{ msg }}</div>
<div v-once>{{ msg }}</div>
<button @click="change">切换</button>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
msg: "小张张要努力",
};
},
components: {},
methods: {
change() {
this.msg = "小张张今天努力了吗";
},
},
};
</script>
- v-html
让元素以html模板的形式展现。
注意:在网站上动态呈现任意HTML可能非常危险,因为它很容易导致XSS攻击。仅使用v-html可信的内容,并从未对用户提供的内容。
<template>
<div>
<div v-html="msg">有html:</div>
<div>无html:{{ msg }}</div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
//msg: "小张张要努力",
msg: "<h1>小张张要努力</h1>",
};
}
};
</script>
- v-bind
动态地将一个或多个属性或组件属性绑定到表达式。
语法糖::
计算属性和侦听器
计算属性
本着模板简单易维护的原则,模板中的逻辑不宜太过复杂,如果在模板中放入太多的逻辑会让模板过重且难以维护。如下面例子。
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
在这个地方,模板不再是简单的声明式逻辑,而是做了大量的逻辑处理。
#计算属性基础案例
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
Vue.createApp({
data() {
return {
message:'Hello'
}
},
computed: {
// a computed getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
}).mount('#example')
#计算属性缓存 vs 方法
对于复杂的逻辑处理,除了计算属性,我们还可以通过在表达式中调用方法来达到同样的效果。
Vue.createApp({
data() {
return {
message:'Hello'
}
},
// 在组件中
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
}).mount('#example')
我们可以看到,将同一个函数定义为方法或者属性,得到的结果是相同的。那么,他们之间有什么区别呢?区别就在于**计算属性是基于它们的响应式依赖进行缓存的。**只在相关响应式依赖发生改变时才会重新计算,这就意味着只要message没发生改变,不管访问几次reversedMessage都会返回之前的结果,不会进行重新计算。
换种说法也就是如果计算属性的值没有基于响应式依赖,那么计算属性的值将在做了第一次计算后,永远不会在更新。例如:Date.now() 不是响应式依赖:
computed: {
now: function () {
return Date.now()
}
}
#计算属性的setter
默认情况下,计算属性仅是getter,但是在必要时也可以提供setter
<template>
<div>
<!-- {{now}} -->
<span>{{fullName}}</span>
<button @click="change">按钮</button>
</div>
</template>
<script>
export default {
name: 'App',
data () {
return {
firstName:'a',
lastName:'b'
}
},
computed: {
now: function () {
return Date.now()
},
fullName: {
// getter
get() {
return this.firstName + ' ' + this.lastName
},
// setter
set(newValue) {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
},
methods:{
change(){
this.fullName = 'John Doe'
}
}
}
</script>
侦听器
对数据更改做出反应,vue提供了一种更通用的方式–watch,当需要执行异步或者开销较大的操作时,使用watch监听更加方便。
直击官网案例.
类和样式绑定
元素的 class 列表和内联样式都是attribute,可以选择使用v-bind(简写::)处理它们。v-bind绑定的表达式结果的类型可以有:字符串,对象或者数组。
绑定HTML类
#对象语法
:class可以绑定一个对象,用于动态切换class。
<div :class="{ active: isActive }"></div>
// 语法解释:isActive 为true,则class为active,反之,class为空
对象中可以绑定多个class。此外,:class与普通的class可以同时存在,如下也是成立的:
<div
class="static"
:class="{ active: isActive, 'text-danger': hasError }"
></div>
data: {
isActive: true,
hasError: false
}
最终结果将为
<div class="static active"></div>
绑定的对象不必是内联的,可以通过data或者computed计算属性返回。
<div v-bind:class="classObject"></div>
// data数据返回
data: {
classObject: {
active: true,
'text-danger': false
}
}
//computed计算属性
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
#数组语法
数组语法的写法:v-bind:class,三元表达式,对象语法
v-bind:class
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
// 渲染为
<div class="active text-danger"></div>
三元表达式
<template>
<div :class="[isActive ? activeClass : '','addClass']">数组绑定class</div>
</template>
<script>
export default {
data () {
return {
isActive:true,
activeClass:'class'
}
}
}
</script>
// 渲染为
<div class="class addClass">数组绑定class</div>
对象语法
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
条件渲染
条件渲染包括 v-show 和 v-if
v-if
- 使用v-if控制模版的显示隐藏,每一次都是重新渲染了模板,也就是在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
- v-if / v-else / v-ele-if 可参考js if / else if / else
- 在 元素上使用 v-if 条件渲染分组。因为 v-if 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 元素。
- key 可将可以复用的元素变成独立的。
v-show
v-show 和 v-if比较着看:
- v-if 比较勤快,每次的条件切换,条件块内的事件监听器和子组件都会被适当的销毁和创建。
- v-if 有时候又比较懒,如果初始渲染条件为假时,什么也不会做,直到条件变为真时才开始渲染。
- v-show 性格比较平均,不管初始条件是什么,都会进行渲染,但是 v-show 为fals时,不会进行销毁,只是进行css上简单的显示隐藏切换。
- 一般来说,v-if比v-show要消耗更高的性能。如果需要频繁的切换,并且不是必须重建组件的情况下,选用v-show会更好,如果条件很少改变时,用v-if会更好。
v-if 与 v-for
不推荐一起使用,
列表渲染
- 列表渲染可以看作循环渲染。渲染的对象可以是数组,也可以是对象。
v-for 渲染数组为一组元素
- v-for 中的属性名称有两个参数,(value,index)值,索引
ul id="array-with-index">
<li v-for="(item, index) in items" :key="index">
{{ index }} - {{ item.message }}
</li>
</ul>
Vue.createApp({
data() {
return {
items: [{ message: 'Foo' }, { message: 'Bar' }]
}
}
}).mount('#array-rendering')
// 结果
.FOO
.Bar
我们可以看到通常情况下,需要为每项提供一个唯一 key,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素。
事件处理
事件用v-on简写为 @ 监听。
内联事件处理
内联事件处理可以传递参数 $event ,用来访问原始的DOM事件。
<button @click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
// ...
methods: {
warn(message, event) {
// now we have access to the native event
if (event) {
event.preventDefault()
}
alert(message)
}
}
内联事件处理
事件处理程序中可以使用多个方法,这些方法用逗号分隔开,如下
<button @click="one($event), two($event)">
Submit
</button>
// ...
methods: {
one(event) {
// first handler logic...
},
two(event) {
// second handler logic...
}
}
问题研究
- 计算属性和方法除了计算属性具有缓存外,还有无其他区别,以及在不同的场景下应该怎么选择计算属性和方法?
- 计算属性一般都是用到它的getter。那么setter存在的意义是什么,什么情况用到setter会是更佳的选择?