1.setup方法
setup() 函数是vue3中专门新增的方法,可以理解为 Composition Api 的入口
# src/Views/Home.vue
# 1、创建setup方法
# 1.1、创建一个常量
# 1.2、必须 return 返回,才能给模版使用
<template>
<div>
<div>{{ data }}</div>
</div>
</template>
<script>
export default {
name: "Home",
setup() {
const data = 10;
return {
data
}
}
};
</script>
# 2、点击方法,不能使用
<template>
<div>
<div>{{ data }}</div>
<button @click="data++">加++</button>
</div>
</template>
<script>
export default {
name: "Home",
setup() {
const data = 10;
return {
data
}
}
};
</script>
# 3、reactive 返回对象的响应式副本
# 所有的 api 都是方法、函数
<template>
<div>
<div>{{ data.number }}</div>
# 3.2、使用 reactive 方法创建的数据,就能相应了
<button @click="data.number++">加++</button>
# 3.3、执行方法
<button @click="jian()">减++</button>
</div>
</template>
<script>
# 3.1、引入 reactive 方法
import {reactive} from 'vue';
export default {
name: "Home",
setup() {
# 3.2、使用reactive方法,创建数据
const data = reactive({
number : 10
})
# 3.4、创建方法
const jian = () => {
data.number--;
}
# 3.5、方法也要return
return {
data,
jian
}
}
};
</script>
# 4、计算属性
<template>
<div>
<div>{{ data.number }}</div>
# 4.3、使用数据
<div>{{ data.jisuan }}</div>
<button @click="data.number++">加++</button>
<button @click="jian()">减++</button>
</div>
</template>
<script>
# 4.1、引入 computed 方法
import {reactive,computed} from 'vue';
export default {
name: "Home",
setup() {
# 4.2、computed 计算属性
const data = reactive({
number : 10,
jisuan : computed( ()=>data.count * data.count )
})
const jian = () => {
data.number--;
}
return {
data,
jian
}
}
};
</script>
# 5、组合使用
<template>
<div>
<div>{{ name }}</div>
<div>{{ data.number }}</div>
<div>{{ data.jisuan }}</div>
<button @click="data.number++">加++</button>
<button @click="jian()">减++</button>
</div>
</template>
<script>
import {reactive,computed} from 'vue';
export default {
name: "Home",
# 5.1、可以和之前学的参数 共生
data() {
return {
name: "php中文网"
}
},
# 5.2、components 导入组件,还是得用原来的
components:{
},
setup() {
const data = reactive({
number : 10,
# 5.3、使用 this 报错
jisuan : computed( ()=>this.count * this.count )
jisuan : computed( ()=>data.count * data.count )
})
const jian = () => {
data.number--;
}
return {
data,
jian
}
}
};
</script>
# 6、setup 方法里没 this,因为它是最先运行的
<template>
<div>
<div>{{ name }}</div>
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
name: "php中文网"
}
},
# 6.1、打印结果是 setup 先运行
beforeCreate() {
console.log("beforeCreate");
# 6.2、这个打印this.name,空值,但不报错,说明有this
console.log(this.name);
},
created() {
console.log("created");
# 6.3、这个打印this.name,就有值,说明已经运行了data
console.log(this.name);
},
beforeMount() {
console.log("beforeMount");
},
setup() {
console.log("setup");
# 6.4、这个打印this.name,就会报错,说明没有this,就是这样设计的
console.log(this.name);
}
};
</script>
# 7、Home.vue 文件引入 One.vue组件
<template>
<div>
# 7.1、使用one组件,传2个值
<one one="1111" two="2222"></one>
# 7.7、使用one组件,传4个值,前2个值会被props接收,后2个值不会被props接收
<one one="1111" two="2222" three="3333" four="4444"></one>
# 7.8、插槽
<one one="1111" two="2222" three="3333" four="4444">
<div>这是插槽</div>
</one>
</div>
</template>
<script>
import One from "../components/One";
export default {
components: {
One
}
};
</script>
# 7.2、创建个组件 src/components/One.vue
<template>
<div>
one = {{ one }}
two = {{ two }}
# 7.9、插槽位置
<slot>插槽</slot>
</div>
</template>
<script>
export default {
name: "One",
# 7.3、接收2个传值
props: {
one: {
type: String,
},
two: {
type: String,
}
},
# 7.4、在setup里不能使用this,就无法使用props的数据
# 7.5、setup方法,第一个参数:就是props里接收的数据,参数名可以更改
# 7.6、第二个参数:没有被props接收的数据,未声明的数据。比如7.7多传2个参数
setup(props,context) { // setup(props,{attrs,slots}) 也可以结构赋值 展开
console.log(props);
console.log(context); // 里面有attrs参数,就是未接收的数据
console.log(context.attrs); // Attribute (非响应式对象,等同于 $attrs)
console.log(context.slots); // 插槽 (非响应式对象,等同于 $slots)
console.log(context.emait); // 触发事件 (方法,等同于 $emit)
console.log(context.expose); // 暴露公共 property (函数)
# 7.10、打印插槽数据
console.log(context.slots.default());
}
};
</script>
2.常用API
# 1、setup里不能使用this,数据也不能改变(非响应式)
<template>
<div>
<div>{{ num }}</div>
<button @click="num++">加++</button>
</div>
</template>
<script>
export default {
setup() {
let num = 10
return {
num
}
}
};
</script>
# 2、ref 接受一个内部值并返回一个响应式且可变的 ref 对象
<template>
<div>
<div>{{ num }}</div>
<button @click="num++">加++</button>
<button @click="add()">js加++</button>
</div>
</template>
<script>
import {ref} from 'vue';
export default {
setup() {
# 2.1、使用ref方法处理后,就变为响应式了
let num = ref(10)
# 2.2、用方法处理,没效果
const add = () => {
num++
# 2.3、打印后,发现里面有个value
console.log(num)
# 2.4、所以要使用 .value
num.value++
}
return {
num,
add
}
}
};
</script>
# 3、reactive 函数接收一个普通对象,返回一个响应式的数据对象
<template>
<div>
<div>{{ data1.num }}</div>
<button @click="add1()">加++</button>
<div>{{ data2.num }}</div>
<button @click="add2()">加++</button>
</div>
</template>
<script>
import { ref, reactive } from "vue";
export default {
setup() {
# 3.1、ref 创建数据
let data1 = ref({
num: 10
})
const add1 = () => {
console.log(data1)
data1.value.num++
}
# 3.2、reactive 创建数据
let data2 = reactive({
num: 10
})
const add2 = () => {
# 3.2.1、打印后,就会少一层.value
console.log(data2)
data2.num++
}
# 3.3、返回值在模版中,会多一层 {{data1.num}},之前是 {{num}}
return {
data1,
data2,
add1,
add2
}
}
};
</script>
# 4、使用结构赋值,就可以减少一层,但是会导致 数据不能相应
<template>
<div>
<div>{{ data2.num }}</div>
<div>{{ num }}</div>
# 4.1、点击后,{{num}}不变,不是响应式的了
<button @click="add2()">加++</button>
</div>
</template>
<script>
# 4.2、引入 toRefs 方法:返回时转换为ref,在不丢失响应性的情况下对返回的对象进行解构/展开
import { reactive,toRefs } from "vue";
export default {
setup() {
let data2 = reactive({
num: 10,
name : "欧阳克"
})
const add2 = () => {
data2.num++
}
return {
data2,
add2,
...data2,
...toRefs(data2) // toRefs 返回时转换为ref
}
}
};
</script>
# 5、readonly 接受一个对象 (响应式或纯对象) 或 ref 并返回原始对象的只读代理
# 5.1、isRef 检查值是否为一个 ref 对象
<template>
<div>
<div>{{ read.num }}</div>
<button @click="add()">加++</button>
</div>
</template>
<script>
import { reactive, ref, readonly, isRef } from "vue";
export default {
setup() {
let data = reactive({
num: 10,
name: "欧阳克",
});
# 5.2、readonly 方法把data数据,设置为只读
const read = readonly(data);
read.num++; // 会报错
const add = () => {
read.num++; // 会报错
};
# 5.3、如果是ref创建的数据,isRef就会返回true
let data1 = ref(10);
console.log(isRef(data1));
return {
read,
add,
};
}
};
</script>
3.侦听API
# 1、watch 侦听数据的改变
<template>
<div>
<div>a = {{ a }} b = {{ b }}</div>
<button @click="a++">a++</button>
<button @click="b++">b++</button>
</div>
</template>
<script>
import { reactive, ref, watch } from "vue";
export default {
setup() {
let a = ref(0)
let b = ref(0)
# 1.1、默认情况下,它有惰性的,只有当被侦听的源发生变化时才执行回调
watch(() => {
console.log(a)
console.log(a.value)
console.log(b.value)
})
# 1.2、侦听单个数据源
watch(a, () => {
console.log(a);
console.log(a.value);
});
# 1.3、新老值
watch(a, (new_a, old_a) => {
console.log("新:" + new_a);
console.log("老:" + old_a);
});
# 1.4、侦听多个数据源
watch([a,b], () => {
console.log(a.value);
console.log(b.value);
});
# 1.5、新老值
watch([a,b], ([new_a,new_b],[old_a,old_b]) => {
console.log('a新值:'+new_a+',a老值:'+old_a);
console.log('b新值:'+new_b+',b老值:'+old_b);
});
return {
a,
b
}
}
};
</script>
# 2、侦听对象
<template>
<div>
<input type="text" v-model="name"/><br>
<input type="text" v-model="age"/><br>
</div>
</template>
<script>
import { reactive, ref, watch, toRefs } from "vue";
export default {
setup() {
const obj = reactive({
name : "欧阳克",
age : 38
})
# 2.1、对象数据改变,会被侦听。侦听对象里的全部数据
watch(obj, () => {
console.log(obj.name);
console.log(obj.age);
})
# 2.2、侦听对象里的单个数据
# 2.2.1、之间写对象里的数据,会报错
watch(obj.age, () => {
console.log(obj.age);
})
# 2.2.2、参数写成方法
watch(()=>obj.age, () => {
console.log(obj.age);
})
# 2.2.3、多个参数
watch([()=>obj.age,()=>obj.name], () => {
console.log(obj.age);
console.log(obj.name);
})
return {
...toRefs(obj)
}
}
};
</script>
# 3、watchEffect 侦听数据的改变,默认会执行一次
<template>
<div>
<div>a = {{ a }} b = {{ b }}</div>
<button @click="a++">a++</button>
<button @click="b++">b++</button>
</div>
</template>
<script>
import { reactive, ref, watch, watchEffect } from "vue";
export default {
setup() {
let a = ref(1)
let b = ref(2)
watchEffect(() => {
console.log(a)
console.log(a.value)
console.log(b.value)
})
return {
a,
b
}
}
};
</script>
4.在组合API中provide和inject使用
# 1、src/Views/Home.vue 文件
<template>
<div>
<div>{{ name }}</div>
<one></one>
</div>
</template>
<script>
import { ref } from "vue";
import One from "../components/One";
export default {
components: {
One
},
data() {
return {
name: ref("欧阳克")
}
},
provide() {
return {
name: "欧阳克",
name: this.name // 还可以用data里的变量
}
}
};
</script>
# 1.1、创建儿子文件:src/components/One.vue文件
<template>
<div>
<div>这是one</div>
<two></two>
</div>
</template>
<script>
import Two from "../components/Two";
export default {
name: "One",
components: {
Two
}
};
</script>
# 1.2、创建孙子文件:src/components/Two.vue文件
# 1.2.1、使用 inject 参数,获取它爷爷的数据
<template>
<div>
<div>这是two {{ name }}</div>
</div>
</template>
<script>
export default {
name: "Two",
inject: ["name"]
};
</script>
----------------------------------------
# 2、在组合API中provide和inject使用
# 2.1、src/Views/Home.vue 文件
<template>
<div>
<div>{{ name }}</div>
<one></one>
</div>
</template>
<script>
import { ref, provide } from "vue";
import One from "../components/One";
export default {
components: {
One
},
setup() {
let name = ref("欧阳克");
provide("name", name)
}
};
</script>
# 2.2、src/components/Two.vue文件
<template>
<div>
<div>这是two {{ name }}</div>
</div>
</template>
<script>
import { inject } from "vue";
export default {
name: "Two",
setup() {
let name = inject("name");
return {
name
}
},
};
</script>
5.路由
# 1、获取路由:useRoute, useRouter (要在 setup 函数中访问路由,请调用 useRouter 或 useRoute 函数)
<template>
<div>
<div>欧阳克</div>
</div>
</template>
<script>
import { useRoute, useRouter } from "vue-router";
export default {
setup() {
const route = useRoute();
const router = useRouter();
console.log(route);
console.log(route.fullPath);
console.log(route.query);
console.log(route.params);
console.log(router);
router.push({
path : "/new",
query: { id:10 }
});
}
};
</script>
# 2、获取vuex状态管理器:useStore
<template>
<div>
<div>欧阳克</div>
</div>
</template>
<script>
import { useStore } from "vuex";
export default {
setup() {
const store = useStore();
console.log(store);
console.log(store.state.num);
}
};
</script>
# 2.1、/src/store/index.js 文件
import { createStore } from "vuex";
const state = {
num: 10,
};
export default createStore({
state
});