vue3 setup语法糖

发布时间:2024年01月17日

一、简介

vue3.2 版本开始才能使用语法糖!

在 Vue3.0 中变量必须 return 出来, template 中才能使用;而在 Vue3.2 中只需要在 script 标签上加上 setup 属性,无需 return , template 便可直接使用,非常的香啊!

Vue3 的一大特性函数 ---- setup
  1、setup函数是处于 生命周期函数 beforeCreate 和 Created 两个钩子函数之间的函数 也就说在 setup函数中是无法 使用 data 和 methods 中的数据和方法的
  2、setup函数是 Composition API(组合API)的入口
  3、在setup函数中定义的变量和方法最后都是需要 return 出去的 不然无法再模板中使用

二、代码

<template>
    <div>
      <div>{{ readersNumber }}</div>
      <el-button type="primary" @click="onClick">自定义点击事件</el-button>
    </div>
  </template>
  
  <script>
  /* 方式一:(script 右边写上 setup)*/
  import {onBeforeMount, ref} from "vue";
  const readersNumber = ref('绿色回收')
  const onClick = () => {
    console.log(readersNumber.value)
    if (typeof readersNumber.value === "string") {
      console.log('string')
    } else {
      console.log('other')
    }
    // alert(readersNumber)
  }
  onBeforeMount(() => {
    console.log('数据渲染前')
  })
  </script>
<template>
    <div>
      <div>{{ readersNumber }}</div>
      <el-button type="primary" @click="onClick">自定义点击事件</el-button>
    </div>
  </template>
  
  <script>
  /* 方式二:*/
 import {onBeforeMount, ref} from "vue";
 export default {
   name: "OrderForm_BP",
   setup() {
     const readersNumber = ref('OrderForm_BP')
     const onClick = () => {
       console.log(readersNumber.value)
       if (typeof readersNumber.value === "string") {
         console.log('string')
       } else {
         console.log('other')
       }
       // alert(readersNumber)
     }
     onBeforeMount(()=>{
       console.log('数据渲染前')
     })
     return {
       onClick,
       readersNumber,
     }
   }
 }
  </script>
<template>
  <div>
    <div>{{ readersNumber }}</div>
    <el-button type="primary" @click="onClick">自定义点击事件</el-button>
  </div>
</template>

<script>
/* 方式一:(script 右边写上 setup)*/
// import {onBeforeMount, ref} from "vue";
// const readersNumber = ref('绿色回收')
// const onClick = () => {
//   console.log(readersNumber.value)
//   if (typeof readersNumber.value === "string") {
//     console.log('string')
//   } else {
//     console.log('other')
//   }
//   // alert(readersNumber)
// }
// onBeforeMount(() => {
//   console.log('数据渲染前')
// })


/* 方式二:*/
// import {onBeforeMount, ref} from "vue";
// export default {
//   name: "OrderForm_BP",
//   setup() {
//     const readersNumber = ref('OrderForm_BP')
//     const onClick = () => {
//       console.log(readersNumber.value)
//       if (typeof readersNumber.value === "string") {
//         console.log('string')
//       } else {
//         console.log('other')
//       }
//       // alert(readersNumber)
//     }
//     onBeforeMount(()=>{
//       console.log('数据渲染前')
//     })
//     return {
//       onClick,
//       readersNumber,
//     }
//   }
// }

/* 方式三:*/
import {reactive, toRefs} from "vue";

export default {
  name: "SetupDemo",
  setup() {
    const data = reactive({
      readersNumber: "",
      userList: [],
      tableList: [],
    })
    const onClick = function () {
      console.log(data.readersNumber, '自定义点击事件')
      data.readersNumber = 'readersNumber数据'
      if (data.readersNumber === "readersNumber") {
        console.log('string')
      } else {
        console.log('other')
      }
    }
    return {
      //解构
      ...toRefs(data),
      onClick
    }
  }
}

</script>

<style scoped>

