Vue3+TypeScript
- 环境
- 图形化界面
- 命令行创建
- 启动
- setup()函数和ref()函数
- reactive()函数toRefs()函数
- 生命周期和钩子函数
- onRenderTracked()和 onRenderTriggered()钩子函数的使用
- Watch的使用
- 独立模块使用
- 功能模块
- 主模块
- 模块化深入-axios
- 功能模块
- 主模块
- Teleport瞬间移动函数的使用
- 新建模块
- 注册
- 挂载
- Suspense异步请求组件
- 处理异步请求错误
环境
# 安装命令
npm install -g @vue/cli
# 或者
yarn global add @vue/cli
# 配置环境
npm install -g eslint
npm install -g yarn
图形化界面
- terminal中输入vue ui
命令行创建
- 所在目录下vue create 项目名称
启动
# 命令行中
yarn serve
setup()函数和ref()函数
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<div>
<h2>欢迎光临</h2>
<div>
<button @click="selectDishFunction(index)" v-for="(item,index) in dishes" v-bind:key="index+1">{{
index + 1
}}:{{ item }}
</button>
</div>
<h3>你点了{{selectDish}}</h3>
</div>
</div>
</template>
<!--使用TypeScript需要添加lang="ts"-->
<script lang="ts">
//import中添加ref才能使用ref()
import { defineComponent, ref } from 'vue'
export default defineComponent({
name: 'App',
//使用setup ()
setup () {
//要在template中使用的变量,必须用ref包装一下。
const dishes = ref(['鱼香肉丝', '咖喱牛肉', '糖醋排骨'])
const selectDish = ref('')
//
const selectDishFunction = (index: number) => {
//必须使用.value才能取到值
selectDish.value = dishes.value[index]
}
//模板中使用则需要通过return暴露
return {
dishes,
selectDish,
selectDishFunction
}
}
})
</script>
<!--系统默认-->
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
reactive()函数toRefs()函数
- 模板中直接使用数据,没有使用data.或者.value取值
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<div>
<h2>欢迎光临</h2>
<div>
<button @click="selectDishFunction(index)" v-for="(item,index) in dishes" v-bind:key="index+1">{{
index + 1
}}:{{ item }}
</button>
</div>
<h3>你点了{{selectDish}}</h3>
</div>
</div>
</template>
<script lang="ts">
//引入toRefs
import { reactive, toRefs } from 'vue'
//添加接口,进行类型检查
interface DataProps{
dishes:string[];
selectDish:string;
selectDishFunction:(index: number) => void
}
export default {
name: 'App',
setup () {
//类型检查+reactive()函数中为对象
const data :DataProps = reactive({
dishes: ['鱼香肉丝', '咖喱牛肉', '糖醋排骨'],
selectDish: '',
selectDishFunction: (index: number) => {
data.selectDish = data.dishes[index]
}
})
//使用toRefs()函数包装
const refData = toRefs(data)
return {
...refData
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
生命周期和钩子函数
<script lang='ts'>
import {
reactive,
toRefs,
onMounted,
onBeforeMount,
onBeforeUpdate,
onUpdated
} from 'vue'
interface DataProps{
dishes:string[];
selectDish:string;
selectDishFunction:(index: number) => void
}
export default {
setup () {
console.log('1-开始创建组件-----setup()')
onBeforeMount(() => {
console.log('2-组件挂载到页面之前执行-----onBeforeMount()')
})
onMounted(() => {
console.log('3-组件挂载到页面之后执行-----onMounted()')
})
onBeforeUpdate(() => {
console.log('4-组件更新之前-----onBeforeUpdate()')
})
onUpdated(() => {
console.log('5-组件更新之后-----onUpdated()')
})
}
}
</script>
onRenderTracked()和 onRenderTriggered()钩子函数的使用
- onRenderTracked直译过来就是状态跟踪,它会跟踪页面上所有响应式变量和方法的状态
- onRenderTriggered直译过来是状态触发,它不会跟踪每一个值,而是给你变化值的信息,并且新值和旧值都会给你明确的展示出来。
<script lang='ts'>
import {
onRenderTracked,
onRenderTriggered
} from 'vue'
interface DataProps{
dishes:string[];
selectDish:string;
selectDishFunction:(index: number) => void
}
export default {
name: 'App',
setup () {
const data :DataProps = reactive({
dishes: ['鱼香肉丝', '咖喱牛肉', '糖醋排骨'],
selectDish: '',
selectDishFunction: (index: number) => {
data.selectDish = data.dishes[index]
}
})
onRenderTracked((event) => {
console.log('状态跟踪组件----------->')
console.log(event)
})
onRenderTriggered((event) => {
console.log('状态触发组件--------------->')
console.log(event)
})
const refData = toRefs(data)
return {
...refData
}
}
}
</script>
Watch的使用
- watch可以直接监听ref()函数,不能直接监听reactive()函数
watch([overText, () => data.selectDish], (newValue, oldValue) => {
console.log(newValue)
console.log(oldValue)
document.title = newValue[1]
})
<template>
<div id='app'>
<img alt='Vue logo' src='./assets/logo.png'>
<div>
<h2>欢迎光临</h2>
<div>
<button @click='selectDishFunction(index)' v-for='(item,index) in dishes' v-bind:key='index+1'>{{
index + 1
}}:{{ item }}
</button>
</div>
<h3>你点了{{selectDish}}</h3>
<button v-once @click="overTextFunction" >点餐完毕</button>
<div>{{overText}}</div>
</div>
</div>
</template>
<script lang='ts'>
import {
ref,
reactive,
toRefs, watch
} from 'vue'
interface DataProps{
dishes:string[];
selectDish:string;
selectDishFunction:(index: number) => void
}
export default {
name: 'App',
setup () {
console.log('1-开始创建组件-----setup()')
const data :DataProps = reactive({
dishes: ['鱼香肉丝', '咖喱牛肉', '糖醋排骨'],
selectDish: '',
selectDishFunction: (index: number) => {
data.selectDish = data.dishes[index]
}
})
const refData = toRefs(data)
const overText = ref('开封菜')
const overTextFunction = () => {
overText.value = '' + overText.value
}
//watch可以直接监听ref()函数,不能直接监听reactive()函数
watch([overText, () => data.selectDish], (newValue, oldValue) => {
console.log(newValue)
console.log(oldValue)
document.title = newValue[1]
})
return {
...refData,
overText,
overTextFunction
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
独立模块使用
功能模块
- 单独写入一个ts文件
//引入ref函数
import { ref } from 'vue'
const nowTime = ref('00:00:00')
const getTime = () => {
const now = new Date()
const hour = now.getHours()
const minute = now.getMinutes()
const second = now.getSeconds()
nowTime.value = hour + ':' + minute + ':' + second
setTimeout(getTime, 1000)
}
//暴露出去
export { nowTime, getTime }
主模块
- 引入功能模块
<script lang='ts'>
import {
getTime, nowTime
} from './hooks/getNowTime'
- setup()中的return是用来暴露给模板使用
setup () {
return {
nowTime,
getTime
}
}
<template>
<div id='app'>
<img alt='Vue logo' src='./assets/logo.png'>
<div>{{nowTime}}</div>
<button @click="getTime" >显示时间</button>
</div>
</template>
<script lang='ts'>
import {
getTime, nowTime
} from './hooks/getNowTime'
export default {
name: 'App',
setup () {
return {
nowTime,
getTime
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
模块化深入-axios
功能模块
import { ref } from 'vue'
import axios from 'axios'
function urlAxios(url:string) {
const result = ref(null)
const loading = ref(true)
const loaded = ref(false)
const error = ref(null)
axios.get(url).then((res) => {
loading.value = false
loaded.value = true
result.value = res.data
}).catch(e => {
error.value = e
loading.value = false
})
return {
result,
loaded,
loading,
error,
}
}
export default urlAxios
主模块
<template>
<div id='app'>
<img alt='Vue logo' src='./assets/logo.png'>
<h2>欢迎光临点都德</h2>
<div>请随机点餐</div>
<div v-if="loading">Loading</div>
<img v-if="loaded" :src="result.message"/>
</div>
</template>
<script lang='ts'>
import urlAxios from './hooks/urlAxios'
export default {
name: 'App',
setup () {
const { result, loading, loaded } = urlAxios('https://dog.ceo/api/breeds/image/random')
return {
result,
loaded,
loading
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Teleport瞬间移动函数的使用
新建模块
- /src/components/
<template>
//teleport函数挂载位置
<teleport to="#module">
<div id="center"><h2>点都德</h2></div>
</teleport>
</template>
<script>
export default {
name: 'module'
}
</script>
<style>
#center {
width: 200px;
height: 200px;
border: 2px solid black;
background: white;
position: fixed;
left: 50%;
top: 50%;
margin-left: -100px;
margin-top: -100px;
}
</style>
注册
export default {
//注册
components: { module },
name: 'App',
setup () {
const { result, loading, loaded } = urlAxios('https://dog.ceo/api/breeds/image/random')
return {
result,
loaded,
loading
}
}
}
挂载
- /public/index.html下
<div id="app"></div>
<div id="module"></div>
Suspense异步请求组件
- 异步请求模块
<template>
<img :src="result && result.imgUrl" />
</template>
<script lang="ts">
import axios from 'axios'
import { defineComponent } from 'vue'
export default defineComponent({
async setup () {
// promise 语法糖 返回之后也是promise对象
const rawData = await axios.get('https://apiblog.jspang.com/default/getGirl')
return { result: rawData.data }
}
})
</script>
- 模板引入
<template>
<div>
<Suspense>
<template #default>
<GirlShow />
</template>
<template #fallback>
<h1>holding</h1>
</template>
</Suspense>
</div>
</template>
<script lang='ts'>
import { onErrorCaptured } from 'vue'
import GirlShow from './components/GirlShow.vue'
export default {
components: { GirlShow },
name: 'App',
setup () {
onErrorCaptured((error) => {
console.log(error)
})
return { GirlShow }
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
处理异步请求错误
import { onErrorCaptured } from 'vue'
export default {
components: { GirlShow },
name: 'App',
setup () {
onErrorCaptured((error) => {
console.log(error)
})
return { GirlShow }
}
}