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 }
  }
}