</style>
<script>
import {SignalR} from "@/client/signalR";
import { inject,onMounted,onUpdated } from 'vue'
export default {
  //inject:['reload','name1'],
  name: "ChatHub",
 
  beforeCreate() {
    let Token = this.$storage.get("Token");
    if(Token){
      SignalR.setToken(Token);

      SignalR.get('/Service/Access/Current').then(res=> {
        console.log(res)
        if (res.statusCode === 200) {
          this.InitSignalR();
          SignalR.start(Token)
              .then(() => {
                SignalR.invoke("Init")
              });
        } else {
          this.$message.warning("请先登录")
          SignalR.removeToken();
          this.$storage.remove("Token")
        }
      })
    }else{
      this.$message.warning("请先登录");
    }


  },
  data(){
    return {
      Groups:[],
      Clients:[],
      My:null,
      CurrentClient:null,
      AllUnReads: 0,
      GroupUnReads:0,
      Form:{
        LoginForm:{UserName:'',Password:'123456',Role:'?'},
        Visible:false,
        GroupForm:{GroupName:''},
        G_Visible:false,
      },
      Picture:{
        Preview:false,
        file:[],
        MainPreview:false,
        MainSrc:null,
      },
      Event:{o:{},p:{},s:{},v:''}
    }
  },
 
  methods:{
    DownToLatest(){
      this.$nextTick(
          ()=>setTimeout(
              ()=>{
                this.$nextTick(function(){
                  this.$refs.ScrollRef.setScrollTop(document.getElementById("ElScroll").parentNode.getBoundingClientRect().height);
                });
              },50
          )
      );
    },

    InitSignalR(){
      SignalR.listen("System",(handler,args)=>{
        args = JSON.parse(args);
        console.log(args)
        switch (handler) {
          case "Init":
            this.My = args;
            break;
          case "Groups":
            this.Groups = args;
            this.Groups.forEach(x=>{this.InitNewClient(x);})
            break;
          case "Clients":
            this.Clients = args;
            this.Clients.forEach(x=>{this.InitNewClient(x);})
            break;
          case "Alert":
            this.$message.warning(args);
            break;
        }
      });
      SignalR.listen("Entire",(handler,args)=>{
        args = JSON.parse(args);
        console.log(args)
        switch (handler) {
          case "OnLine":
            this.InitNewClient(args);
            this.ClientOnLine(args);
            break;
          case "OffLine":
          {
            /*this.Clients.forEach(function(item, index, arr) {
              if(item.userId === args.userId ) {
                arr.splice(index, 1);
              }
            });*/
            let client = this.Clients.find(x => x.userId === args.userId);
            client.status = 0;
            break;
          }
          case "Clients":
            this.Clients = args;
            break;
          case "GroupCreate":
            this.InitNewClient(args);
            this.Groups.push(args);
            break;
        }
      });
      SignalR.listen("Group",(handler,args)=>{
        args = JSON.parse(args);
        console.log(args)
        switch (handler) {
          case "GroupMessage": {
            let group = this.Groups.find(x => x.groupId === args.p.groupId)
            let client = this.Clients.find(x=>x.userId===args.s.userId);
            let message = args.o;
            let M = {message:message,client:client }
            group.Messages.push(M)
            if(!this.CurrentClient || (this.CurrentClient && this.CurrentClient.groupId!==group.groupId)){
              group.unReads++;
              this.GroupUnReads++;
            }else{
              this.DownToLatest();
            }
            break;
          }

        }
      });
      SignalR.listen("Client",(handler,args)=>{
        args = JSON.parse(args);
        console.log(args)
        switch (handler) {
          case "ClientMessage": {
            let client = this.Clients.find(x => x.userId === args.s.userId);
            let M = {message:args.o,client:client }
            client.Messages.push(M);
            if(!this.CurrentClient || (this.CurrentClient && this.CurrentClient.userId!==client.userId)){
              client.unReads++;
              this.AllUnReads++;
            }else{
              this.DownToLatest();
            }
            console.log(client)
            break;
          }
        }
      });
    },
    ClientOnLine(Client){
      let client = this.Clients.find(x => x.userId === Client.userId);
      if(client){
        client.connectionId=Client.connectionId;
        client.status=1;
      }else{
        this.Clients.push(Client);
      }
    },
    InitNewClient(Client){
      Client.unReads=0;
      Client.Messages=[];
      Client.SendingMessage='';
      Client.status = 1;
      Client.SendingPicture = [];
    },
    Chat(Client){
      this.CurrentClient = Client;
      if(Client.userId) {
        this.AllUnReads -= this.CurrentClient.unReads;
        this.CurrentClient.unReads = 0;
      }
      if(Client.groupId){
        this.GroupUnReads -= this.CurrentClient.unReads;
        this.CurrentClient.unReads = 0;
      }
      this.DownToLatest();
    },
  },

  setup(){

  const reload = inject('reload');
  const name1 = inject('name1');
  onMounted(()=> {
    console.log("mounted")
   // this.reload();
  });
  onUpdated(()=>{
    console.log("update")
  }) ;
  return { reload};
  }
}
</script>

三、说明

