Vue3.0.0 is coming !

2020-09-25 11:01:04

First - Update @vue/cli

npm i @vue/cli@latest -g

Second - Look New Type

import * as vue from 'vue';
console.log(vue)
{
  BaseTransition: Object,
  Comment: Symbol(Comment),
  Fragment: Symbol(Fragment),
  KeepAlive: Object,
  Static: Symbol(Static),
  Suspense: Object,
  Teleport: Object,
  Text: Symbol(Text)
  Transition: (props, { slots }) => {},
  TransitionGroup: Object,
  callWithAsyncErrorHandling: ƒ callWithAsyncErrorHandling(fn, instance, type, args),
  callWithErrorHandling: ƒ callWithErrorHandling(fn, instance, type, args),
  camelize: (str) => {},
  capitalize: (str) => {},
  cloneVNode: ƒ cloneVNode(vnode, extraProps, mergeRef = false),
  compile: () => {},
  computed: ƒ computed(getterOrOptions),
  createApp: (...args) => {},
  createBlock: ƒ createBlock(type, props, children, patchFlag, dynamicProps),
  createCommentVNode: ƒ createCommentVNode(text = ''){}, 
  createHydrationRenderer: ƒ createHydrationRenderer(options),
  createRenderer: ƒ createRenderer(options),
  createSSRApp: (...args) => {},
  createSlots: ƒ createSlots(slots, dynamicSlots),
  createStaticVNode: ƒ createStaticVNode(content, numberOfNodes),
  createTextVNode: ƒ createTextVNode(text = ' ', flag = 0),
  createVNode: (...args) => {},
  customRef: ƒ customRef(factory),
  defineAsyncComponent: ƒ defineAsyncComponent(source),
  defineComponent: ƒ defineComponent(options),
  devtools: Object,
  getCurrentInstance: () => currentInstance || currentRenderingInstance,
  getTransitionRawChildren: ƒ getTransitionRawChildren(children, keepComment = false),
  h: ƒ h(type, propsOrChildren, children),
  handleError: ƒ handleError(err, instance, type, throwInDev = true),
  hydrate: (...args) => {},
  inject: ƒ inject(key, defaultValue, treatDefaultAsFactory = false),
  isProxy: ƒ isProxy(value),
  isReactive: ƒ isReactive(value),
  isReadonly: ƒ isReadonly(value),
  isRef: ƒ isRef(r),
  isVNode: ƒ isVNode(value),
  markRaw: ƒ markRaw(value),
  mergeProps: ƒ mergeProps(...args),
  nextTick: ƒ nextTick(fn),
  onActivated: ƒ onActivated(hook, target),
  onBeforeMount: (hook, target = currentInstance) => {},
  onBeforeUnmount: (hook, target = currentInstance) => {},
  onBeforeUpdate: (hook, target = currentInstance) => {},
  onDeactivated: ƒ onDeactivated(hook, target),
  onErrorCaptured: (hook, target = currentInstance) => {},
  onMounted: (hook, target = currentInstance) => {},
  onRenderTracked: (hook, target = currentInstance) => {},
  onRenderTriggered: (hook, target = currentInstance) => {},
  onUnmounted: (hook, target = currentInstance) => {},
  onUpdated: (hook, target = currentInstance) => {},
  openBlock: ƒ openBlock(disableTracking = false),
  popScopeId: ƒ popScopeId(),
  provide: ƒ provide(key, value),
  proxyRefs: ƒ proxyRefs(objectWithRefs),
  pushScopeId: (...),
  queuePostFlushCb: (...),
  reactive: (...),
  readonly: (...),
  ref: (...),
  registerRuntimeCompiler: (...),
  render: (...),
  renderList: (...),
  renderSlot: (...),
  resolveComponent: (...),
  resolveDirective: (...),
  resolveDynamicComponent: (...),
  resolveTransitionHooks: (...),
  setBlockTracking: (...),
  setDevtoolsHook: (...),
  setTransitionHooks: (...),
  shallowReactive: (...),
  shallowReadonly: (...),
  shallowRef: (...),
  ssrContextKey: (...),
  ssrUtils: (...),
  toDisplayString: (...),
  toHandlers: (...),
  toRaw: (...),
  toRef: (...),
  toRefs: (...),
  transformVNodeArgs: (...),
  triggerRef: (...),
  unref: (...),
  useCssModule: (...),
  useCssVars: (...),
  useSSRContext: (...),
  useTransitionState: (...),
  vModelCheckbox: (...),
  vModelDynamic: (...),
  vModelRadio: (...),
  vModelSelect: (...),
  vModelText: (...),
  vShow: (...),
  version: (...),
  warn: (...),
  watch: (...),
  watchEffect: (...),
  withCtx: (...),
  withDirectives: (...),
  withKeys: (...),
  withModifiers: (...),
  withScopeId: (...)
}

