vue3.0体验卡

前言

vue3.0 Rc(候选发布版本)已经于7月18上线,离正式版本发布已经不远了,鉴于此,本人就通过@vue/composition-api 这个 Vue Composition API 来事先体验下3.0的新特性,为以后能快速上手新版本做准备。

准备工作

下载与引入

  • 下载体验版api
 npm i @vue/composition-api
  • 引入与使用
 1. 在main.js中要引入全部的api
 
 import VueCompositionApi from '@vue/composition-api'

 Vue.use(VueCompositionApi)
 
 2. 在页面中按需引入api
 
 import { 需要使用的api } from '@vue/composition-api'

tips: main.js和局部页面都需要引入,不能只在页面中引入。

开发与使用

reactive和toRefs

reactive创建响应式数据,toRefs把普通数据转换成响应式数据

<template>
  <div class="home">
    <span>{{name}}</span>
    <span>{{num}}</span>
    <button @click="btn">按钮</button>
    <button @click="btn2">按钮2</button>
  </div>
</template>
<script>
// reactive 创建响应式数据对象 --类似data
import { reactive, toRefs } from '@vue/composition-api'
export default {
  name: 'Home',
  setup () {
    // state对象
    const state = reactive({
      name: 'hello world'
    })
    // modelData 
    const modelData = reactive({
      num: 1
    })
    const btn = () => modelData.num++
    const btn2 = () => {
      state.name = '我是不双向绑定的数据,没有toRefs转换不可更改'
      return state
    }
    return {
      ...state,
      ...toRefs(modelData), //把数据转换为响应式
      btn, // 事件
      btn2
    }
  }
}
</script>

tips:

  1. setup中是没有this
  2. 数据、方法都写在setup里面。
  3. 方法里改变值需return这个值
  4. 用了...运算符后使用reactive创建出来的数据都不是响应式数据了,需要使用toRefs转换为ref()类型的响应式数据

ref(推荐)

  • reactive一样创建响应式数据,但更推荐使用。
<template>
 <div class="RefCom">
   <span>{{refCount}}</span>
   <button @click="refCount+=1">+1</button>
 </div>
</template>
<script>

import { ref, reactive } from '@vue/composition-api'
export default {
 name: 'RefCom',
 setup (props, { root }) {
   const refCount = ref(0) //创建响应式数据
   console.log(refCount.value)
   const data = reactive({
     refCount
   })
   console.log(data.refCount)
   data.refCount++
   console.log(data.refCount)
   return {
     ...data,
     refCount
   }
 }
}
</script>
  • 模板上的ref–获取dom
//父组件
<template>
  <div class="Father">
    <h1 ref="h1Ref">父组件</h1>
    <som ref="somRef"></som>
  </div>
</template>
<script>

import som from './Som'
import { ref, onMounted } from '@vue/composition-api'
export default {
  name: 'Father',
  components: {
    som
  },
  setup (props, { root }) {
    const h1Ref = ref(null) //赋值null
    const somRef = ref(null)
    onMounted(() => {
      console.log(h1Ref.value, 'h1的dom')
      console.log(somRef.value, 'som的dom')
    })
    return {
      h1Ref,  //要和模板上ref值相同
      somRef
    }
  }
}
</script>

 //子组件
 <template>
  <div class="Som">
    <h3>子组件</h3>
  </div>
</template>

<script>
export default {
  name: 'som',
  setup (props, { root }) {}
}
</script>

tips:

  1. ref括号里的值就是refCount的值,括号里的值可以是各种类型的值。
  2. setup要通过xxx.value获取ref转换的值。
  3. 模板中无需通过xxx.value展示数据,直接{{xxx}}即可,在return时已经进行了转换了。
  4. ref包裹创建出来的值是个对象,里面就一个属性value
  5. reactive包裹ref创建的值不需要通过XXX.value访问
  6. 新的ref会覆盖旧的ref的值
  7. 通过isRef可以判断是否是ref创建出来的。

computed

计算属性:可创建可读可写的计算属性。

<template>
  <div class="RefCom">
    <span>原值:{{refCount}}</span> |
    <span>
      计算属性值:{{ onlyReadComputed
      }}
    </span> |
    <button @click="refCount+=1">+1</button>
  </div>
</template>
<script>

import { ref, computed } from '@vue/composition-api'
export default {
  name: 'RefCom',
  setup (props, { root }) {
    const refCount = ref(0)
    // 只读的计算属性
    const onlyReadComputed = computed(() => refCount.value + 1)
    // 可读可写的计算属性
    const rwComputed = computed({
      get: () => refCount.value + 1,
      set: value => {
        refCount.value = value - 1
      }
    })
    console.log(onlyReadComputed, '只读计算属性的值')
    rwComputed.value = 11
    console.log(rwComputed, '可读可写计算属性的值')
    return {
      refCount,
      rwComputed,
      onlyReadComputed
    }
  }
}
</script>

watch

监听数据的变化

<template>
 <div class="RefCom">
   <span>{{refCount}}</span>
   <span>{{name}}</span>
   <button @click="stopWatch">停止watch</button>
   <input v-model="inputValue" />
 </div>
