组合式API
- 在组合式api中直接声明的变量,就是一个普通的变量,不是响应式属性
- 修改这些属性时,不会在视图中产生效果
- 可以通过 reactive()来创建一个响应式的对象
- 在setup()中可以通过返回值来指定那些内容要暴露给外部
- 暴露后的内容,可以在模板中直接使用
<script>
import { reactive } from "vue"
export default {
setup() {
// 定义变量
// 在组合式api中直接声明的变量,就是一个普通的变量,不是响应式属性
// 修改这些属性时,不会在视图中产生效果
let msg = "今天天气真不错!"
let count = 0
//可以通过 reactive()来创建一个响应式的对象
const stu = reactive({
name: "孙悟空",
age: 18,
gender: "男"
})
function changeAge(){
stu.age = 44
}
// 在setup()中可以通过返回值来指定那些内容要暴露给外部
// 暴露后的内容,可以在模板中直接使用
return {
msg,
count,
stu,
changeAge
}
}
}
</script>
<template>
<h1>演示组合式API</h1>
<h2>{{ msg }}</h2>
<h3>{{ count }}</h3>
<button @click="changeAge">点我一下</button>
<h2>{{ stu.name }} -- {{ stu.age }} -- {{ stu.gender }}</h2>
</template>
setup
- 在
script
标签中加上setup,就说明要使用组合式API
<script setup>
//默认暴露了
import { reactive } from "vue"
const msg = "我爱Vue"
const count = 0
const stu = reactive({
name: "孙悟空"
})
function fn() {
alert("哈哈哈,好快乐!")
}
</script>
<template>
<h1 @click="fn">组合式的API</h1>
<h2>{{ msg }} -- {{ count }}</h2>
<h3>{{ stu.name }}</h3>
</template>
响应式原理
reactive()
- 返回一个对象的响应式代理
- 返回的是一个深层响应式对象
- 也可以使用shallowReactive()创建一个浅层响应式对象
- 缺点:
- 只能返回对象的响应式代理!不能处理原始值
ref()
- 接收一个任意值,并返回它的响应式代理
- ref在生成响应式代理时,它是将值包装为了一个对象 0 --> {value:0}
- 访问ref对象时,必须通过 对象.value 来访问其中的值
- 在模板template中,ref对象会被自动解包,不用通过.value来访问
- vue给我们提供了一个语法糖,使得ref对象在script标签中也可以自动解包
- $是一个实验性的,需要在vite插件(vite.config.js)中做一些配置 reactivityTransform:true.即在这里修改
plugins: [vue({
eactivityTransform:true
})],
<script setup>
import { reactive, ref } from "vue"
import { $ref } from "vue/macros"
/*
reactive()
- 返回一个对象的响应式代理
- 返回的是一个深层响应式对象
- 也可以使用shallowReactive()创建一个浅层响应式对象
- 缺点:
- 只能返回对象的响应式代理!不能处理原始值
ref()
- 接收一个任意值,并返回它的响应式代理
*/
const stu = reactive({
name: "孙悟空"
})
// ref在生成响应式代理时,它是将值包装为了一个对象 0 --> {value:0}
// 访问ref对象时,必须通过 对象.value 来访问其中的值
// 在模板template中,ref对象会被自动解包,不用通过.value来访问
let count = $ref(0) // 生成一个0的响应式代理
// count = 10 // 改变量只会影响到变量自己,在js中,无法实现对一个变量的代理
console.log(count)
// vue给我们提供了一个语法糖,使得ref对象在script标签中也可以自动解包
// $是一个实验性的,需要在vite插件(vite.config.js)中做一些配置 reactivityTransform:true
// 即在这里修改 plugins: [vue({
// reactivityTransform:true
// })],
function fn() {
// count自增
count++
}
</script>
<template>
<h1>组合式的API</h1>
<h2 @click="fn">{{ count }}</h2>
</template>
ref对象解包
<script setup>
import { ref, reactive, computed } from "vue"
const msg = ref("Hello Vue")
// {value: obj}
// obj.value.name
// 一般用这种方式,而不是下面的obj2
const obj = ref({
name: "孙悟空",
age: 18
})
// obj2.name.value
const obj2 = {//此时obj2对象不是响应式的
name: ref("孙悟空"), // {value:"孙悟空"}
age: ref(18) // // {value:18}
}
const { name, age } = obj2 //对obj2对象解构,此时就是顶层对象了,直接在模板解析name即可,不用加value
const changeMsgHandler = () => {
// 修改ref对象时,必须通过value。语法糖暂未正式用,但也可以用
// msg.value = "哈哈"
name.value = "你看我变不变"
}
// computed 用来生成计算属性
const newMsg = computed(() => {
return msg.value + "-我爱Vue!"
})
</script>
<template>
<!-- ref对象在模板中可以自动解包(要求ref对象必须是顶层对象) -->
<h1>{{ msg }}</h1>
<h1>{{ newMsg }}</h1>
<h2>{{ obj.name }}</h2>
<!-- name不是顶层响应式对象,所以不能自动解包 -->
<!-- <h2>{{ obj2.name.value }}</h2> -->
<h2>{{ name }}</h2>
<hr />
<h2>{{ obj.age + 1 }}</h2>
<!-- <h2>{{ obj2.age.value + 1 }}</h2> -->
<h2>{{ age + 1 }}</h2>
<button @click="changeMsgHandler">点我一下</button>
</template>
模板的语法
-
在模板中,可以直接访问到组件中声明的变量
- 除了组件中的变量外,vue也为我们提供了一些全局对象可以访问:
比如:Date、Math、RegExp …
除此之外,也可以通过app对象来向vue中添加一些全局变量
在main.js中添加app.config.globalProperties - 使用插值(双大括号),只能使用表达式
表达式,就是有返回值的语句 - 插值实际上就是在修改元素的textContent,
如果内容中含有标签,标签会被转义显示,不会作为标签生效
指令:
- 指令模板中为标签设置的一些特殊属性,它可以用来设置标签如何显示内容
- 指令使用v-开头
v-text 将表达式的值作为元素的textContent插入,作用同{{}}
使用指令时,不需要通过{{}}来指定表达式
v-html 将表达式的值作为元素的innerHTML插入,有xss攻击的风险
- 除了组件中的变量外,vue也为我们提供了一些全局对象可以访问:
<script setup>
const msg = "我爱vue"
const html = `<h2>我是一段html代码</h2>`
const fn = () => {
console.log("哈哈哈")
}
</script>
<template>
<!--
- 在模板中,可以直接访问到组件中声明的变量
- 除了组件中的变量外,vue也为我们提供了一些全局对象可以访问:
比如:Date、Math、RegExp ...
除此之外,也可以通过app对象来向vue中添加一些全局变量
在main.js中添加app.config.globalProperties
- 使用插值(双大括号),只能使用表达式
表达式,就是有返回值的语句
- 插值实际上就是在修改元素的textContent,
如果内容中含有标签,标签会被转义显示,不会作为标签生效
指令:
- 指令模板中为标签设置的一些特殊属性,它可以用来设置标签如何显示内容
- 指令使用v-开头
v-text 将表达式的值作为元素的textContent插入,作用同{{}}
使用指令时,不需要通过{{}}来指定表达式
v-html 将表达式的值作为元素的innerHTML插入,有xss攻击的风险
-->
<h1>{{ "hello" + "world" }}</h1>
<!-- <h2>{{ if(1+1==2){console.log(123)} }}</h2> -->
<div>{{ html }}</div>
<div v-text="html"></div>
<div v-html="html"></div>
</template>
v-bind
- 当我们需要为标签动态的设置属性时,需要使用v-bind指令,
- v-bind可以简写为 :
- 当我们为一个布尔值设置属性时,
- 如果值为true,则元素上有该属性(转换后为true,也算true)
- 如果值为false,则元素没有该属性(转换后为false,也算false)
- 特殊情况:“” 空串,在这里会被当成真值
动态参数
同样在指令参数上也可以使用一个 JavaScript 表达式,需要包含在一对方括号内:
<!--
注意,参数表达式有一些约束,
参见下面“动态参数值的限制”与“动态参数语法的限制”章节的解释
-->
<a v-bind:[attributeName]="url"> ... </a>
<!-- 简写 -->
<a :[attributeName]="url"> ... </a>
这里的 attributeName
会作为一个 JavaScript 表达式被动态执行,计算得到的值会被用作最终的参数。举例来说,如果你的组件实例有一个数据属性 attributeName
,其值为 "href"
,那么这个绑定就等价于 v-bind:href
。
<script setup>
import { ref } from "vue"
const imgPath = ref("/images/messi.png")
const changeImg = () => {
imgPath.value = "/images/neymar.png"
}
const attrs = {
id: "box1",
class: "hello"
}
const attrName = "title"
const attrValue = "这是一个title属性"
const isDisabled = ""
</script>
<template>
<!--
当我们需要为标签动态的设置属性时,需要使用v-bind指令,
v-bind可以简写为 :
当我们为一个布尔值设置属性时,
如果值为true,则元素上有该属性(转换后为true,也算true)
如果值为false,则元素没有该属性(转换后为false,也算false)
特殊情况:"" 空串,在这里会被当成真值
-->
<!-- <button @click="changeImg">切换图片</button> -->
<img :[attrName]="attrValue" :src="imgPath" alt="梅西" />
<div :="attrs"></div> <!--等价于 <div id="box1" class="hello"></div> -->
<input type="text" :disabled="isDisabled" />
</template>