官方还没有正式推出来,利用@vue/composition-api先预热一下

初始化项目
npm install -g @vue/cli

vue create vue3

npm install @vue/composition-api --save

// main.js 导入
import VueComposition from '@vue/composition-api'

Vue.use(VueComposition)
一、setup

setup是专门为使用vue3的composition-api新特性开放的统一入口

1.1 执行时机
beforeCreate 与 created 之间

可以新建一个模块,如下操作

import {} from "@vue/composition-api";
export default {
  setup() {
    console.log("setup");
  },
  beforeCreate() {
    console.log("beforeCreate");
  },
  created() {
    console.log("created");
  },

在这里插入图片描述
1.2 接收props数据


// 父
 <setup :page = "1"></setup> 

// 子
  props: {
    page: { type: Number }
  },
  setup(props) {
    console.log(props.page);  // 1  props必须声明
  },

1.3 context

执行上下文,在setup中它可以取代this,因为在setup上是取不到this的

  setup(props,context) {
    // console.log("setup");
    //    console.log(props.page);
    console.log(context,"ctx")
  },

在这里插入图片描述

二、reactive

可以创建多个响应式的数据对象

setup.vue

<template>
  <div class="wrapper">
      <p>count:{{count}}</p>  // 没有state.count
      <button @click="count+=1">+1</button>
  </div>
</template>

<script>
import { reactive } from "@vue/composition-api";
export default {
  props: {
    page: { type: Number }
  },
  setup(props,context) {
    // console.log("setup");
    //    console.log(props.page);
    // console.log(context,"ctx")
    const state = reactive({count:0})
    state.count += 1;
    console.log(state)
    return state;
    
  },
  beforeCreate() {
    // console.log("beforeCreate");
  },
  created() {
    // console.log("created");
  },
  components: {},
  data() {
    return {};
  },

};
</script>
<style lang="css" scoped>
.wrapper {
}
</style>

在这里插入图片描述

三、ref

3.1 ref()

根据给定的值,创建响应式的数据对象,返回值是一个对象,且只有value。
建议使用ref创建,不提倡reactive

ref.vue

<template>
  <div class="wrapper">
      <div>{{a}}</div>  // 不需要a.value
      <button @click="a+=1">+1 ref</button>
  </div>
</template>

<script>
import { ref } from "@vue/composition-api";
export default {
  setup(){
      const a = ref(0)
      console.log(a.value)
      return {
          a
      }
  },
  components:{},
  props:{},
  data(){
    return {
    }
  },
}
</script>
<style lang="css" scoped>
.wrapper{}
</style>

3.2 在reactive中访问ref创建的响应式对象

setup(){
	  const  b =ref (1)
      const state = reactive({
          b
      })
      console.log(b)
}

3,3 ref覆盖

    const c1 = ref(2)
    const state = reactive({
        c1
    })

    const c2 = ref(9)
    state.c1 = c2
    state.c1++

    console.log(state.c1)  // 10
    console.log(c2.value)  // 10
    console.log(c1.value)  // 2

3.4 isRef

判断某个值是ref()创建

	import { isRef } from "@vue/composition-api"
	
    console.log(isRef(c2) ? c2.value : c2)

3.5 toRefs

toRefs函数能将reactive创建的响应式对象,转化成为普通的对象,只不过,这个对象上的每个节点,都是ref()类型的响应式数据

<template>
  <div class="wrapper">
    <div>count: {{count}}</div>
    <button @click="add">+1</button>
  </div>
</template>

<script>
import { reactive ,isRefs, toRefs} from "@vue/composition-api";
export default {
  setup(){
    const state = reactive({count:0,name:'yp'});

    // 定义+1方法
    const add =()=>{
      state.count += 1;
    }
    return {
      //...state,  // reactive 展开运算符后就不响应了
      ...toRefs(state),
      add
    }
  },
  data(){
    return {
    }
  },
  watch:{},
  computed:{},
}
</script>
<style lang="css" scoped>
.wrapper{}
</style>
四、computed

computed()函数用来创建计算属性,返回的是个ref实例

4.1 只读属性

<template>
  <div class="wrapper">
      <p>count:{{refCount}}</p>
      <p>计算属性:{{computedCount}}</p>
      <button @click="refCount+=1">+1</button>
  </div>
</template>

<script>
import { ref,computed } from "@vue/composition-api";
export default {
  setup(){
      const refCount = ref(0) 

      const computedCount = computed(()=> refCount.value+1)

  		//   computedCount=2
      return {
          refCount,
          computedCount
      }
  },
  components:{},
  props:{},
  data(){
    return {
    }
  },
}
</script>
<style lang="css" scoped>
.wrapper{}
</style>

4.2 可读可写

<template>
  <div class="wrapper">
    <p>count:{{refCount}}</p>
    <p>计算属性:{{computedCount}}</p>
    <button @click="refCount+=1">+1</button>
  </div>
</template>

<script>
import { ref, computed } from "@vue/composition-api";
export default {
  setup() {
    const refCount = ref(0);

    //   const computedCount = computed(()=> refCount.value+1)

    //   computedCount=2

    const computedCount = computed({
      get: () => refCount.value + 1,
      set: a => {
        refCount.value = a + 112;
      }
    });
    computedCount.value = 33;
    return {
      refCount,
      computedCount
    };
  },
  components: {},
  props: {},
  data() {
    return {};
  }
};
</script>
<style lang="css" scoped>
.wrapper {
}
</style>
五、watch

监视数据变化,做响应处理。组件创建,默认会执行一次,可配置项

5.1 基本用法

import { watch,ref, set } from "@vue/composition-api";
export default {
  setup(){
    const refCount = ref(0)

    watch(()=>console.log(refCount.value))

    setTimeout(()=>{
      refCount.value += 2;
    },1000)
  },
  data(){
    return {
    }
  },

}

5.2 监听指定数据源

ref

    const count = ref(2)
    watch(count,(count,oldCount)=>{
      console.log(count,oldCount)
    })
    setTimeout(() => {
      count.value += 2;
    }, 1000);
// 2 undefined
// 4 2

reactive

  setup() {
    const state = reactive({ count: 0 });
    watch(() => state.count, (count, oldCount) => console.log(count, oldCount));
    setTimeout(() => {
      state.count += 2;
    }, 1000);
  },
  // 0 undefined
  // 2 0
----------------------------------------
    watch(
      () => state.count,
       (count, oldCount) =>{ console.log(count, oldCount)},
       {lazy:true,} //组件第一次创建不调用
    );


5.3 监视多个数据源

ref

    const count = ref(0)
    const name = ref('yp1')

    watch(
      [count,name],
      ([count,name],[oldCount,oldName])=>{
        console.log(count)
        console.log(name)
        console.log('------------')
        console.log(oldCount)
        console.log(oldName)
      },
      {
        lazy:true
      }
    )
    setTimeout(()=>{
      count.value++
      name.value = "yp2"
    })
// 1
// yp2
// ---------------------
// 0
// yp1

reactive

   const state = reactive({count:0,name:'yp1'})
   
    watch(
      [()=>state.count,()=>state.name],
      ([count,name],[oldCount,oldName])=>{
        console.log(count)
        console.log(name)
        console.log("---------------------")
        console.log(oldCount)
        console.log(oldName)
      },
      {
        lazy: true
      }
    )
    setTimeout(()=>{
      state.count++
      state.name = "yp2"
    })
// 1
// yp2
// ---------------------
// 0
// yp1

5.4 取消监视

setup()函数内创建的watch监视,会在当前组件被销毁的时候自动停止。watch的返回值调用

两秒内点击按钮,取消了watch监听,可查 console

<template>
  <div class="wrapper">
    <div>{{count}}</div>
    <button @click="stopwatch">stop</button>
    
  </div>
</template>

<script>
import { watch, ref, set, reactive } from "@vue/composition-api";
export default {
  setup() {
    const count = ref(0)

    const stop = watch(()=>{
      console.log("监听到watch的变化"),
      console.log(count.value)
    }

    )

    setTimeout(() => {
        count.value += 2
    }, 2000);

    const stopwatch = ()=>{
      stop()
    }
    return {
      count,
      stopwatch
    }

  },
  data() {
    return {};
  }
};
</script>
<style lang="css" scoped>
.wrapper {
}
</style>

5.5 watch 清除无效的异步

watch监视的值发生变化的时候,或者watch本身被stop()之后,我们希望能够清除那些无效的异步任务,此时,watch回调中提供一个cleanup registrator function来执行清除的工作,

eg watch 被重复执行了 或者被强制stop

实际场景一:打开a.html 会执行a.html的页面的3个ajax请求;但是在有两个ajax请求还没有发出去的时候,用户打开b.html,那剩下的两个请求我就不需要再接着请求了

实际场景二:输入框按键输值请求

<!--  -->
<template>
  <div>
    <input type="text" v-model="kw">
  </div>
</template>

<script>
import { ref, watch } from "@vue/composition-api";
export default {
  name: "",
  setup() {
    const kw = ref("");

    const asyncprint = val => {
      return setTimeout(() => {
        console.log(val);
      }, 1000);
    };

    watch(
      kw,
      (kw, oldkw, callback) => {
        const timeId = asyncprint(kw);
        
        callback(()=>clearTimeout(timeId));
      },
      { lazy: true }
    );

    return {
      kw
    };
  },
  data() {
    return {};
  },

  created() {},

  components: {},

  computed: {},

  mounted() {},

  watch: {},

  methods: {}
};
</script>
<style lang='css' scoped>
</style>
六、 LifeCycle Hooks

setup()

vue2生命周期vue3生命周期
beforeCreatesetup
createdsetup
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestoryonBeforeDestory
destroyedonUnmounted
errorCapturedonErrorCaptured

建议异步请求,在onMounted()/mounted()

import { onBeforeMount,onMounted, } from "@vue/composition-api";

setup(){

    onBeforeMount(()=>{
        console.log("onBeforeMount")
    });
    onMounted(()=>{
        console.log("onMounted")
    })
    
}

七、provide & inject

7.1 共享普通数据

祖组件

import { provide } from '@vue/composition-api'

  setup(){
    provide('themeColor','red')  // 键值
  },

孙组件

import { inject } from '@vue/composition-api'

  setup(){
    const  color = inject('themeColor');

    return {
        color: color,
    }
  },

7.2 共享ref()数据

祖组件

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <h1>父组件</h1>
    <button @click="color='red'">红色</button>
    <button @click="color='yellow'">黄色</button>
    <button @click="color='blue'">蓝色</button>
    <hr>>
    <child />
  </div>
</template>

  setup(){
    const color = ref('red');
    provide('themeColor',color)
    return {
      color
    }
  },
八、refs

8.1 元素引用

<!-- refs -->
<template>
  <div>
      <h3 ref="h3Ref">我是一个h3标签</h3>
  </div>
</template>

<script>
import { ref , onMounted } from '@vue/composition-api'
export default {
  name:'',
  setup(){
      const h3Ref = ref(null)

      onMounted(()=>{
          h3Ref.value.style.color = "red"
      })

      return {
          h3Ref
      }
  }
}

8.2 组件的引用

子组件

<!-- refs -->
<template>
  <div>
      <h3 ref="h3Ref">我是一个h3标签</h3>
      <p>{{str1}}</p>
  </div>
</template>

<script>
import { ref , onMounted } from '@vue/composition-api'
export default {
  name:'',
  setup(){
    const str1 =  ref('this is 子组件')
    const setStr = ()=>{
        str1.value = "被赋值了---"
    }

    return {
        str1,
        setStr

    }
  }
}

</script>
<style lang='css' scoped>
</style>

父组件

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <template-refs ref="childref"></template-refs>

    <button @click="show">展示</button>
  </div>
</template>

<script>
import { provide, ref } from "@vue/composition-api";
import templateRefs from "./components/template-refs";
export default {
  name: "app",
  setup() {

    const childref = ref(null);
    const show = () => {
      childref.value.setStr() // 注意 .value  函数调用
      console.log(childref);
      console.log("str1的值是:" + childref.value.str1);
    };

    return {
      childref,
      show
    };
  },
  components: {

    templateRefs
  }
};
</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>

九、createComponent

非必需,完美配合typescript的类型推断的

gitHub:案例地址

Logo

前往低代码交流专区

更多推荐