</template>
<script>
import { ref, reactive, watch, toRefs } from '@vue/composition-api'
export default {
 name: 'watch',
 setup (props, { root }) {
   const refCount = ref(0)
   const inputValue = ref('')
   const state = reactive({
     name: '张总'
   })
   /* ---监听单个--- */

   // ref
   const stop = watch(
     refCount,
     (newValue, oldValue) => {
       console.log(refCount.value)
       console.log('新值:' + newValue, '旧的值:' + oldValue)
     }
   )

   const stopWatch = () => {
     stop()
   }

   // reactive
   watch(
     () => state.name,
     (newValue, oldValue) => {
       // console.log(refCount.value)
       console.log('新值:' + newValue, '旧的值:' + oldValue)
     }
   )

   /* ---监听多个--- */
   watch(
     [() => refCount, () => state.name],
     ([newRefCount, newName], [oldRefCount, oldName]) => {
       console.log('newRefCount:' + newRefCount.value, 'newName:' + newName)
       console.log('oldRefCount:' + oldRefCount.value, 'oldName:' + oldName)
     }
   )

   setTimeout(() => {
     refCount.value++
   }, 1000)

   setTimeout(() => {
     state.name = '李总'
   }, 3000)

   // 异步打印
   const asyncPrint = (val) => {
     return setTimeout(() => {
       console.log(val)
     }, 1000)
   }

   // ref
   watch(
     inputValue,
     (newValue, oldValue, clean) => {
       const timeId = asyncPrint(newValue)
       // 每当数据变化的时候清除定时器
       clean(() => clearTimeout(timeId))
     }
   )

   return {
     ...toRefs(state),
     refCount,
     stopWatch,
     inputValue
   }
 }
}
</script>

tips:

  1. refreactive的值的监听方法不同,reactive需用方法返回值,() => xxx,ref可直接使用。
  2. 当监听多个时,不管是ref还是reactive创建的值,都需要用方法返回
  3. 在监听多个值时,用数组来解构新旧值时,新值和旧值分别在不同的数组里,和vue2.x不一样。
  4. watch监听返回新值、旧值时还返回了个函数,当前函数在watch被重复执行stop操作时发生,可做些清除操作。常见应用场景有防抖。
  5. 防抖:就是对于频繁触发的事件添加一个延时同时设定一个最小触发间隔,如果触发间隔小于设定的间隔,则清除原来的定时,重新设定新的定时;如果触发间隔大于设定间隔,则保留原来的定时,并设置新的定时;防抖的结果就是频繁的触发转变为触发一次

生命周期

  • beforeCreate -> setup()
  • created -> setup
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

<template>
  <div class="Father">
 
  </div>
</template>
<script>


import { onMounted, onUpdated, onBeforeUnmount } from '@vue/composition-api'
export default {
  name: 'Father',

  setup (props, { root }) {

    onMounted(() => {
      console.log('onMounted')
    })

    onUpdated(() => {
      console.log('onUpdated')
    })

    onBeforeUnmount(() => {
      console.log('onBeforeUnmount')
    })

  }
}
</script>

tips:

  1. 去除了beforeCreatecreated生命周期,直接就在setup中,setup执行顺序 是beforeCreate后,created
  2. 其他生命周期就在原本前加上on,功能没有什么变化,且定义在setup函数中
  3. 推荐请求都放在onMounted

依赖注入

  • provide
//父组件
<template>
  <div class="Father">
    <h1>父组件</h1>
    <button @click="color='red'">红色</button>
    <button @click="color='blue'">蓝色</button>
    <button @click="color='yellow'">黄色</button>
    <som></som>
  </div>
</template>
<script>

import som from './Som'
import { provide, ref } from '@vue/composition-api'
export default {
  name: 'Father',
  components: {
    som
  },
  setup (props, { root }) {
    const color = ref('red') //响应式的值,父组件修改可影响子孙后代
    //注入值
    provide('color', color)
    return {
      color
    }
  }
}
</script>
 //子组件
 <template>
  <div class="Som">
    <h3>子组件</h3>
    <Grandson />
  </div>
</template>

<script>
import Grandson from './Grandson'
export default {
  name: 'som',
  components: {
    Grandson
  },
  setup (props, { root }) { }
}
</script>
  • inject
//孙子组件
<template>
  <div class="Grandson">
    <h5 :style="{color:color}">孙子组件</h5>
  </div>
</template>

<script>
import { inject } from '@vue/composition-api'
export default {
  name: 'Grandson',
  setup (props, { root }) {
  //接收值
    const color = inject('color') 
    return {
      color
    }
  }
}
</script>

路由跳转

<template>
  <div class="home">
    <button @click="jump">跳转</button>
  </div>
</template>
<script>
export default {
  name: 'Home',
  setup (props, { root }) {
   const jump = () => root.$router.push('/about')
    return {
      jump
    }
  }
}
</script>

tips: root指代的就是vue对象,即this,且名字是不可更改的。

props


//父
<template>
  <div class="about">
    <h1>This is an about page</h1>
    <div>{{num}}</div>
    <button @click="btn">增加</button>
    <HelloWorld msg="我是props传进去的值" />
  </div>
</template>


//子
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup (props) {
    console.log(props)
  }
}
</script>

未完待续~~~

猜你喜欢

转载自blog.csdn.net/u010716530/article/details/107978361