NO.1 setup写在script标签内。

使用ref绑定数据,无需export,import的组件页面内可以直接使用,但需要反复const,ref数据。调用数据{数据名}.value。

<script setup>
import {onBeforeMount, ref} from "vue";
const readersNumber = ref('setup写在script标签内')
const onClick = () => {
  console.log(readersNumber.value)
  if (typeof readersNumber.value === "string") {
    console.log('string')
  } else {
    console.log('other')
  }
  // alert(readersNumber)
}
onBeforeMount(() => {
  console.log('数据渲染前')
})

</script>

NO.2 setup写在js中。

使用ref绑定数据,事件和数据都需要return出去。调用数据{数据名}.value。

<script>
import {ref} from "vue";
export default {
  name: "SetupDemo",
  setup() {
    const readersNumber = ref('setup写在js中')
    const onClick = () => {
      console.log(readersNumber.value)
      if (typeof readersNumber.value === "string") {
        console.log('string')
      } else {
        console.log('other')
      }
      // alert(readersNumber)
    }
    return {
      onClick,
      readersNumber,
    }
  }
}
</script>

NO.3 setup写在js中,使用reactive打包页面内数据,再使用toRefs解构。

避免数据反复const和return,事件需要return出去。调用数据data.{数据名}。

<script>
import {reactive, toRefs} from "vue";

export default {
  name: "SetupDemo",
  setup() {
    //data可以自定义名字
    const data = reactive({
      readersNumber: "setup写在js中"
    })
    const onClick = function () {
      console.log(data.readersNumber, '自定义点击事件')
      data.readersNumber = 'setup写在js中'
      if (data.readersNumber === "readersNumber") {
        console.log('string')
      } else {
        console.log('other')
      }
    }
    return {
      //解构
      ...toRefs(data),
      onClick
    }
  }
}
</script>

四、PS:关于vue3生命周期介绍

<script>
import {onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated, reactive, toRefs} from "vue";

export default {
  name: "SetupDemo",
  setup() {
    const data = reactive({
      readersNumber: "",
    })
    const onClick = function () {
      console.log(data.readersNumber, '自定义点击事件')
      data.readersNumber = 'readersNumber'
      if (data.readersNumber === "readersNumber") {
        console.log('string')
      } else {
        console.log('other')
      }
    }
    //生命周期
    onBeforeMount(() => {
      console.log('数据渲染前')
    })
    onMounted(() => {
      console.log('渲染结束')
    })
    onBeforeUpdate(() => {
      console.log('页面Dom更新之前')
    })
    onUpdated(() => {
      console.log('页面Dom更新之后')
    })
    onBeforeUnmount(() => {
      console.log('Vue实例销毁之前')
    })
    onUnmounted(() => {
      console.log('Vue实例销毁之后')
    })
    return {
      //解构
      ...toRefs(data),
      onClick
    }
  }
}
</script>

1、如何使用setup语法糖

只需在 script 标签上写上 setup

代码如下(示例):

<template>
</template>
<script setup>
</script>
<style scoped lang="less">
</style>

2、data数据的使用

由于 setup 不需写 return ,所以直接声明数据即可

<script setup>
    import {
      ref,
reactive,
      toRefs,
    } from 'vue'

    const data = reactive({
      patternVisible: false,
      debugVisible: false,
      aboutExeVisible: false,
    })

    const content = ref('content')
    //使用toRefs解构
    const { patternVisible, debugVisible, aboutExeVisible } = toRefs(data)
</script>

3、method方法的使用

<template >
    <button @click="onClickHelp">系统帮助</button>
</template>
<script setup>
import {reactive} from 'vue'

const data = reactive({
      aboutExeVisible: false,
})
// 点击帮助
const onClickHelp = () => {
    console.log(`系统帮助`)
    data.aboutExeVisible = true
}
</script>

4、watchEffect的使用

<script setup>
import {
  ref,
  watchEffect,
} from 'vue'

let sum = ref(0)

watchEffect(()=>{
  const x1 = sum.value
  console.log('watchEffect所指定的回调执行了')
})
</script>

5、watch的使用

<script setup>
    import {
      reactive,
      watch,
    } from 'vue'
     //数据
     let sum = ref(0)
     let msg = ref('你好啊')
     let person = reactive({
                    name:'张三',
                    age:18,
                    job:{
                      j1:{
                        salary:20
                      }
                    }
                  })
    // 两种监听格式
    watch([sum,msg],(newValue,oldValue)=>{
            console.log('sum或msg变了',newValue,oldValue)
          },{immediate:true})

     watch(()=>person.job,(newValue,oldValue)=>{
        console.log('person的job变化了',newValue,oldValue)
     },{deep:true}) 

