01-gitting-started
vue3基础
<template> <div> {{ count }} <button @click="handelClick">add</button> </div> </template> <script setup> import { ref } from 'vue'; const count = ref(0) const handelClick = () => { count.value ++ } </script> <style lang="css"> </style>
02-template-syntax
模版语法
<template> <div> {{ rawHtml }} </div> <div v-html="rawHtml"></div> <div v-bind="obj">obj</div> <button @click="handelClick">反转切换</button> <div v-if="toggle">是</div> <div v-else>否</div> <div v-bind:title="title">我有标题</div> <div> {{ title2.split('').reverse().join('') }} </div> <div> <p>{{ inputVal }}</p> <!-- <input type="text" v-on:keyup.enter="hanedlKeyup" /> --> <input type="text" v-on:keyup="hanedlKeyup" /> </div> </template> <script setup> import { ref } from 'vue'; const rawHtml = ref('<p>2022</p>') const title = '我是标题' const title2 = 'hello vue3' const obj = ref({ id: '01', class: 'box' }) const toggle = ref(true) const handelClick = () => { toggle.value = !toggle.value } const inputVal = ref('') const hanedlKeyup = (e)=>{ console.log(e.target.value) inputVal.value = e.target.value } </script> <style lang="css"> </style>
03-reactivity-fundament
响应式基础
<template> <div> <button @click="handelClickRef">ref add {{count}}</button> <button @click="handelClickRec">reactive add {{state.count}}</button> </div> </template> <script setup> import { ref, reactive } from 'vue'; const count = ref(0) const state = reactive({ count: 0 }) const handelClickRef = ()=>{ count.value++ } const handelClickRec = ()=>{ state.count++ } </script> <style lang="css"> </style>
04-computed-properties
<template> <div> <p>{{count}}</p> {{doubleCount}} <!-- {{doubleCount()}} --> </div> <div> <button @click="handelClick">add</button> </div> </template> <script setup> import { ref, computed } from 'vue' const count = ref(1) const handelClick = ()=>{ count.value++ } const doubleCount = computed(()=>{ return count.value *2 }) // const doubleCount = ()=>{ // return count.value *2 // } </script> <style lang="css"> </style>
05-class-style
动态样式
<template> <div :class="[italic,{a:isA,b:isB}]" class="c d"> <p>hello vue3</p> </div> <div> <button @click="handelClick">change</button> </div> <div><example></example></div> </template> <script setup> import { ref } from 'vue'; import example from './Example.vue' const italic = ref('italic') const isA = ref(true) const isB = ref(true) const handelClick = () => { isA.value = !isA.value } </script> <style lang="css"> .a{ color: red; } .b{ font-size: 50px; } .c{ font-weight: 900; } .d{ text-decoration: underline; } .italic{ font-style: italic; } </style>
<template> <ul class="box"> <li v-for="item, index in list" :class="{active:index === crunteIndex}" @click="handelClick(index)" > {{item}} </li> </ul> </template> <script setup> import { ref } from 'vue'; const list = ref(['line 1', 'line 2', 'line 3']) const crunteIndex =ref(0) const handelClick = (index) => { crunteIndex.value = index } </script> <style lang="css"> .box{ border: 1px solid #999; padding: 20px; } .box li{ cursor: pointer; } .active{ color: red; font-size: 30px; } </style>
06-condition-rendering
条件渲染
<template> <div v-if="isShow >= 75">{{isShow}}</div> <div> {{ count }} <button @click="handelClick">tagger</button> </div> </template> <script setup> import { ref } from 'vue'; const isShow = ref(65) const handelClick = () => { isShow.value = 85 } </script> <style lang="css"> </style>
07-list-rendering
遍历渲染
<template> <div> <ul> <template v-for="item,index in bookList"> <li v-if="item.type !== '历史'">{{index+1}}: {{item.name}} --- {{item.user}}</li> </template> </ul> </div> <div> <ul> <li v-for="n,u,i in course">{{i}} - {{u}}: {{n}}</li> </ul> </div> </template> <script setup> import { ref, reactive } from 'vue'; const course = reactive({ name: '轮语', user: '孔子', time: '春秋战国' }) const bookList = ref([ { id:'01', name:'红楼梦', user:'罗惯中', type: '四大名著' }, { id:'02', name:'西游记', user:'吴承恩', type: '四大名著' }, { id:'03', name:'三国演义', user:'罗惯中', type: '四大名著' }, { id:'04', name:'水浒传', user:'罗惯中', type: '四大名著' }, { id:'03', name:'史记', user:'司马迁', type: '历史' } ]) </script> <style lang="css"> </style>
08-event
事件处理
<template> <div> <p>{{ count }}</p> <p>{{numb}}</p> <p>{{ text }}</p> <button @click="handel1(), handel2()">add</button> <input type="text" @input="handelInput(100, $event)" /> </div> </template> <script setup> import { ref } from 'vue'; const count = ref('事件处理') const numb = ref(0) const text =ref('') const handelInput = (num, e) => { numb.value += num text.value = e.target.value } //一个动作触发2个事件,vue3特有新属性 const handel1 = ()=>{ console.log('事件1') } const handel2 = ()=>{ console.log('事件2') } </script> <style lang="css"> </style>
09-form
表单
<template> <div> {{name}} <input type="text" v-model="name" /> </div> <div> <textarea v-model="about"></textarea> </div> <div> 隐藏:<input type="checkbox" v-model="isShow" />{{isShow ? '是' : '否'}} </div> <div> {{sex}} <input type="radio" value="男" v-model="sex" />男 <input type="radio" value="女" v-model="sex" />女 <input type="radio" value="保密" v-model="sex" />保密 </div> <div> {{interest}} <input type="checkbox" value="教育" v-model="interest" />教育 <input type="checkbox" value="动漫" v-model="interest" />动漫 <input type="checkbox" value="新闻" v-model="interest" />新闻 </div> <div> {{city}} <select v-model="city"> <option>北京</option> <option>上海</option> <option>广州</option> </select> </div> <div> {{time}} <select v-model="time" @click="handelClick" multiple> <option>06:00</option> <option>08:00</option> <option>10:00</option> <option>12:00</option> <option>14:00</option> </select> </div> </template> <script setup> import { ref } from 'vue'; const name = ref('') const about =ref('') const isShow = ref(true) const sex = ref('') const interest = ref([]) const city = ref('广州') const time = ref([]) const handelClick =(e)=>{ console.log(e.target.value) } </script> <style lang="css"> div{ margin-bottom: 10px; } </style>
10-life-cycle
生命周期
<template> <div> <p id="box">{{ count }}</p> </div> </template> <script setup> //生命周期 import { ref, onMounted, onBeforeMount, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'; const count = ref(0) let t = null onMounted(()=>{ //加载后 console.log('加载后----->',document.getElementById('box').innerHTML) t = setTimeout(()=>{ count.value = 1000 },1000) }) onBeforeMount(()=>{ //加载前 // console.log('加载前----->',document.getElementById('box').innerHTML) count.value = 100 }) onBeforeUpdate(()=>{ //数据更新前,DOM不变 console.log('更新前DOM----->',document.getElementById('box').innerHTML) console.log('更新前value----->',count.value) }) onUpdated(()=>{ //更新后 console.log('更新后----->',document.getElementById('box').innerHTML) }) onBeforeUnmount(()=>{ //销毁前 // console.log('销毁前----->',document.getElementById('box').innerHTML) }) onUnmounted(()=>{ //销毁后 // console.log('销毁后----->',document.getElementById('box').innerHTML) clearTimeout(t) }) </script> <style lang="css"> </style>
11-watcher
侦听器
<template> <div> {{ count }} <p>{{doubleCount}}</p> <p>{{text}}</p> <button @click="handelClick">add</button> </div> </template> <script setup> //侦听器 import { computed } from '@vue/reactivity'; import { ref, watchEffect, watch } from 'vue'; const count = ref(1) const doubleCount = computed(()=>count.value*2) const text = ref('hello') const handelClick = () => { count.value ++ } watchEffect(()=>{ //侦听所有条件的变化,页面加载时会执行一次 console.log('count变化为:'+count.value) }) watch( //精确侦听具体某一条件的变化,页面加载时不触发 // count, // ()=>{ // console.log('----') // } ()=>{ text.value = 'vue3' //可在条件发生变化前执行某些逻辑 return count.value//侦听的条件 }, ()=>{ console.log('count发生变化了') //侦听到变化后执行逻辑 } ) </script> <style lang="css"> </style>
12-components
全局组件与局部组件
import { createApp } from 'vue' import App from './App.vue' import GlobalComponents from './views/12-components/GlobalComponents.vue' const app = createApp(App) app.component('GC',GlobalComponents) app.mount('#app')
<template> <div> <GC></GC> </div> <div> <Child></Child> </div> </template> <script setup> //注册组件 import Child from './Child.vue' </script> <style lang="css"> </style>
<template> <div> Child </div> </template> <script setup> //局部注册组件 </script> <style lang="css"> </style>
<template> <div> Global </div> </template> <script setup> //全局注册组件 </script> <style lang="css"> </style>
13-props
父子传参事件(父传子)
<template> <div> <Child2 :count="count" @my-event2="handelEvent"></Child2> </div> <div> <Child1 :count="count" @my-event1="handelClick"></Child1> </div> <div> {{title}} </div> </template> <script setup> //注册组件 import {ref} from 'vue' import Child1 from './Child1.vue' import Child2 from './Child2.vue' const title = ref('') const count = ref(100) const handelClick =(e)=>{ console.log('来自child1-->', e.value) title.value += e.value } const handelEvent=(e)=>{ console.log('来自child2-->', e.value) title.value += e.value } </script> <style lang="css"> </style>
<template> <div> Child1 <p>{{count}}</p> </div> </template> <script setup> //局部注册组件 import {ref, onMounted} from 'vue' const props = defineProps(['count']) const title = ref('hello') const emit = defineEmits(['my-event1']) console.log('child1--->', props.count) onMounted(()=>{ emit('my-event1', title) }) </script> <style lang="css"> </style>
<template> <div> Child2 </div> </template> <script setup> //局部注册组件 import {ref, onMounted} from 'vue' const title = ref ('vue3') const emit = defineEmits(['my-event2']) onMounted(()=>{ emit('my-event2', title) }) </script> <style lang="css"> </style>
14-components-event
父子传参事件(子传父)
<template> <div> {{title}} <Child v-model:titleEvent="title"></Child> </div> </template> <script setup> //注册组件 import {ref} from 'vue' import Child from './Child.vue' const title = ref('hello') </script> <style lang="css"> </style>
<template> <div> Child </div> </template> <script setup> //局部注册组件 import {ref, onMounted} from 'vue' const props = defineProps(['titleEvent']) const emit =defineEmits(['update:titleEvent']) const title = ref('World') onMounted(()=>{ console.log('props--->', props.titleEvent) let obj = props.titleEvent emit('update:titleEvent', obj += title.value) }) </script> <style lang="css"> </style>
15-fallthrough-attrs
组件透传
<template> <div> <Child title="hello" class="world"></Child> </div> </template> <script setup> import { ref } from 'vue'; import Child from './Child.vue' </script> <style lang="css"> </style>
<template> <div id="child"> Child </div> </template> <script> export default { inheritAttrs: false //阻止组件之间的透传 } </script> <script setup> //局部注册组件 import {ref, useAttrs} from 'vue' const attrs = useAttrs() console.log('class-->', attrs) //通过useAttrs透传可以直接获取父组件继承过来的所有属性 </script> <style lang="css"> .world{ font-size: 50px; color: red; } </style>
16-slots
插槽
<template> <div> <Child> <!-- <template #default="data"> --> <template v-slot:default="data"> <div>{{str}} {{data.mark2}} world {{data.mark}}</div> </template> <template v-slot:line2> <div>{{str}} slot</div> </template> </Child> </div> </template> <script setup> import { ref } from 'vue'; import Child from './Child.vue' const str = ref('hello') </script> <style lang="css"> </style>
<template> <div> <slot :mark="mark" mark2="--->"></slot> <slot name="line2"></slot> </div> </template> <script setup> //局部注册组件 import {ref} from 'vue' const mark = ref('!!!') </script> <style lang="css"> </style>
17-inject-provide
依赖注入
<template> <div> <Child1></Child1> <Child2></Child2> </div> </template> <script setup> import { ref, provide, onMounted } from 'vue'; import Child1 from './Child1.vue' import Child2 from './Child2.vue'; const title = ref('happy') provide('title', title) onMounted(()=>{ setTimeout(()=>{ title.value = 'hello' },2000) }) </script> <style lang="css"> </style>
<template> <div> {{title}} Child1 </div> </template> <script setup> //局部注册组件 import { ref, inject } from 'vue'; const title = inject('title') </script> <style lang="css"> </style>
<template> <div> {{title}} Child2 <Grandson></Grandson> </div> </template> <script setup> //局部注册组件 import { ref, inject } from 'vue'; import Grandson from './Grandson.vue'; const title = inject('title') </script> <style lang="css"> </style>
<template> <div> {{title}} Grandson </div> </template> <script setup> //局部注册组件 import { ref, inject } from 'vue'; const title = inject('title') </script> <style lang="css"> </style>
18-composition-functions
组合式函数
<template> <div> {{ count }} <button @click="handelClick">add</button> </div> </template> <script setup> import userCount from './userCount' import userTitle from './userTitel' const {count, handelClick} = userCount() userTitle(count) </script> <style lang="css"> </style>
import {ref} from 'vue' const userCount = ()=>{ const count = ref(0) const handelClick = () => { count.value ++ } return { count, handelClick } } export default userCount
import { ref, onMounted, onUpdated } from 'vue'; const userTitle =(count)=>{ onMounted(()=>{ document.title = count.value }) onUpdated(()=>{ document.title = count.value }) } export default userTitle
19-directive-plugin
自定义指令和插件
20-router
路由
21-pinia
状态管理pinia
<template> <div> <!-- {{counterStore.count}} <p><button @click="counterStore.add()">add</button></p> --> {{count}} <p>{{title}}</p> <p><button @click="counterStore.add()">add</button></p> <Child></Child> </div> </template> <script setup> import {storeToRefs} from 'pinia' //storeToRefs将失去响应性的数据恢复响应性 import useCounterStore from '../../store/counterState' import Child from './Child.vue' const counterStore = useCounterStore() const {count, title} = storeToRefs(counterStore) </script> <style lang="scss"> </style>
<template> <div> Child <p> {{title}} --- {{count}} </p> </div> </template> <script setup> //局部注册组件 import useCounterStore from '@/store/counterState'; import { storeToRefs } from 'pinia'; //storeToRefs将失去响应性的数据恢复响应性 const countStore = useCounterStore() const {count, title} = storeToRefs(countStore) </script> <style lang="css"> </style>
import {defineStore} from 'pinia' const useCounterStore = defineStore('counterStore',{ state(){ return { count: 0, title: 'hello world' } }, actions: { add(){ this.count ++ } } }) export default useCounterStore