Third - Write Demo

Please refer to the notes for detailed explanation

<template>
  <div class="reactivity">
    <h3>reactivity</h3>
    {{ reactiveObj.num }}
    <button @click="handleReactivityAdd">add</button>
  </div>

  <div class="readonly">
    <h3>readonly</h3>
    {{ readonlyA.a }}
  </div>

  <div class="ref">
    <h3>ref</h3>
    {{ reactiveRef }}
    <div ref="refDiv"></div>
    <button @click="handleRefAdd">add</button>
  </div>

  <div class="toRef">
    <h3>toRef</h3>
    {{ reactiveA }}
    <button @click="handleToRefAdd">add</button>
  </div>

  <div class="toRefs">
    <h3>toRefs</h3>
    {{ b }}
    <button @click="handleToRefsAdd">add</button>
  </div>

  <div class="computed">
    <h3>computed</h3>
    {{ conputedA }}
    <button @click="handleComputedAdd">add</button>
  </div>

  <div class="customRef">
    <h3>customRef</h3>
    <input type="text" v-model="customR" />
    {{ customR }}
  </div>

  <div class="toRaw">
    <h3>toRaw</h3>
    look console
  </div>

  <!-- shallowReactive/shallowReadonly/shallowRef -->
  <div>
    <h3>shallowReactive/shallowReadonly/shallowRef</h3>
    look console
  </div>

  <!-- watch/watchEffect -->
  <div class="watch">
    <h3>watch/watchEffect</h3>
    <button @click="handleChange">click and look console</button>
  </div>

  <div class="nextTick">
    <h3>nextTick</h3>
    {{ reactiveNextTickObj.a }}
    <button @click="handleNextTickChange">add and look console</button>
  </div>

  <!-- provide/inject -->
  <div>
    <h3>provide/inject</h3>
    look console
  </div>

  <div class="getCurrentInstance">
    <h3>getCurrentInstance</h3>
    look console
  </div>
</template>

