<template>
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<!-- 瞬间移动
组件中 一些 结构 是放在组件中 写样式 定位时 会受其外层多级父元素的 定位干扰
teleport to 将组件移动到 指定 结构中 这样在写定位至于 这个结构有关系
一般指定 body 这样不受所有起外层组件的干扰 也可以 选择器 .class 指定结构 或 html
-->
<teleport to="body">
<h3>弹窗</h3>
<h3>弹窗</h3>
<h3>弹窗</h3>
<h3>弹窗</h3>
</teleport>
<!--
异步组件 不是异步的组件先出来 异步组件等一等 在出来,且有骨架屛占位
等一等 1 网络慢 2 组件setup返回Promise 里面延迟
1 引入异步组件
2 使用 suspense 包裹异步组件
配制好 默认的具名插槽 default->异步组件 fallback->骨架屏
3 组件的 setup 函数 可以是 Promise
async setup(){
let sum = ref(0)
let D = await new Promise((resolve,reject)=>{
setTimeout(()=>resolve(sum),3000)
})
return D
}
-->
<suspense>
<template v-slot:default>
<hello-world/>
</template>
<template v-slot:fallback>
<h3>我是占位的 骨架屛</h3>
</template>
<suspense />
<router-view />
</template>
<script>
// 1 引入异步组件
import { defineAsyncComponent } from "vue"
// 异步组件包裹 自定义组件 且异步引入
const HelloWorld = defineAsyncComponent(() => import("./components/HelloWorld"))
import {
/* h, */
ref,
reactive,
computed,
watch,
watchEffect,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
toRef,
toRefs,
shallowReactive,
shallowRef,
customRef,
provide,
inject,
isRef,
isReactive,
isReadonly,
isProxy,
} from "vue"
// hook 导入
import usePoint from "./hooks/usePoint"
import HelloWorld from './components/HelloWorld.vue'
// 组合式 API Composition API
// setup 值 是 函数
// setup 是 所有 Composition API 表演的 舞台
// 以前的所有东西 都写在 setup中
export default {
name: "App",
components: { HelloWorld },
props: [],
emits: [],
setup(props, context) {
// data 非响应式的数据
let name = "aa"
// ref函数 使数据变为响应式
// 引用对象 ref将 age 变为一个对象 {value:18}
// 模板解析时 自动 读取了 value值
let age = ref(18)
let age2 = ref(20)
// ref 处理对象类型
const job = ref({
type: "前端",
salary: "100000",
})
// reactive 只能处理对象 数组类型 ,基本类型用ref ref全部可以处理
// refImp job.value=Proxy{type:"",salary:""}
// Proxy job2=Proxy{type:"",salary:""} 直接使用 job2.type
const job2 = reactive({
type: "前端",
salary: "100000",
j: {
s: 10000,
},
})
// methods
function sayHello() {
console.log(`我的名字是${name}年龄是${age}`)
}
// 引用对象 age 变为一个对象 {value:18}
function changeInfo() {
// age 是 refImpl对象 .value 获得值
age.value = 20
// 对象类型 的 修改 job是 refImpl对象 .value 获得值
// job.value=Proxy{type:"",salary:""}
job.value.type = "XXXXX"
job.value.salary = "600000"
job2.salary = "600000"
}
// ref 得到ref对象 必须value reactive 得到Proxy对象直接用
// 所以可以定义一个对象P={ name:"",info:{}} 全部使用 reactive
// Proxy{ name:"",info:{}} 直接使用 p.name p.info.a
// data.d1.XXX
const data = reactive({
d1: {},
person: { name: "张三" },
})
/*
计算属性 computed 要使用
是一个函数 () 调用 传入一个函数 箭头 fun 都可 没有this
返回结果 给 定义
或者直接新增已有对象 key
return 出去
*/
let fullName = computed(() => name + "aaa")
job2.salary2 = computed(() => job2.salary * 100)
let fullName = computed({
set(v) {},
get() {
return name + "aaa"
},
})
// 监视属性 watch 要回调
// 数据源 回调 配置项
// 1 监视 ref一个数据 三个参数 基本数据类型 无需 deep: true
// ref包裹对象类型 1 ref.value==reactive 或 2 deep: true 也可检测到
watch(age, (newValue, oldValue) => {}, { immediate: true })
// 2 监视 ref多个数据 newValue==[新变化的 数组] 或者重复写
watch([age, age2], (newValue, oldValue) => {})
/*
3 监视 reactive 包裹的 对象类型的数据 全部属性
注意 1 无法正确获取 oldValue 都是 newValue 目前无法解决
2 强制开启了 深度监视模式 deep配置无效
*/
watch(job2, (newValue, oldValue) => {})
// 4 监视 reactive 某个属性
// 要求是一个函数的返回值 oldValue有效
watch(
() => job2.type,
(newValue, oldValue) => {}
)
// 5 监视 reactive 某些属性
// 数组模式
watch([() => job2.type, () => job2.salary], (newValue, oldValue) => {})
// 6 深度监视 监视的是reactive对象中某个属性是 一个对象 deep: true
watch(
() => job2.j,
(newValue, oldValue) => {},
{ deep: true }
)
/*
watchEffect 监视效应
1 上来就执行
2 回调函数里面使用谁 就监视了谁的变化
3 像computed 但是 像computed依赖返回值 watchEffect依赖回调执行过程 无需返回值
*/
watchEffect(() => {
let x = name.value
let y = age.value
})
/*
setup 注意点
vue2 中 props没写 $attrs 兜底接收 写了vc接收 $attrs不接收
没有定义slot 但是 父组件 使用子组件传递了 Dom 节点 会在 $slots中接收
setup() 执行时机 在 beforeCreate()之前 this 是 undefined
props:[],组件外部传递过来 且组件内部声明接收的属性
emits:[],
setup(props,context)
context
.attrs $attrs
.slots $slots
.emit $emit context.$emit 触发自定义事件
*/
/*
setup中 实现生命周期
beforeCreate -->created 相当于 setup
setup中的执行时机 先于 配置项的时机
*/
onBeforeMount(() => {})
onMounted(() => {})
onBeforeUpdate(() => {})
onUpdated(() => {})
onBeforeUnmount(() => {})
onUnmounted(() => {})
/*
自定义 hook 函数 把Composition API 进行封装 复用已存在的逻辑
hook.js中 返回值
setup中 调用 接收
setup中 return point
模板使用
组合式API 依靠 hook 提现 将 数据 方法 计算属性 生命周期 分类抽离 导入
hook 是一个 function return {data,methods,computed}
const { data,methods,computed } = usePoint()
*/
let point = usePoint()
/*
toref
return data.person.name 相当于一个单纯的 String 没有响应式
哪个对象 哪个key
该新属性不是新建的 而是还是指向 原数据的 data.person.name
修改同步修改原数据 页面响应
直接 ref(data.adress) 新创建了一个 refImpl对象
点击事件 修改的是return出去的新建数据 页面虽然响应 但是原数据没有被修改
return {name:toRef(data.person, "name")}
*/
toRef(data, "adress") //refImpl对象
toRef(data.person, "name") //refImpl对象
/*
toRefs(data) 将data中所有 属性都变成 refImpl 且指向原数据
return {name:xxx,age:xxx}
return { ...toRefs(data) }
模板中只能省略第一层级的 data. person.name 第二级开始还得.
*/
toRefs(data)
/*
优化时会用
shallowReactive 浅层次的 响应式 只考虑对象第一层数据的响应式{name:"aa",info:{}}
shallowRef 基本数据类型和 ref 一样都是响应式的 没区别
对象类型 不处理为响应式 不借助reactive ,所以ref({ }) 第一层级为value
一般用在 整体替换 整个对象 对象内无需响应式 替换后触发页面更新 refImpl value 替换
readonly 接收一个响应式数据 返回的数据不可以被修改
shallowreadonly 第一层不可修改{name:"aa",info:{}} name不可修改
使用场景 接受别人传过来的数据 只做显示 可以readonly 确保不会修改
toRaw 将响应式数据还原为非响应式 只针对 reactive处理的对象类型
toRaw(data)
markRaw 标记一个对象 使其永远不会是响应式的
data.car = {name:"大众"} data是proxy 添加KEY 是响应式的
data.car = marRaw({}) data.car 就不是响应式的
1 第三方库 不应被设置为响应式
2 复杂的数据 要求还不需要变化 不设为响应式可提高性能
customRef 自定义ref
get track() return value + set value=newValue trigger() 相当于 ref
其他是就是自定义的逻辑
*/
function myRef(value, delay) {
let timer
return customRef((track, trigger) => {
return {
get() {
track() //通知Vue追踪value的变化,不然只有初始化模板才会get一次
return value //模板解析读取
},
set(newValue) {
clearTimeout(timer)
timer = setTimeout(() => {
value = newValue //修改value 值 get中 value被修改
trigger() //通知Vue重新解析模板
}, delay)
},
}
})
}
let data1 = myRef("hello", 500)
/*
祖孙 组件的 数据通信 儿子也可不过 儿子一般props
provide 提供 名字 数据
inject 注入
*/
provide("data", data) //给后代组件传递数据
const data = inject("data") // 后代组件获取数据
/*
响应式数据的判断 API boolean
isProxy Proxy被Readonly修饰后Proxy 仍然是 Proxy
*/
console.log(isRef(name), isReactive(data), isReadonly(data), isProxy(data))
//fragment vue3 可以没有根标签,内部将多个标签包裹在一个Fragment虚拟元素中,减少层级
/*
返回渲染函数 相当于渲染函数中 button替换了 容器#app
return () => h("button", "按钮")
*/
// 返回的是一个对象 对象内配置可以在模板中直接使用
return {
name,
age,
job,
job2,
data,
sayHello,
changeInfo,
fullName,
point,
...toRefs(data),
data1,
}
},
/*
生命周期
beforeUnmount() unmounted() 取代之前的 destroy
*/
mounted() {},
/*
1 全局API的 转移
2 过渡类名的修改
3 移除 keyCode(数字) 作为 v-on 的修饰符 不支持 config.keyCodes
@keyUp.enter 13不行
4 移除 v-on.native 修饰符
@click="increament"
emits: ["close"], 子组件中不添加 就是原生事件,添加了就是自定义事件
5 移除 filter 计算属性 代替也可
*/
}
</script>
vue3 笔记
最新推荐文章于 2024-06-05 23:42:25 发布