</script>

6、computed计算属性的使用

<script setup>
    import {
      reactive,
      computed,
    } from 'vue'

    //数据
    let person = reactive({
       firstName:'小',
       lastName:'叮当'
     })
    // 计算属性简写
    person.fullName = computed(()=>{
        return person.firstName + '-' + person.lastName
      }) 
    // 完整写法
    person.fullName = computed({
      get(){
        return person.firstName + '-' + person.lastName
      },
      set(value){
        const nameArr = value.split('-')
        person.firstName = nameArr[0]
        person.lastName = nameArr[1]
      }
    })
</script>

7 、props父子传值的使用

子组件代码如下(示例):

<template>
  <span>{{props.name}}</span>
</template>

<script setup>
  import { defineProps } from 'vue'
  // 声明props
  const props = defineProps({
    name: {
      type: String,
      default: '11'
    }
  })  
  // 或者
  //const props = defineProps(['name'])
</script>
父组件代码如下(示例):
<template>
  <child :name='name'/>  
</template>

<script setup>
    import {ref} from 'vue'
    // 引入子组件
    import child from './child.vue'
    let name= ref('小叮当')
</script>

8 、emit子父传值的使用

子组件代码如下(示例):

<template>
   <a-button @click="isOk">
     确定
   </a-button>
</template>
<script setup>
import { defineEmits } from 'vue';

// emit
const emit = defineEmits(['aboutExeVisible'])
/**
 * 方法
 */
// 点击确定按钮
const isOk = () => {
  emit('aboutExeVisible');
}
</script>
父组件代码如下(示例):
<template>
  <AdoutExe @aboutExeVisible="aboutExeHandleCancel" />
</template>
<script setup>
import {reactive} from 'vue'
// 导入子组件
import AdoutExe from '../components/AdoutExeCom'

const data = reactive({
  aboutExeVisible: false, 
})
// content组件ref


// 关于系统隐藏
const aboutExeHandleCancel = () => {
  data.aboutExeVisible = false
}
</script>

9、获取子组件ref变量和defineExpose暴露

即 vue2 中的获取子组件的 ref ,直接在父组件中控制子组件方法和变量的方法

子组件代码如下(示例):

<template>
    <p>{{data }}</p>
</template>

<script setup>
import {
  reactive,
  toRefs
} from 'vue'

/**
 * 数据部分
 * */
const data = reactive({
  modelVisible: false,
  historyVisible: false, 
  reportVisible: false, 
})
defineExpose({
  ...toRefs(data),
})
</script>
父组件代码如下(示例):
<template>
    <button @click="onClickSetUp">点击</button>
    <Content ref="content" />
</template>

<script setup>
import {ref} from 'vue'

// content组件ref
const content = ref('content')
// 点击设置
const onClickSetUp = ({ key }) => {
   content.value.modelVisible = true
}
</script>
<style scoped lang="less">
</style>

10、路由useRoute和us eRouter的使用

<script setup>
  import { useRoute, useRouter } from 'vue-router'

  // 声明
  const route = useRoute()
  const router = useRouter()

  // 获取query
  console.log(route.query)
  // 获取params
  console.log(route.params)

  // 路由跳转
  router.push({
      path: `/index`
  })
</script>

11、store仓库的使用

<script setup>
  import { useStore } from 'vuex'
  import { num } from '../store/index'

  const store = useStore(num)

  // 获取Vuex的state
  console.log(store.state.number)
  // 获取Vuex的getters
  console.log(store.state.getNumber)

  // 提交mutations
  store.commit('fnName')

  // 分发actions的方法
  store.dispatch('fnName')
</script>

12、await的支持

<script setup>
  import api from '../api/Api'
  const data = await Api.getData()
  console.log(data)
</script>

13、provide 和 inject 祖孙传值

父组件代码如下(示例):

<template>
  <AdoutExe />
</template>

<script setup>
  import { ref,provide } from 'vue'
  import AdoutExe from '@/components/AdoutExeCom'

  let name = ref('Jerry')
  // 使用provide
  provide('provideState', {
    name,
    changeName: () => {
      name.value = '小叮当'
    }
  })
</script>
子组件代码如下(示例):
<script setup>
  import { inject } from 'vue'
  const provideState = inject('provideState')

  provideState.changeName()
</script>
文章来源:https://blog.csdn.net/gqk01/article/details/135641666
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。