<script>
import { reactive, readonly, ref, onMounted, toRef, toRefs, computed, customRef, toRaw, isReactive, shallowReactive, shallowReadonly, 
shallowRef, watch, watchEffect, nextTick, provide, inject, getCurrentInstance } from 'vue';
export default {
  setup() {
    // reactivity: Receives a normal object and returns the responsive proxy for that common object
    let reactiveObj = reactive({ num: 1, a: 1, b: 2, c: 3 });
    const handleReactivityAdd = () => { reactiveObj.num += 1; };

    // readonly: Gets an object (responsive or pure) or ref and returns the read-only proxy of the original agent. Read only proxies are deep: any nested properties accessed are also read-only.
    const readonlyA = readonly({ a: 1 });
    readonlyA.a += 2;
    // Set operation on key "a" failed: target is readonly. { a: 1 }

    // ref: Accepts the parameter and returns it wrapped in an object with a value property, which can then be used to access or change the value of the response variable, and on components or elements that can also function
    let reactiveRef = ref(0);
    let refDiv = ref(0);
    const handleRefAdd = () => { reactiveRef.value += 1 };
    let handleMounted = async () => { console.log(refDiv) };
    onMounted(handleMounted);

    // toRef: Can be used to create a ref for properties on source responsive objects. You can then pass the ref out to maintain a responsive connection to its source property.
    const reactiveA = toRef(reactiveObj, 'a');
    const handleToRefAdd = () => { reactiveA.value += 1 };

    // toRefs: Convert a responsive object to a normal object, where each property of the result object is a ref pointing to the corresponding property of the original object.
    const handleToRefsAdd = () => { reactiveObj.b += 1 };

    // computed: Like ref and watch, you can use the computed functions imported from Vue to create calculated properties outside the Vue component.
    const conputedA = computed(() => reactiveObj.c + 2);
    const handleComputedAdd = () => { reactiveObj.c += 1 };

    // customRef: Create a custom ref and explicitly control its dependency tracking and update triggering. It needs a factory function that takes the track and trigger functions as parameters and should return an object with get and set.
    const handleCustom = ( value, delay = 1000 ) => {
      let timeout;
      return customRef((track, trigger) => {
        return {
          get() {
            track();
            return value;
          },
          set(newValue) {
            clearTimeout(timeout);
            timeout = setTimeout(() => {
              value = newValue;
              trigger();
            }, delay)
          }
        }
      })
    }

    // toRaw: Returns the original object of the reactive or readonly proxy. This is an escape port that can be used for temporary read without proxy access / trace overhead, or for writing without triggering changes. It is not recommended to keep a persistent reference to the original object. Please use with caution.
    const obj = {};
    const reactiveToRawObj = reactive(obj);
    console.log('toRaw------' + (toRaw(reactiveToRawObj) === obj));            // true

    // shallowReactive/shallowReadonly/shallowRef:
    
    // Shadowreactive creates a responsive proxy that tracks the responsiveness of its own properties, but does not perform deep responsive conversions of nested objects (exposing the original values).
    
 	// Shallowreadonly creates a proxy with its own property read-only, but does not perform deep read-only conversion of nested objects (exposing the original values).
 	
	// Shadowref creates a ref that tracks its own. Value changes, but does not make its value responsive.
    const shallowObj = shallowReactive({
      a: '123',
      b: {
        c: 456
      }
    });
    const readonlyShallowObj = shallowReadonly({
      a: '123',
      b: {
        c: 456
      }
    });
    const shallowRefObj = shallowRef(0);

    console.log('shallowReactive------' + isReactive(shallowObj.b));           // false
    console.log('shallowReadonly------' + isReactive(readonlyShallowObj.b));   // false
    console.log('shallowRef------' + isReactive(shallowRefObj.value));         // false

    // watch/watchEffect:

	// Watch needs to listen to a specific data (responsive) source and have side effects in a separate callback function. By default, it is also inert -- that is, callbacks are called only when the listening source changes.
	
	// Watcheffect immediately runs a function when it tracks its dependencies responsibly and reruns it when the dependency changes.
    let reactiveObjA = reactive({ a: 1 });
    let reactiveObjB = reactive({ b: 1 });
    const handleChange = () => {
      reactiveObjA.a += 1;
      reactiveObjB.b += 1;
    };
    watchEffect(() => {
      console.log('reactiveObjA.a------' + reactiveObjA.a)
      console.log('reactiveObjB.b------' + reactiveObjB.b)
    })
    watch(
      [() => reactiveObjA.a, () => reactiveObjB.b],
      ([newA, newB], [a, b]) => {
        console.log('newA------' + newA);
        console.log('newB------' + newB);
        console.log('a------' + a);
        console.log('b------' + b);
      }
    )

    // nextTick: Postpone the callback until after the next DOM update cycle. Use it as soon as you have changed some data to wait for the DOM to update.
    const reactiveNextTickObj = reactive({ a: 1 });
    const handleNextTickChange = async () => {
      reactiveNextTickObj.a += 1;
      await nextTick();
      console.log('dom is uodated')
    }

    // provide/inject: Provide and inject enable dependency injection. Both can be called only during setup () using the current active instance.
    provide('a', 1);
    const a = inject('a');
    console.log('provide/inject------' + a)

    // getCurrentInstance: Gets an instance of the current component, similar to this of 2.0
    const { ctx } = getCurrentInstance();
    console.log('getCurrentInstance------')
    console.log(ctx)

    // createApp/createSSRApp
    // createApp(App).use(store).use(router).mount('#app');

    return {
      reactiveObj,
      handleReactivityAdd,
      readonlyA,
      reactiveRef,
      handleRefAdd,
      refDiv,
      handleMounted,
      reactiveA,
      handleToRefAdd,
      handleToRefsAdd,
      ...toRefs(reactiveObj),
      conputedA,
      handleComputedAdd,
      customR: handleCustom(''),
      handleChange,
      reactiveNextTickObj,
      handleNextTickChange
    };
  }
}
</script>

<style scoped>
  h3 {
    color: rgb(177, 12, 12);
  }
</style>