目录
1. 创建Vue实例
Vue3使用API一律是函数式风格所以和new告别了。
// Vue3.0
import {createApp} from 'vue'
createApp(App).use(router).use(store).mount('#app')
// Vue2.0
import Vue from 'vue'
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
1.1 其他的区别
全局
// vue2
import Vue from 'vue'
Vue.component(...)
// vue3
import {createApp} from 'vue'
let app = createApp(App)
app.component(...)
filter 没有了
全局
Vue.component -> app.component
filter没了 filter -> computed/method
v-model value+input -> value+input || modelValue+update:modelValue
函数h render(h) -> import {h} from ‘vue’
data data: {} || data(){} -> data(){}
异步组件 ()=>import(’…’) -> defineAsyncComponent(()=>import(’…’))
事件 e m i t 、 emit、 emit、on、… -> $emit
其他 …
2. 响应式数据
模板定制
<template>
<div class="hello" style="border:1px solid">
<h1 ref="root">{
{ msg }}</h1>
{
{state.count}} double is {
{double}}
<button @click="add">+</button>
</div>
</template>
2.1 声明响应式数据
// Vue2
export default {
// ....
data() {
return {
state: {
count: 0
}
};
},
}
// Vue3 reactive
export default {
// ....
setup(){
const state = reactive({
count:0
})
return {state}
}
}
2.2 自定义事件
// Vue2
export default {
// ....
methods: {
add() {
this.state.count++;
}
},
}
// Vue3
export default {
// ....
setup(){
const add = () => {
state.count++
}
return {add}
}
}
2.3 计算属性
// Vue2
export default {
// ...
computed: {
double() {
return this.state.count * 2;
}
},
}
// Vue3
export default {
// ...
setup(){
const double = computed (() => state.count * 2 )
return {double}
}
}
2.4 监听器
// Vue2
export default {
// ...
watch: {
count: value => {
console.log("count is changed:", value);
}
}
}
// Vue3
export default {
// ...
setup(){
watch(
() => state.count,
value => {
console.log('state change :',value)
}
)
}
}
2.5 生命周期及其获取Dom元素
// Vue2
<div ref="dom"></div>
export default {
// ...
mounted() {
this.$refs.dom.style.color = "red";
}
}
// Vue3
<h1 ref="myRef">7777777777777777777</h1>
export default {
// ...
setup() {
// ref 创建一个响应式的数据对象
const myRef = ref(null);
onMounted(() => {
console.dir(myRef);
const dom = myRef.value
dom.style.color = 'red'
});
return {
myRef
}
},
}
3. API 列表
const {
createApp,
reactive, // 创建响应式数据对象
ref, // 创建一个响应式的数据对象
toRefs, // 将响应式数据对象转换为单一响应式对象
isRef, // 判断某值是否是引用类型
computed, // 创建计算属性
watch, // 创建watch监听
// 生命周期钩子
onMounted,
onUpdated,
onUnmounted,
} = Vue
3.1 setup使用composition API的入口
setup函数会在 beforeCreate之后 created之前执行
setup(props,context){
console.log('setup....',)
console.log('props',props) // 组件参数
console.log('context',context) // 上下文对象
}
3.2 reactive
reactive() 函数接受一个普通对象 返回一个响应式数据对象
const state = reactive({
count: 0,
plusOne: computed(() => state.count + 1)
})
3.3 ref 与 isRef
ref 将给定的值(确切的说是基本数据类型 ini 或 string)创建一个响应式的数据对象
isRef 其实就是判断一下是不是ref生成的响应式数据对象
// 定义创建响应式数据
const time = ref(new Date())
// 设置定时器为了测试数据响应
setInterval(() => time.value = new Date(), 1000)
// 判断某值是否是响应式类型
console.log('time is ref:', isRef(time))
console.log('time', time)
console.log('time.value', time.value)
// 我们看看模板里面我们这样展示
template: `
<div>
<div>Date is {
{ time }}</div>
</div>
`
3.4 toRefs
toRefs就是ref的批量操作
toRefs 可以将reactive创建出的对象展开为基础类型
// 如果不用toRefs
const state = reactive({
count: 0,
plusOne: computed(() => state.count + 1)
})
return {
state
}
// 模板渲染要这样写
template: `
<div>
<div>count is {
{ state.count }} </div>
<div>plusOne is {
{ state.plusOne }}</div>
</div>
`
// 我们再看看用了toRefs
const state = reactive({
count: 0,
plusOne: computed(() => state.count + 1)
})
return {
...toRefs(state)
}
// 模板渲染要这样写
template: `
<div>
<div>count is {
{ count }} </div>
<div>plusOne is {
{ plusOne }}</div>
</div>
`
3.5 watch 定义监听器
这个其实没有什么新东西,需要手动指定
watch(() => 谁,()=>{})
watch(() =>[a,b....], ()=>{})
watch(() => state.count * 2, val => {
console.log(`count * 2 is ${val}`)
})
3.5.1 watchEffect 自动监听
自动监听,当watchEffect内部使用了某个值会自动监听这个值变化,当这个值变化的时候触发
watchEffect((invalidate) => {
console.log('a变了',a)
})
invalidate: 参数是一个函数,放监听器失效的时候触发。监听器什么时候会失效?stop的时候、或者组件销毁
invalidate(()=>{})
3.5.2 停止监听
let stop = watchEffect((invalidate) => {})
let stop1 = watch(() => 谁,()=>{})
stop()
stop1()
3.6 ffect 副作用函数
响应式对象修改会触发这个函数
// 副作用函数
effect(() => {
console.log('数值被修改了..',state.count)
})
3.7 computed 计算属性
const state = reactive({
count: 0,
plusOne: computed(() => state.count + 1)
})
3.8 provide/inject 依赖注入
// 外部组件
setup(){
provide(名字,值【可以是任何类型】)
}
// 内部
setup(){
const a = inject(名字,可选参:默认值)
toRaw 与 markRaw
toRaw 拿出reactive、ref、readonly这个方法转换前的原始互数据,对原始数据操作不会被监听
markRaw 保持一个数据永远是原始数据不会被监听
unRef 、toRef、customRef
unRef :获取ref对象的原始数据,那为什么不用toRaw
toRaw连着value一起拿,获取出来就是 => {value:xxx}
unRef是ref专用 => xxx
toRef: 也是把一个数据转成ref对象,但是的ref专有一些区别
let json = {a:12}
const b = ref(json.a)
b.value++
console.log(json,b) // {a:12} // {value:13}
const a = toRef(json,'a')
a.value++
console.log(json,a) // {a:13} // {value:13}
ref toRef
相当于把原始数据拷贝,以后操作与原始数据无关 依然存在引用关系
改ref对象后模板会重新渲染 不会触发模板渲染
customRef:自定义ref
function myCustomRef(){
let _val = 12
return customRef((track,trigger)=>{
return {
get(){
track()
return _val
},
set(newVal){
_val = newVal
// 通知vue,请重新渲染
trigger()
}
}
})
}
setup(){
const arr = myAjax('xxxx',[])
return {
arr
}
}
function myAjax(url,initval){
let _data = initval
return customRef((track,trigger)=>{
axios(url).then(res=>{
_data = res._data
trigger()
})
return {
get(){
track()
return _data
},
set(newVal){
_data = newVal
// 通知vue,请重新渲染
trigger()
}
}
})
}
Vue2 | Vue3
--------------------------------------------------
beforeCreate | setup(替代)
created | setup(替代)
beforeMount | onBeforeMount
mounted | onMounted
beforeUpdate | onBeforeUpdate
updated | onUpdated
beforeDestroy | onBeforeUnmount
destroyed | onUnmounted
errorCaptured | onErrorCaptured
4. Teleport 组件
Teleport 提供了一种干净的方法,允许我们控制在 DOM 中哪个父节点下渲染了 HTML
// vue3 新添加了一个默认的组件就叫 Teleport,我们可以拿过来直接使用,它上面有一个 to 的属性,它接受一个css query selector 作为参数,这就是代表要把这个组件渲染到哪个 dom 元素中
<teleport to="#modal">
<div id="center">
<h1>this is a modal</h1>
</div>
</teleport>
4.1 Suspense - 异步组件好帮手
定义一个异步组件,在 setup 返回一个 Promise,AsyncShow.vue
<template>
<h1>{
{result}}</h1>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
setup() {
return new Promise((resolve) => {
setTimeout(() => {
return resolve({
result: 42
})
}, 3000)
})
}
})
</script>
使用 async await 改造一下异步请求, 新建一个 DogShow.vue 组件
<template>
<img :src="result && result.message">
</template>
<script lang="ts">
import axios from 'axios'
import { defineComponent } from 'vue'
export default defineComponent({
async setup() {
const rawData = await axios.get('https://dog.ceo/api/breeds/image')
return {
result: rawData.data
}
}
})
</script>
<Suspense>
<template #default>
<async-show />
<dog-show />
</template>
<template #fallback>
<h1>Loading !...</h1>
</template>
</Suspense>
5. 路由Vue-router
5.1 创建路由
// Vue2
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes: [
// 路由配置不变
]
})
// Vue3
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes: [
// 路由配置不变
]
})
5.2 使用路由
// Vue2
export default {
name: "Home",
methods: {
goHome() {
this.$router.push('Home')
}
}
};
// Vue3
export default {
setup() {
const router = useRouter()
const goHome = () => router.push('Home')
return { goHome};
}
};
6.0 统一状态管理Vuex
6.1 创建Vuex
// Vue2
export default new Vuex.Store({
state: {
count:1
},
mutations: {
inc(state){
state.count ++
}
},
actions: {
},
modules: {
}
})
// Vue3
export default Vuex.createStore({
state: {
count:1
},
mutations: {
add(state){
state.count ++
}
},
actions: {
},
modules: {
}
});
6.2 使用Vuex
// Vue2
export default {
name: "Home",
data() {
return {
state: this.$store.state
};
},
computed: {
double() {
return this.$store.state.count * 2;
},
},
methods: {
add() {
this.$store.commit("add");
}
}
};
// Vue3
import { computed, reactive } from "vue";
import { useStore } from "vuex";
export default {
setup() {
const store = useStore()
const state = store.state
const double = computed(() => store.state.count * 2)
const add = () => {
store.commit("add");
};
return { state, add ,double};
}
};