vue3学习
安装
npm install -g @vue/cli@next
子传父
父
<One :titles="msg1" @oneTwo="clickMethod"/>
子
export default {
name: "One",
emits: ['oneTwo'],
methods: {
updatedOne() {
this.$emit('oneTwo', 12)
}
}
}
update方面的修改
父 <One v-model="msg1" ></One>
子
updatedOne() {
// 内部把v-model 封装到 modelValue
this.$emit('update:modelValue',10)
}
动态组件
<component :is="currentTabComponent"></component>
<component :is="condition ? 'FooComponent' : 'BarComponent'"></component>
watch
obj: {
name: 12
}
watch:{
// 正常的基本类型的监听
nums(val) {
console.log(val);
},
obj:{
handler(newName, oldName) {
console.log(newName, oldName);
},
immediate: true,//立即执行触发回调
deep: true // 深度监听
}
},
可以改成字符串的形式,可以理解为铺平
obj: {
name: 12
}
'obj.name': {
handler(newName, oldName) {
console.log(newName, oldName);
},
}
我们知道deep:true
很消耗性能
created() {
this.fn = this.$watch('obj', (newVal) => {
console.log(newVal);
}, {immediate: true, deep: true})
},
unmounted() {
this.fn();
}
vue3.0
// 监听title发生改变
watch(
() => props.title,
(newTitle, oldTitle) => {
console.log('newTitle, oldTitle :>> ', newTitle, oldTitle);
context.emit('change-title', title);
}
);
监听多个值得变化
const r = ref(1)
const s = ref(1)
const t = ref(1)
watch([r, s, t], val => {
console.log('watch', val)
})
$forceUpdate
强制刷新,只会影响实例本身和插入了插槽内容的子组件
@
@click.stop
等修饰符
.stop
阻止事件冒泡event.stopPropagation()
.prevent
阻止事件的默认行为``event.preventDefault()`
.self
自身元素触发
Keep-alive
缓存组件
include
-string | RegExp | Array
。仅具有匹配名称的组件将被缓存。exclude
-string | RegExp | Array
。名称匹配的任何组件都不会被缓存。max
-number | string
。要缓存的组件实例的最大数量。
<transition>
<keep-alive>
<component :is="view"></component>
</keep-alive>
</transition>
<keep-alive>
<comp-a v-if="a > 1"></comp-a>
<comp-b v-else></comp-b>
</keep-alive>
条件匹配
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
最大缓存组件
<keep-alive :max="10">
<component :is="view"></component>
</keep-alive>
setup
- 参数,
props
,context
setup(props, context) {
// Attributes (Non-reactive object)
console.log(context.attrs)
// Slots (Non-reactive object)
console.log(context.slots)
// Emit Events (Method)
console.log(context.emit)
}
setup(props, { attrs, slots, emit }) {
...
}
ref
ref
的本质是拷贝,与原始数据没有引用关系
reactive
复杂类型的响应
toRef
toRef
将单个reactive
对象属性转换为保持与父对象的连接的ref:
const state = reactive({
foo: 1,
bar: 2
})
const fooRef = toRef(state, 'foo')
// 这样进行修改值,因为转化为ref类型啦
foos.value=100
toRefs
toRefs
将所有属性转换为具有refs属性的普通对象:
<h1>{{foo}}</h1>
setup() {
const state = reactive({
foo: 1,
bar: 2
})
const clickMethod = () => {
state.foo=100
}
return {
clickMethod,
...toRefs(state)
}
},
computed
const twiceTheCounter = computed(() => counter.value * 2)
get/set
const count = ref(1)
const plusOne = computed({
get: () => count.value + 1,
set: val => {
count.value = val - 1
}
})
plusOne.value = 1
console.log(count.value) // 0
slot
命名插槽
父
<One>
<h1>223223</h1>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
</One>
子
// 默认插槽
<slot></slot>
// 命名插槽
<slot name="header"></slot>
生命周期
选件API | 钩在里面 setup |
---|---|
beforeCreate |
不需要* |
created |
不需要* |
beforeMount |
onBeforeMount |
mounted |
onMounted |
beforeUpdate |
onBeforeUpdate |
updated |
onUpdated |
beforeUnmount |
onBeforeUnmount |
unmounted |
onUnmounted |
errorCaptured |
onErrorCaptured |
renderTracked |
onRenderTracked |
renderTriggered |
onRenderTriggered |
activated |
onActivated |
deactivated |
onDeactivated |
提供/注入
父
provide: {
location: 'North Pole',
geolocation: {
longitude: 90,
latitude: 135
}
}
子
inject: ['location', 'geolocation']
vue3.0
父
setup() {
provide('location', 'North Pole')
provide('geolocation', {
longitude: 90,
latitude: 135
})
}
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
const updateLocation = () => {
location.value = 'South Pole'
}
provide('location', location)
provide('geolocation', geolocation)
provide('updateLocation', updateLocation)
}
子/孙
setup() {
const userLocation = inject('location', 'The Universe')
const userGeolocation = inject('geolocation')
return {
userLocation,
userGeolocation
}
}
dom查找
<div ref="root">This is a root element</div>
setup() {
const root = ref(null)
onMounted(() => {
console.log(root.value) // <div>This is a root element</div>
})
return {
root
}
}
toRaw
拿到原始的值, 类似于表单表单的提交给后面的值
const foo = {name:'xx'}
const reactiveFoo = reactive(foo)
console.log(toRaw(reactiveFoo) === foo) // true
watchEffect
- 没有过多的参数 只有一个回调函数
- 立即执行,没有惰性,页面的首次加载就会执行。
- 自动检测内部代码,代码中有依赖 便会执行
watchEffect
当我想观察多个反应特性而我不在乎旧值时
watchEffect能够监视在回调函数中引用的任何反应变量。
watchEffect(() => {
console.log(root.value);
})
setTimeout(() => {
root.value = 10
},1000)
// 1 默认执行一次
// 10
watch
当单个电抗值更改时,如果您想触发副作用,请使用此命令。
watch(user, () => doSomething({ user: user.value, profile: profile.value }))
使用watchEffect
时,你需要看多个反应值,并引发副作用,只要任何人被更新。
watchEffect(() => doSomething({ user: user.value, profile: profile.value }))
清除监听
我们知道监听会有副作用, 我们可以发现这个跟react的useEffect
很像
const stop = watchEffect(() => {
/* ... */
})
// 离开后,我们可以执行清除监听
stop()
更新策略
flush: 'post'
设置后是DOM更新后运行效果
<div ref="root">This is a root element</div>
setup() {
const root = ref(null)
watchEffect(() => {
console.log(root.value) // => <div></div>
},
{
flush: 'post'
})
return {
root
}
}
teleport
<teleport>
并告诉Vue将这个HTML传送到body
标签
<teleport to="body">
<div v-if="modalOpen" class="modal">
xxxxxxx
</div>
</teleport>
我们可以把两个组件添加到同一个目标
<teleport to="#modals">
<div>A</div>
</teleport>
<teleport to="#modals">
<div>B</div>
</teleport>
<div id="modals">
<div>A</div>
<div>B</div>
</div>
render
resolveComponent
用于全局注册的组件。
const { h, resolveComponent } = Vue
// ...
render() {
const ButtonCounter = resolveComponent('ButtonCounter')
return h(ButtonCounter)
}
ts 的写法
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
// type inference enabled
})
</script>
全局刷新
const {ctx: _this}: any = getCurrentInstance()
_this.$forceUpdate();
防抖节流
全局添加
Vue.createApp({
methods: {
// Debouncing with Lodash
click: _.debounce(function() {
// ... respond to click ...
}, 500)
}
}).mount('#app')
另一种形式
生命周期挂钩中添加去抖动功能
app.component('save-button', {
created() {
// Debouncing with Lodash
this.debouncedClick = _.debounce(this.click, 500)
},
unmounted() {
// Cancel the timer when the component is removed
this.debouncedClick.cancel()
},
methods: {
click() {
// ... respond to click ...
}
},
template: `
<button @click="debouncedClick">
Save
</button>
`
})
这种方式才是computed的精华所在
const vm = Vue.createApp({
data() {
return {
firstName: 'Foo',
lastName: 'Bar'
}
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName
}
}
}).mount('#demo')
vue3
https://cli.vuejs.org/core-plugins/typescript.html#injected-commands
vue add typescript
别用vue-component-class 感觉不是很成熟
reactive
const book = reactive({ title: 'Vue 3 Guide' })
book.title 使用就可以啦, 不能用 .value
最后上一个,刚开始学习的小案例
import {ref, watch, onMounted, computed,toRefs} from 'vue'
export default {
name: "One",
props:['sex'],
setup(props) {
let {sex} = toRefs(props);
console.log(sex.value);
let sex1=toRefs(props,'sex')
console.log(sex1.sex.value);
let a = ref(0)
// 监听
watch(a, (newVal, val) => {
console.log(newVal, val);
}, {deep: true})
//如果还需要监控一个就继续写一个
watch(b, (newValue, oldValue) => {
console.log(newValue, oldValue);
})
const add = () => {
// 类似请求修改值
a.value = [1, 2, 3, 4]
};
// 计算属性
const b = computed(() => a.value[0] + 100)
// 生命周期
onMounted(add)
return {a, b}
}
}
html
<input type="text" v-model="a[0]">
{{ a }} <br>
{{ b }}
{{sex}}
决定自己的高度的是你的态度,而不是你的才能
记得我们是终身初学者和学习者
总有一天我也能成为大佬