关于javascript:vue30体验卡

52次阅读

共计 6506 个字符,预计需要花费 17 分钟才能阅读完成。

前言

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>
    

    未完待续~~~

    正文完
     0