Vue3 文档学习笔记
vue3学习笔记
setup()
生命周期的与vue2的不同点在:beforeCreated
、created
都在setup()
里进行默认调用,其他的都要写在setup()
里面,算做compositionAPI
。
props
由父组件传过来的值会自动被响应式,不用再去reactive包一层(注意不能在子组件里直接修改props的值)。
setup()
的第一个参数是props
(不可进行解构,否则会丢失双向绑定),第二个参数是context
,有3个值 attrs
,slots
,emit
,(可进行解构)
props: {name: String,num: Number
},
setup (props, ctx) {props.name // 获取props的name的值ctx.emit('add', value) // 在子组件中使用emit像父组件传递值,与vue2中的this.$emit()有较大区别
}
watch()
监听两个回调函数,第一个函数return
你要监听数据,第二个函数有参数new Value
,然后执行你的操作。
reactive, ref
return
出去的ref
数据在template
里不用.value
去调用。
如果将一个对象通过ref
创建,那么会通过reactive
进行创建。
const person = ref({name: '李四',info: {age: 11,height: 174}
})
console.log(person.value) // 会打印一个Proxy对象,说明是通过reactive创建的
如果在reactive
里访问/修改ref
,它会自动展开ref
,也就是自动给你.value
const count = ref(0)const state = reactive({count
})console.log(state.count)
如果在reactive
里放的是Array
或者原生集合(比如Map
),他们取值都必须加上.value
,不会自动展开
const arr = reactive([ref(100),2])console.log(arr[0].value)
unref
如果是ref
对象就返回通过reactive
创建的数据,如果是普通对象,就直接返回
const info = {name: '李四',age: 22
}
const info2 = ref({name: '李四',age: 22
})
console.log(unref(info)) // {name: '李四', age: '22'}
console.log(unref(info2)) // Proxy{name: '李四', age: '22'}// unref就等同于 isRef(info) ? info.value : info
toRef
可以通过toRef
把reactive
响应源数据(source property
)里的值单独拿出来使用。转引用一下,用的对方不多。官方示例是对自己写的composition API
进行传值。
const toRef1 = reactive({name: 'xx',age: 11
})
const nameRef = toRef(toRef1, 'name')
nameRef.value = '徐忠炜'
console.log(toRef1.name) // 徐忠炜
toRefs
获取源数据所有数据。在template
里直接写属性名就可以使用
<template><h1> {{count}} </h1>
</template>
export default {name: 'App',setup(props, ctx) {const state = reactive({count: 4})return {...toRefs(state)}}
}
customRef
用于防抖节流(图片懒加载、边输入边请求接口的场景)。
computed (API)
跟vue2一样的用法
// 这里用的get
const hello = ref('先生,欢迎来到红浪漫会所。')
const xiaogege = computed(() => {return `徐忠炜${hello.value}`
})
console.log(xiaogege.value) // 徐忠炜先生,欢迎来到红浪漫会所。
readonly
让响应式数据或者普通对象都只读,并且是深层的(DEEP)
const read = reactive({a:1,b: {c: 3,d: [3,4,5,6]}
})
const readOnly = readonly(read)
console.log(readOnly.a) // 1
readOnly.a = 3 // Set operation on key "a" failed: target is readonly.
watchEffect
watchEffect
会立即执行(在onBeforeMount之前),并响应式的追踪当前watchEffect
里的依赖(数据),并且只要数据改变了它就重新执行一次。当watchEffect
写在setup()
或生命周期
里时,在该组件被销毁时它会自动停止监听。
watchEffect
还返回一个stop,用于我们手动停止监听。
const stop = watchEffect(() => {// do something
})// later
stop()
Side Effect Invalidation(副作用失效时)
在watchEffect
即将重新执行/stop时会执行一次onInvalidate
方法,watchEffect
接收一个onInvalidate
参数,其实onInvalidate
是一个函数,这个函数的执行顺序是先与watchEffect
里面其他所有的程序。
以后慢慢消化SideEffect
const count = ref(0)count.value = 1const stop = watchEffect((onInvalidate) => {console.log(count.value)onInvalidate(() => {console.log('onInvalidate is triggered')})
})
// 打印结果
// 0
// onInvalidate is triggered
// 1
2020-12-03 听至 21p https://www.bilibili.com/video/BV1Q54y1k7At?p=21
watchEffect
刷新时间是在所有组件刷新之前调用。也就是执行顺序基本在最前面。
watchEffect
的第二个对象(OPTIONS),默认是pre
,还有post
,sync
。具体解释看下面
watchEffect(() => {console.log(count.value)
}, {flush: 'pre' // 呼应上面的话,pre是默认在所有组件刷新之前调用flush: 'post' // post是默认在所有组件刷新之后调用,第一次在onBeforeMount之后调用(onMounted之前),之后改变在onbeforeUpdate之后调用(onUpdate之前)flush: 'sync' // 同步执行
})
watchEffect
第一次执行时是在mounted
之前,如果你要操作DOM
或者Template refs
请把watchEffect
放在onMounted
生命周期里
<template><h1 ref='myRef'></h1>
</template>
export default {name: 'App',setup(props, ctx) {const myRef = ref(null)watchEffect(() => {console.log(myRef.value)})return {myRef}}
}
//打印结果
// null
// <h1></h1> (dom)// 如果放在onMounted里面
onMounted(() => {watchEffect(() => {console.log(myRef.value)})
})
// 打印结果
// <h1></h1> (dom)
watch
watch
必须监听一个数据,还得有一个回调函数去处理数据
watch(() => {return count.value
}, (newValue, oldValue) => {// 源数据改变才执行(懒执行)
})
watch监听单一数据有两种写法
// watching a getter
const state = reactive({count: 0})
watch(() => state.count,(newValue, oldValue) => {// do something!}
)// watch a ref
const count = ref(0)
watch(count, (newValue,oldValue) => {// do something!
})
watch监听多个源数据
const foo = ref(1)
const bar = ref(2)setTimeout(() => {foo.value = 11bar.value = 22
}, 2000)// 监听要加上.value
watch(() => [foo.value, bar.value], ([newFoo, newBar], [oldFoo, oldBar]) => {// do something!
})
watch
的执行顺序和watchEffect
一样,配置参数也一样,详情往前翻。
isProxy
只有reactive
和readonly
创建的对象才能被isProxy
验证为true
即使new Proxy
创建的也为false*
isReactive
一个readonly
对象用isReactive
验证为false
const plain = readonly({name: 'Mary'
})
console.log(isReactive(plain)) // false
如果将一个reactive
对象用readonly
再包一下,那么验证为true
const state = reactive({name: 'John'
})
const stateCopy = readonly(state)
console.log(isReactive(stateCopy)) // true
shallowReactive
很简单,就是浅的响应式,说明嵌套的对象不会被代理,也就是没有响应式
markRaw
以后记得多看,现在用不到
生命周期
Options API LifeCycle
与 Composition API LifeCycle
的映射关系
Options API LifeCycle | Composition API LifeCycle |
---|---|
beforeCreate | setup() |
created | setup() |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
update | onUpdate |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
setup()
代替了beforeCreate
和create
钩子,之前要写在他们里的东西现在只需写在setup()
里面。
组件卸载时可在onbeforeUnmount
和onUnmounted
里处理一些事件。
在onErrorCaptured
里捕获子孙组件的异常错误,也就是可以在父组件看到子组件的错误。
onRenderTracked
函数里写debugger
即可进入调试模式(组件第一次render时)。
onRenderTriggered
函数里写debugger
即可进入调试模式(rerender时)。
provide/inject (option API)
通常,父子组件传值我们用props。但想象一种情况,当有嵌套比较深的子组件时,比如是个孙组件,那么我们传值必须通过父 -> 子 -> 孙,这样非常麻烦。
为了解决这个情况,我们可以使用provide
和inject
。
举个例子:
RootTodoListTodoItemTodoListFooterClearTodoButtonTodoListStatistics
如果我们想把数据从TodoList
传到TodoListStatistics
,需经过TodoList
->TodoListFooter
->TodoListStatistics
,但使用provide/inject,我们可以这样做:
// 祖先组件
export default {name: 'TodoList',provide: {name: '徐忠炜'}
}// 孙组件
<template>{{ name }}
</template>
export default {name: 'TodoListStatistics',inject: ['name']
}
!如果我们尝试传递一些组件的实例(绑定在this上),那么它是不会工作的。
如果实在要传实例,那么可以这样写(其实也更推荐这样写,就跟Vue2的data
一样)
provide() {return {name: this.name}
}
之前这么做,它的数据是不会有响应式的。因为绑定的
provide/inject
默认是不被响应的。在Vue2中我们把数据用computed包起来就可以让它变成响应式
provide() {return {name: Vue.computed(() => '张三')}
}
provide/inject (composition API)
普通用法与optionAPI
的一样
在setup()里使用provide
provide
允许你定义两个参数,第一个是属性名(<string>
),第二个是属性值
setup() {// 可定义多个provide('name', '张三')provide('age', 22)provide('lover', {name: '陈诗诗',xiongwei: '70D'})
}
在setup()里使用inject
inject
允许你填两个参数,第一个是属性名,第二个是默认值(可选)。使用值时要加.value
setup() {const name = inject('name')const age = inject('age', 18)const lover = inject('lover')return {name,age,lover}
}
自带响应式,不用像Vue2里面那样去解决响应式的问题
如果要在inject
的那个子组件去改变传递的数据,最好的解决方式是在父组件provide
一个方法,方法里面去改变那个值
setup() {const lover = ref('nobody')const updateLover = () => {lover.value = null}provide('updateLover', updateLover)
}
// 子组件还是一样的方法去获取。完美!
还有,如果你为了杜绝在子组件不小心修改了传递的数据,那么你provide数据的时候给数据加个readonly
provide('name',readonly(name))
2020-12-09学习到 refs https://www.bilibili.com/video/BV1Q54y1k7At?p=36
refs (composition API)
在setup()
里声明一个refs
,然后导出,在视图里进行绑定。
// Child.vue
<template><h1> {{ name }} </h1><button @click='changeName'>changeName</button>
</template>
setup() {const child = ref(null) const name = ref('张三')const changeName = () => {console.log(child.value) // 打印的domchild.value.innerText = '李四'}return {child,changeName}
}// 如果想在父组件调用子组件的方法或数据
// Father.vue
<template><child ref='child'></child>
</template>
setup() {const child = ref(null)console.log(child.value.name) // 张三
}
遍历生成refs
<div v-for='(item, i) in list' :ref='el => { if (el) divs[i] = el }'></div>setup() {const divs = ref([])onMounted(() => {console.log(divs.value) // 打印出经过代理的dom节点})
}
Application Config
Application Config
const app = Vue.createApp({})
app.config = {...
}
errorHandler
// 基本用不到
app.config.errorHandler = (err, vm, info) => {// handle error// 'info' 是Vue的特别的错误信息,比如生命周期呀。
}
warnHandler
// 基本用不到
app.config.warnHandler = (msg, vm, trace) => {// 在运行时产生的一些警告// 'trace'
}
global properties
添加一个全局属性,在任何组件实例里都能引用
app.config.globalProperties.foo = 'bar'app.component('child-component', {mounted() {console.log(this.foo) // 'bar'}
})
就相当于在Vue2.x中,我们往Vue实例上绑东西是这样的
Vue.prototype.$axios = axios
在Vue3中,应该这样做
const app = Vue.createApp({})
app.config.globalProperties.$axios = axios
在组件中调用全局属性
// main.js
app.config.globalProperties.token = 'aofhbioasdlfbnislfbsdkl'// App.vue
// 获取globalProperties
const instace = getCurrentInstance()
console.log(`全局的token:${instace.ctx.token}`)
isCustomElement
使用方法,不报错的。
// vue.config.js
module.exports = {vueCompilerOptions: {isCustomElement: tag => /^jsjiajia-/.test(tag)}
}
Application API
const app = Vue.createApp({})
component 全局注册组件
app.component('componentName', component)
directive 自定义指令
实例一:不使用自定义指令,实现tab栏切换
<template><div class='tab' @click='handleTabClick($event)'><button data-index='0' :class='['tab-btn', {'active': curIndex === 0}]'></button><button data-index='1' :class='['tab-btn', {'active': curIndex === 1}]'></button><button data-index='2' :class='['tab-btn', {'active': curIndex === 2}]'></button></div>
</template>
export default {setup() {const curIndex = ref(0)const handleTabClick = e => {const tar = e.targetconst className = tar.classNameconst index = parseInt(tar.dataset.index)if (className === 'tab-btn') {curIndex.value = index}}return {curIndex,handleTabClick}}
}
实例二:使用自定义指令
<template><div class='tab' @click='handleTabClick($event)' v-tab="{ className: 'tab-btn', activeClass: 'active', curIndex}"><button data-index='0' class='tab-btn'></button><button data-index='1' class='tab-btn'></button><button data-index='2' class='tab-btn'></button></div>
</template>
<script>import tab from './tab.js'export default {directive: {tab},setup() {const curIndex = ref(0)const handleTabClick = e => {const tar = e.targetconst className = tar.classNameconst index = parseInt(tar.dataset.index)if (className === 'tab-btn') {curIndex.value = index}}return {curIndex,handleTabClick}}}
</script>// tab.js
export default {mounted(el,binding) {// el是指令挂载的对象// binding对象的value包含了传过来的值 binding.value.activeClassconst { className, activeClass, curIndex } = binding.valueconst btns = el.getElementsByClassName(className)btns[curIndex].className += ` ${activeClass}`},update(el,binding) {const { className, activeClass, curIndex } = binding.valueconst { oldIndex } = binding.oldValueconst btns = el.getElementsByClassName(className)btns[oldIndex].className = classNamebtns[curIndex].className += ` ${activeClass}`}
}
Vue3 文档学习笔记相关推荐
- 【ember zigbee】序章:协议栈相关文档学习笔记
原文地址:https://blog.csdn.net/tainjau/article/details/90648114 文章目录 写在前面 一.材料出处 二.文档解析 2.1.EZSP Protoco ...
- python定义函数的组成部分有_Python文档学习笔记(4)--定义函数
定义函数 关键字 def 引入函数的定义.其后必须跟有函数名和以括号标明的形式参数列表.组成函数体的语句从下一行开始,且必须缩进. 执行 一个函数会引入一个用于函数的局部变量的新符号表. 因此,在函数 ...
- IAM 策略文档学习笔记
策略文档 IAM 许可策略 附加到确定角色可执行哪些任务的角色.将许可限定为仅角色需要进行的操作,以及仅为进行这些操作角色需要的资源.您可以使用 AWS 管理的或客户创建的 IAM 许可策略 操作:您 ...
- w3schools文档学习笔记 - XML
http://www.w3school.com.cn/xml/xml_syntax.asp 在 XML 中,省略关闭标签是非法的.所有元素都必须有关闭标签 声明不属于XML本身的组成部分.它不是 XM ...
- Django1.10文档学习笔记二
创建应用 1 创建project Django-admin startproject mysite 自动创建目录结构: mysite/ #项目容器 Manage.py #命令行工具 mys ...
- Unity Shader unity文档学习笔记(十一):战争迷雾核心算法
核心算法 非常简单 主要就是把一个点的世界坐标转换到贴图的UV坐标 给整个场景一个大的plane 加上写的shader 摄像机位置调成plane的正上方 Shader "Unlit/FogR ...
- Unity Shader unity文档学习笔记(十七):径向模糊 实现类似冲锋时的速度感
实现思路:离中心点越远的像素 模糊效果越明显 UV偏移的量越大 shader // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'Uni ...
- Vue3项目搭建学习笔记
Vue3项目搭建学习笔记 参考王红元老师vue课程 创建项目 vue create vue3-ts-cms 项目搭建规范 集成editorconfig配置 VSCode需要安装一个插件:EditorC ...
- FreeRTOS官方指导文档阅读笔记
FreeRTOS官方指导文档阅读笔记 基于 161204_Mastering_the_FreeRTOS_Real_Time_Kernel-A_Hands-On_Tutorial_Guide.pdf,可 ...
最新文章
- 一步一步学Silverlight 2系列(35):升级Silverlight 2 Beta 1应用程序到Beta 2
- 根据文件属性或权限进行find查找
- Interview:算法岗位面试—2019秋招校园招聘—算法工程师【机器学习、深度学习(偏图像)】秋招感悟:初期阶段的傲娇→中期阶段的紧张→后期阶段的蜕变
- Python 中类的继承:属性初始化、类型判断、多态、多继承和对象信息的获取
- 如何根据jar包的名称找到包含对应源代码的jar包
- 搭建自己的base.js(2)-其他事件方法
- oracle中文转全拼音,Oracle 将汉字转为全拼或返回拼音首字母SQL(二)
- [linux]centos6.3安装flash插件rpm方式
- http客户端-性能比较系列-第二篇-多线程
- qq街景输入 dir-item.js
- Eclipse设置编辑器为绿豆沙颜色
- 超级计算机作文230字,我想养小兔子二年级作文230字
- 红米note3耍android8.0,凡人手机进化论 篇六:软件小白入门,红米note3全网通版刷入魔趣体验安卓9.0的快乐...
- 由Sensor光谱响应曲线联想到的白平衡增益计算
- 计算机图形几何算法详解勘误
- HIDL服务死亡通知实例 hidl_death_recipient
- 【自然语言处理与文本分析】文本特征提取方法总结。关键词提取方法。公认效果较好的IDF,RCF。
- Linux 流量监控软件 NetHogs
- Installing Zune software on Windows Server 2003 SP2 (x86)
- HTML5期末大作业:电影网站设计——电影介绍(11页) 大学生电影网页作品 电影网页设计作业模板 学生网页制作源代码下载