Vue 3.0 新特性学习

119 阅读2分钟

Ref语法

import { ref } from 'vue' 

export default {
  name: 'App',
  setup() {
    const count = ref(0)
    //count与ref进行绑定,变成响应对象
    const double = computed(()=>{
      return count.value * 2
      //ref对象可以直接把value的值展现出来
    })
    const increase = ()=> {
      count.value++
    }
    return {
      count,
      increase
    }
  }
  
};

template

<h1>{{count}}</h1> 
<h1>{{double}}</h1>
<button @click='increase'>+1</button>

Reactives函数

import { ref, computed, reactive, toRefs } from 'vue'
// reactive 是一种object,可以放入一系列响应式数据
// 特别注意模板中是否用了引用类的数据类型,如果是,return的时候要保证它的类型

interface DataProps {
  count: number;
  double: number;
  increase: () => void;
  numbers:number[];
  person:{name?:string}
}
//定义data,确保它return时的数据类型,需要结合toRefs

setup() {
  const data: DataProps  = reactive({
  //DataProps定义了data里面的属性
    count: 0,
    increase: () => { data.count++},
    double: computed(() => data.count * 2)
  })
  data.numbers[0]=5;
  data.person.name='viking';
  //vue2.0通过defineProperty的getter和setter来双向绑定数据,但弊端在于这无法检测到数据的新增和改动
  //vue3.0用Proxy模式,对每一个元素属性都可以检测到
  const refData = toRefs(data)
  //使用 toRefs 保证 reactive 对象属性保持响应性
  return {
    ...refData
  }
}

Vue 3.0 生命周期

setup() {
  onMounted(() => {
    console.log('mounted')
  })
  //一刷新page就会log
  onUpdated(() => {
    console.log('updated')
  })
  //一更新页面数据就会log
  onRenderTriggered((event) => {
    console.log(event)
  })
  //记录了重新rerender的时候哪些值发生了变化
}

侦测变化 -watch

import { ref, computed,reactive, toRefs, watch } from 'vue' 
interface DataProps {
  count:number;
  increase:()=> void;
}
export default {
  name: 'App',
  setup() {
  const data:DataProps = reactive({
    count:0,
    increase:()=>{data.count++}
  })
  const greetings = ref('')
  const updateGreeting = () => {
    greetings.value += 'hello!'
  }
  //监听 watch
  watch([greetings,()=>data.count],(newValue,oldValue) => {
  //用一个函数包裹data.count,防止data.count失去响应式数据的特性
    console.log('old', oldValue)
    //old (2) ["hello!hello!hello!", 0]
    console.log('new', newValue)
    //new (2) ["hello!hello!hello!hello!", 0]
    document.title='updated' + greetings.value
    //这里会update到Bom页面上的标签名噢
  })
  
  const refData = toRefs(data)
    return{
      ...refData,//三个点是es6表达式,表示refData里面的所有内容
      greetings,
      updateGreeting
    }
    //下面千万记得导出来!!!!!愚蠢如我debug了半天
<template>
<div>
  <img alt="Vue logo" src="./assets/logo.png">
  <h1>{{count}}</h1> 
  <h1>{{greetings}}</h1>
  <!-- ref对象可以直接把value的值展现出来 -->
  <button @click='increase'>+1</button>
  <button @click='updateGreeting'>update Title</button>
</div>
</template>

模块化:鼠标追踪器

在hooks文件夹下创建一个useMousePosition.ts
可以reactive也可以ref

import { reactive, onMounted, onUnmounted, toRefs } from 'vue'
//raective一定会用到toRefs
interface positionProps {
    x:number;
    y:number;
}
function useMousePosition(){
    const position:positionProps = reactive({
        x:0,
        y:0
    })//reactive出现的地方
    const updateMouse = (e:MouseEvent) => {
        position.x=e.pageX
        position.y=e.pageY
    }//直接更改position内部的函数

    onMounted(()=>{
        document.addEventListener('click',updateMouse)
    })
    onUnmounted(()=>{
        document.removeEventListener('click',updateMouse)
    })
    
    const refPosition = toRefs(position)
    //toRefs保护position在return时不会丧失响应
    return {
        ...refPosition
    }
}

export default useMousePosition
//记得要导出噢!

在App.vue文件夹中

import useMousePosition from '@/hooks/useMousePosition'
export default {
  name: 'App',
  setup() {  
    const{x , y} = useMousePosition()
  //引用外部composition的时候记得加括号在后面
    return{
      ...refData,
      x,
      y
    }
 },
}

模块化:加载页面缓存

在hooks里面新建一个useURLLoder的功能

import { ref } from 'vue'
import axios from 'axios'

function useURLLoader (url:string) {
    const result = ref(null)
    const loading = ref(true)
    const loaded = ref(false)
    const error = ref(null)

    axios(url).then((rawData)=>{
        loading.value = false
        loaded.value = true
        result.value = rawData.data
    }).catch((e)=>{//如果出错,则loading结束,loaded也保持未完成
        error.value=e
        loading.value = false
    })

    return {
        result,
        loading,
        loaded,
        error
    }
}

export default useURLLoader

在App.vue页面引用

   <h1 v-if='loading'>Loading......</h1>
  <img v-if='loaded' :src="result.message" alt="dog picture">
  <!--下面是script !-->
  const {result, loading ,loaded} = useURLLoader('https://dog.ceo/api/breeds/image/random')

用狗狗网站的API接口可以返回一个{具有属性message:狗狗图片地址}的对象