ref ¶
定义基础数据类型,如 string, boolean, number
html
<template>
<!-- 模板读取不需要.value -->
<p>{{name}}</p>
<el-button @click="chengeName">改变name</el-button>
</template><template>
<!-- 模板读取不需要.value -->
<p>{{name}}</p>
<el-button @click="chengeName">改变name</el-button>
</template>js
import { defineComponent, ref, Ref } from 'vue';
export default defineComponent({
setup(){
//定义 响应式变量
let name = ref<string>('梁朝伟');
//这种写法也可以 但是这种写法没有上面的简洁
let name2:Ref<string> = ref('110');
//改变 name
let chengeName = () =>{
//修改 ref响应式数据 需要.value
name.value = '120';
}
return {
name,
chengeName
}
}
})import { defineComponent, ref, Ref } from 'vue';
export default defineComponent({
setup(){
//定义 响应式变量
let name = ref<string>('梁朝伟');
//这种写法也可以 但是这种写法没有上面的简洁
let name2:Ref<string> = ref('110');
//改变 name
let chengeName = () =>{
//修改 ref响应式数据 需要.value
name.value = '120';
}
return {
name,
chengeName
}
}
})reactive ¶
定义复杂引用类型数据,如 object, array
html
<template>
<p>{{data.name}}</p>
<el-button @click="chengeData">改变data</el-button>
</template><template>
<p>{{data.name}}</p>
<el-button @click="chengeData">改变data</el-button>
</template>js
import { defineComponent, reactive, toRef, toRefs } from 'vue';
enum SEX{
MAN = '男',
WOMAN = '女'
}
interface IData {
name: string,
age: number,
sex: SEX
}
export default defineComponent({
setup(){
//定义响应式对象数据, let data = reactive<IData> 也可以
let data: IData = reactive({
name: '梁朝伟',
age: 20,
sex: SEX.MAN
});
let chengeData = () =>{
data = {
name: '吴彦祖',
age: 40,
sex: SEX.MAN
}
}
return {
data,
chengeData
}
}
})import { defineComponent, reactive, toRef, toRefs } from 'vue';
enum SEX{
MAN = '男',
WOMAN = '女'
}
interface IData {
name: string,
age: number,
sex: SEX
}
export default defineComponent({
setup(){
//定义响应式对象数据, let data = reactive<IData> 也可以
let data: IData = reactive({
name: '梁朝伟',
age: 20,
sex: SEX.MAN
});
let chengeData = () =>{
data = {
name: '吴彦祖',
age: 40,
sex: SEX.MAN
}
}
return {
data,
chengeData
}
}
})computed ¶
js
import { defineComponent, computed, ref } from 'vue';
export default defineComponent({
setup(){
let count = ref<number>(0);
let getCount = computed(() =>{
return count.value * 10;
});
}
})import { defineComponent, computed, ref } from 'vue';
export default defineComponent({
setup(){
let count = ref<number>(0);
let getCount = computed(() =>{
return count.value * 10;
});
}
})watch ¶
js
import { defineComponent, reactive, ref, watch, watchEffect } from 'vue';
export default defineComponent({
name: 'watch',
setup(){
//监听普通类型
let count = ref(1);
const changeCount = () => {
count.value += 1
};
watch(count, (newValue, oldValue) => { //直接监听
console.log('count改变了:' + newValue + ',' + oldValue);
});
//监听响应式对象
let book = reactive({
name: 'js编程',
price: 50,
data: {
d2: {
age: 10
}
}
});
const changeBookName = () => {
book.name = 'JAVA编程'
};
//指定监听 book.name 属性
watch(()=> book.name,() =>{
console.log('书名改变了')
})
const changeBookAge = () => {
book.data.d2.age = 40
};
//深度监听
watch(()=> book,() =>{
console.log('age改变了')
},{
deep: true,
})
//监听多个值
watch([() => book.name, count], ([name, count], [preName, preCount]) => {
console.log("count或book.name改变了");
});
//监听setup 里所有响应式对象
//1.不需要手动传入依赖
//2.每次初始化时会执行一次回调函数来自动获取依赖
//3.无法获取到原值,只能得到变化后的值
//4.watchEffect 会返回一个用于停止这个监听的函数
const stop = watchEffect(() => {
})
//执行stop 方法可停止 监听
stop()
}
})import { defineComponent, reactive, ref, watch, watchEffect } from 'vue';
export default defineComponent({
name: 'watch',
setup(){
//监听普通类型
let count = ref(1);
const changeCount = () => {
count.value += 1
};
watch(count, (newValue, oldValue) => { //直接监听
console.log('count改变了:' + newValue + ',' + oldValue);
});
//监听响应式对象
let book = reactive({
name: 'js编程',
price: 50,
data: {
d2: {
age: 10
}
}
});
const changeBookName = () => {
book.name = 'JAVA编程'
};
//指定监听 book.name 属性
watch(()=> book.name,() =>{
console.log('书名改变了')
})
const changeBookAge = () => {
book.data.d2.age = 40
};
//深度监听
watch(()=> book,() =>{
console.log('age改变了')
},{
deep: true,
})
//监听多个值
watch([() => book.name, count], ([name, count], [preName, preCount]) => {
console.log("count或book.name改变了");
});
//监听setup 里所有响应式对象
//1.不需要手动传入依赖
//2.每次初始化时会执行一次回调函数来自动获取依赖
//3.无法获取到原值,只能得到变化后的值
//4.watchEffect 会返回一个用于停止这个监听的函数
const stop = watchEffect(() => {
})
//执行stop 方法可停止 监听
stop()
}
})async setup ¶
- 子组件 children.vue
js
import { defineComponent, getCurrentInstance } from 'vue'
export default defineComponent({
name: 'v-children',
async setup() {
//vue this
const { proxy } : any = getCurrentInstance();
//比如获取 某某列表
const d = await proxy.API.xxxList();
if(!d.code){
//获取成功
}
},
})import { defineComponent, getCurrentInstance } from 'vue'
export default defineComponent({
name: 'v-children',
async setup() {
//vue this
const { proxy } : any = getCurrentInstance();
//比如获取 某某列表
const d = await proxy.API.xxxList();
if(!d.code){
//获取成功
}
},
})- 父组件 parent.vue
html
<template>
<div class="v-parent">
<!-- 需要使用 suspense 组件包裹, suspense为vue3 内置组件, 不然vChildren组件会显示不出来 -->
<suspense>
<vChildren />
</suspense>
</div>
</template><template>
<div class="v-parent">
<!-- 需要使用 suspense 组件包裹, suspense为vue3 内置组件, 不然vChildren组件会显示不出来 -->
<suspense>
<vChildren />
</suspense>
</div>
</template>js
import { defineComponent } from 'vue';
//引入子组件
import vChildren from './vChildren';
export default defineComponent({
name: 'v-parent',
components: {
vComponent
},
setup() {}
})import { defineComponent } from 'vue';
//引入子组件
import vChildren from './vChildren';
export default defineComponent({
name: 'v-parent',
components: {
vComponent
},
setup() {}
})父子组件通信 ¶
- 父组件 parent.vue
html
<template>
<div class="parent-children">
<el-button size="medium" type="primary" @click="isShowChildren = true">显示子组件</el-button>
<el-button size="medium" type="primary" @click="handleChildrenShow">调用子组件show方法</el-button>
<vChildren ref="vChildren" v-model:value="isShow" @checkValue="handleCheckValue" />
</div>
</template><template>
<div class="parent-children">
<el-button size="medium" type="primary" @click="isShowChildren = true">显示子组件</el-button>
<el-button size="medium" type="primary" @click="handleChildrenShow">调用子组件show方法</el-button>
<vChildren ref="vChildren" v-model:value="isShow" @checkValue="handleCheckValue" />
</div>
</template>js
import{ defineComponent, computed, reactive, ref } from 'vue';
import vChildren from './children.vue';
export default defineComponent({
name: 'v-children',
components: {
vChildren
},
setup(){
//是否显示子组件
let isShowChildren = ref<boolean>(false);
//子组件 $emit 回调方法
let handleCheckValue = (value: boolean) =>{
isShowChildren.value = value;
}
//vue3 获取dom 节点上的ref 只需定义一个与ref 名称相同的 响应式变量即可
let vChildren = ref(null);
let handleChildrenShow = () =>{
vChildren.value.show()
}
return{
isShowChildren,
handleCheckValue,
vChildren,
show
}
}
})import{ defineComponent, computed, reactive, ref } from 'vue';
import vChildren from './children.vue';
export default defineComponent({
name: 'v-children',
components: {
vChildren
},
setup(){
//是否显示子组件
let isShowChildren = ref<boolean>(false);
//子组件 $emit 回调方法
let handleCheckValue = (value: boolean) =>{
isShowChildren.value = value;
}
//vue3 获取dom 节点上的ref 只需定义一个与ref 名称相同的 响应式变量即可
let vChildren = ref(null);
let handleChildrenShow = () =>{
vChildren.value.show()
}
return{
isShowChildren,
handleCheckValue,
vChildren,
show
}
}
})- 子组件 children.vue
html
<template>
<div class="v-children" v-show="value">
子组件
<el-button size="medium" type="primary" @click="handleCheck">修改父组件值(emit)</el-button>
<el-button size="medium" type="primary" @click="handleCheck2">修改父组件值(直接修改)</el-button>
</div>
</template><template>
<div class="v-children" v-show="value">
子组件
<el-button size="medium" type="primary" @click="handleCheck">修改父组件值(emit)</el-button>
<el-button size="medium" type="primary" @click="handleCheck2">修改父组件值(直接修改)</el-button>
</div>
</template>js
import{ defineComponent } from 'vue';
export default defineComponent({
name: 'v-children',
props: {
value: {
type: Boolean,
required: true
}
},
setup(props, context){
//通过emit回调
let handleCheck = () =>{
context.emit('checkValue', false);
}
//直接通过vue 提供的 update 特性修改
let handleCheck2 = () =>{
context.emit('update:value', false)
}
//子组件方法
let show = () =>{
console.log('子组件show方法');
}
return{
show,
handleCheck,
handleCheck2,
}
}
})import{ defineComponent } from 'vue';
export default defineComponent({
name: 'v-children',
props: {
value: {
type: Boolean,
required: true
}
},
setup(props, context){
//通过emit回调
let handleCheck = () =>{
context.emit('checkValue', false);
}
//直接通过vue 提供的 update 特性修改
let handleCheck2 = () =>{
context.emit('update:value', false)
}
//子组件方法
let show = () =>{
console.log('子组件show方法');
}
return{
show,
handleCheck,
handleCheck2,
}
}
})slot ¶
- 子组件 children.vue
html
<template>
<div class="v-children">
<header>
<slot name="header" />
</header>
<div class="v-body">
<slot name="body">
hello body
</slot>
</div>
<footer>
<slot name="footer" />
</footer>
</div>
</template><template>
<div class="v-children">
<header>
<slot name="header" />
</header>
<div class="v-body">
<slot name="body">
hello body
</slot>
</div>
<footer>
<slot name="footer" />
</footer>
</div>
</template>- 父组件 parent.vue
html
<vChildren>
<!-- v-solt:header 缩写为 #header -->
<template #header>
头部
</template>
<template #footer>
底部
</template>
</vChildren><vChildren>
<!-- v-solt:header 缩写为 #header -->
<template #header>
头部
</template>
<template #footer>
底部
</template>
</vChildren>vue hook ¶
- vue3 hook相当于vue2 的mixin, 不同于hook是函数
- vue3 hook能让我提高代码复用性
- 让函数拥有组件的特性
useMousePosition.ts
js
import { onMounted, onUnmounted, ref } from 'vue';
//点击窗口获取 鼠标 x y 坐标
function useMousePosition(){
const x = ref(0);
const y = ref(0);
const clickHandler = (e: MouseEvent) =>{
x.value = e.pageX;
y.value = e.pageY;
}
onMounted(() =>{
window.addEventListener('click', clickHandler);
})
onUnmounted(() =>{
window.removeEventListener('click', clickHandler);
})
return{
x,
y
}
}
export default useMousePosition;import { onMounted, onUnmounted, ref } from 'vue';
//点击窗口获取 鼠标 x y 坐标
function useMousePosition(){
const x = ref(0);
const y = ref(0);
const clickHandler = (e: MouseEvent) =>{
x.value = e.pageX;
y.value = e.pageY;
}
onMounted(() =>{
window.addEventListener('click', clickHandler);
})
onUnmounted(() =>{
window.removeEventListener('click', clickHandler);
})
return{
x,
y
}
}
export default useMousePosition;useWindowResize.ts
js
import { onMounted, onUnmounted, ref } from 'vue';
//窗口尺寸改变 实时获取窗口宽高
function useWindowResize(){
const width = ref(0);
const height = ref(0);
const onResize = () =>{
width.value = window.innerWidth;
height.value = window.innerHeight;
}
onMounted(() =>{
onResize();
window.addEventListener('resize', onResize);
})
onUnmounted(() =>{
window.removeEventListener('resize', onResize);
})
return{
width,
height
}
}
export default useWindowResize;import { onMounted, onUnmounted, ref } from 'vue';
//窗口尺寸改变 实时获取窗口宽高
function useWindowResize(){
const width = ref(0);
const height = ref(0);
const onResize = () =>{
width.value = window.innerWidth;
height.value = window.innerHeight;
}
onMounted(() =>{
onResize();
window.addEventListener('resize', onResize);
})
onUnmounted(() =>{
window.removeEventListener('resize', onResize);
})
return{
width,
height
}
}
export default useWindowResize;组件中使用
html
<template>
<div class="hook">
窗口尺寸
<p>宽: {{width}}</p>
<p>高: {{height}}</p>
点击窗口获取 鼠标 x y 值
<p>x: {{x}}</p>
<p>y: {{y}}</p>
</div>
</template><template>
<div class="hook">
窗口尺寸
<p>宽: {{width}}</p>
<p>高: {{height}}</p>
点击窗口获取 鼠标 x y 值
<p>x: {{x}}</p>
<p>y: {{y}}</p>
</div>
</template>js
import { defineComponent } from 'vue';
import useWindowResize from '@/hook/useWindowResize';
import useMousePosition from '@/hook/useMousePosition';
export default defineComponent({
name: 'hook',
setup(){
const { width, height } = useWindowResize();
const { x, y } = useMousePosition();
return{
width,
height,
x,
y
}
}
})import { defineComponent } from 'vue';
import useWindowResize from '@/hook/useWindowResize';
import useMousePosition from '@/hook/useMousePosition';
export default defineComponent({
name: 'hook',
setup(){
const { width, height } = useWindowResize();
const { x, y } = useMousePosition();
return{
width,
height,
x,
y
}
}
})provide/inject 依赖注入 ¶
当一个负责页面业务逻辑负责, 需要根据业务拆分成很多子组件编写, 当顶层父组件有个数据需要逐层传递到 子组件,孙组件, ... 的时候. 当然使用 prop 也是可以的, 但是需要在 子组件,孙组件, ... 都要定义prop 缺点: 会存在命名冲突问题, 命名上谨慎处理好
父组件
html
<template>
<div class="provide-inject">
provide-inject
<vChildren />
</div>
</template><template>
<div class="provide-inject">
provide-inject
<vChildren />
</div>
</template>js
import { defineComponent, provide } from 'vue';
import vChildren from './children.vue';
export default defineComponent({
name: 'provide-inject',
components: {
vChildren
},
setup(){
//注入 一个字符串
provide('role', '超级管理员');
//注入 一个对象
provide('userInfo', {
name: '梁朝伟',
age: 20,
sex: '男'
});
return{
}
}
})import { defineComponent, provide } from 'vue';
import vChildren from './children.vue';
export default defineComponent({
name: 'provide-inject',
components: {
vChildren
},
setup(){
//注入 一个字符串
provide('role', '超级管理员');
//注入 一个对象
provide('userInfo', {
name: '梁朝伟',
age: 20,
sex: '男'
});
return{
}
}
})子组件
html
<template>
<div class="v-children">
子组件
<p>角色: {{role}}</p>
<p>姓名: {{userInfo.name}}</p>
<p>年龄: {{userInfo.age}}</p>
<p>性别: {{userInfo.sex}}</p>
</div>
</template><template>
<div class="v-children">
子组件
<p>角色: {{role}}</p>
<p>姓名: {{userInfo.name}}</p>
<p>年龄: {{userInfo.age}}</p>
<p>性别: {{userInfo.sex}}</p>
</div>
</template>js
import{ defineComponent, inject } from 'vue';
export default defineComponent({
name: 'v-children',
setup(){
//获取顶层组件注入的 role
const role = inject('role');
//获取顶层组件注入的 role
const userInfo = inject('userInfo');
return{
role,
userInfo
}
}
})import{ defineComponent, inject } from 'vue';
export default defineComponent({
name: 'v-children',
setup(){
//获取顶层组件注入的 role
const role = inject('role');
//获取顶层组件注入的 role
const userInfo = inject('userInfo');
return{
role,
userInfo
}
}
})Teleport ¶
html
//teleport 组件包裹 可以通过to参数设置 teleport内的内容渲染到指定位置
//body 只指渲染到 body 节点下, 参数值还可以是 id 和 class
//disabled 参数可以设置 是否开启指定渲染操作 值为 true false
<teleport to="body" :disabled="displayVideoInline">
<div>
内容
</div>
</teleport>//teleport 组件包裹 可以通过to参数设置 teleport内的内容渲染到指定位置
//body 只指渲染到 body 节点下, 参数值还可以是 id 和 class
//disabled 参数可以设置 是否开启指定渲染操作 值为 true false
<teleport to="body" :disabled="displayVideoInline">
<div>
内容
</div>
</teleport>