vue3使用小结

1 watch 
 用法 :1 可以监听某个ref对象。此时watch的第一个参数可以直接是ref
 如下
 <input type="text" v-model="message" />

import {ref} from "vue"
setup(props,ctx){

const message =ref("")
watch(message,(newVal,oldVal)=>{
      console.log("newVal:",newVal)
      console.log("oldVal:",oldVal)
 })
     return{
    message:""
     }

2 可以监听某个reactive对象。此时watch的第一个参数必须是一个函数
<input type="text" v-model="message" />

import {reactive} from "vue"
setup(props,ctx){

const message =reactive({message:""})
watch(()=>{
  return state.message
},(newVal,oldVal)=>{
      console.log("newVal:",newVal)
      console.log("oldVal:",oldVal)
 })
     return{
    message:""
     }

3 对于props对象。我们进行监听的时候也必须采用函数的形式,哪怕监听的是props中某个对象的属性。

const props = defineProps({
	data: {
		type: Object,
		default: () => {}
	},
	imgList: {
		type: Array,
		default: () => []
	}
});



watch(
	() => props.data.checked,
	(n: boolean): void => {
		console.log("n---", n);
		n ? (isShow.value = true) : (isShow.value = false);
		console.log("isShow:", isShow.value);
		console.log("imgList:", props.imgList);
	}
);

请注意:这里我们监听props中传递过的来的data对象里面的checked属性,此时我们watch的第一个参数也必须采用函数形式,否则会报错

2 父子组件传值:

依旧通过props和emit来实现,只不过setup()中没有this。而是通过setup(props,context)来实现
子--》父  
contex.emit("my-emit",payload)

注意:vue3中新增了一个emits选项。可以通过在emits选项中指定自定义事件名称来向父级派送事件
如下:
----------父组件------- 
 <button @click="flag=true">打开</button>
  <tel  :visable="flag" @close="closeFlag"></tel>
import {  reactive,ref } from "vue"
import tel from "./tel.vue"
export default {
  name: 'HelloWorld',
  components:{tel},
  setup(){
   
  const flag=ref(false)
  const closeFlag=(val)=>{
    console.log("val:",val)
    flag.value=val
   }
    
    return {
       flag,
       closeFlag
      }
    }
}
子组件---tel.vue------
 <teleport to='body'>
        <div v-if="visable" class="wrap">
          <h2>
            <span>标题</span>
            <span @click="$emit('close',false)">x</span>
          </h2>
          <div class="p12">内容区</div>
        </div>
      </teleport>
import {ref} from "vue"
export default {
    name:'tel',
    emits:['close'], //注意这里,新增了emits选项
    props:['visable'],
    setup(props,ctx){      
      const closeTel=()=>{
        ctx.emit('close',false)
      }
      return{
        closeTel
      }
    }    
};

在vue中关于父子组件传值有一类特殊的存在。那就是v-mode。vue2中v-model实则是:vaule和input事件的语法糖;通过v-model绑定的值,在子组件中默认props的值的名称就是value;当然你也可以自定义model选项去更改默认的value这个名称和input事件;而在vue3中,这个默认的名称则变成了modelValue;而input事件则变成了update:事件

父组件:

<script setup>
import { ref } from 'vue';
import Count from './Count.vue';

defineProps({
  msg: String,
});

const num = ref(0);
</script>

<template>
  <h2>{{ num }}</h2>

  <Count v-model="num"></Count>
</template>

<style scoped>
a {
  color: #42b983;
}
</style>

子组件:

<template>
  <div>
    <button @click="updateCount">我是count组件</button>
  </div>
</template>

<script setup>
import { ref, defineProps, defineEmits } from 'vue';
const props = defineProps({
  modelValue: {
    type: Number,
    default: 0,
  },
});

const emits = defineEmits(['update:modelValue']);

const updateCount = () => {
  console.log(props.modelValue+ 1);
  emits('update:modelValue', props.modelValue+ 1);
};
</script>
<style scoped></style>

这里特别注意在定义emits时,update要和model一起作为事件。写成const emits = defineEmits(['update']);是错误的;

当然,如果你不喜欢modelValue这个默认值。则可以再v-model后面添加:attr来实现;比如上面的例子。我们改成这样:

父组件:

<script setup>
import { ref } from 'vue';
import Count from './Count.vue';

defineProps({
  msg: String,
});

const num = ref(0);
</script>

<template>
  <h2>{{ num }}</h2>
  <Count v-model:count="num"></Count>
</template>

<style scoped>
a {
  color: #42b983;
}
</style>

子组件:

<template>
  <div>
    <button @click="updateCount">我是count组件</button>
  </div>
</template>

<script setup>
import { ref, defineProps, defineEmits } from 'vue';
const props = defineProps({
  count: {
    type: Number,
    default: 0,
  },
});

const emits = defineEmits(['update:count']);

const updateCount = () => {
  console.log(props.count + 1);
  emits('update:count', props.count+ 1);
};
</script>
<style scoped></style>

这里只要注意一点:v-model:attr。这里的attr就是我们在子组件中props传过来的值

3 vue3中全局挂在axios
const app=createApp(App)
app.globalProperty.$axios=axios


4  vue-router 无任何页面路径匹配时
  {
    path: '/:pathMatch(.*)*',
    name: 'notFound',
    // redirect: 'notFound',
    component: () => import('../views/notFound.vue')
  }

5 新增api---expose选项的使用

vue3中新增了一个expose选项,用来在子组件中暴露一些属性和方法给外部。常用的场景是父组件中直接操作子组件的方法。在vue3.2中则直接被defineExpose()取代。具体用法如下:

父组件
<script setup>
import {getCurrentInstance, ref} from "vue"
import Test from './components/test.vue'

const testRef=ref(null)


const toggle=(flag)=>{
  flag?testRef.value.open():testRef.value.close()
}

</script>

<template>
  <el-button @click="toggle(true)"> 打开</el-button>
  <el-button @click="toggle(false)"> 关闭</el-button>
  <hr/>

  <Test msg="Vite + Vue"  ref="testRef"/>

</template>

<style scoped>

</style>
----------------------------------------------
子组件
<template>
  <div class="mask" v-if="show">
        <div class="cont">
            <span @click="close">x</span>
            <h1>this is cont</h1>
        </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const show=ref(false);

const open=()=>{
    show.value=true
}
const close=()=>{
    show.value=false
}
defineExpose({close,open})


</script>
<style  scoped>
.mask{
    position: fixed;
    top:0%;
    left:0;
    z-index:10;
    background:rgba(0,0,0,0.5);
    width: 100%;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
  
}

.cont{
    width:500px;
    height: 420px;
    background: #fff;
}
</style>

我们在子组件中通过defineExpose暴露了2个方法,分别是close,open。这样我们在父组件中通过ref引用拿到子组件,然后直接调用其close和open方法就可以正常打开弹窗(子组件),控制子组件显示和隐藏的show变量被隐藏在子组件内部。

6 插件注册与使用

一个简单的插件实例:

prew插件基础代码:

loading.vue
----------------------------------------------------------
<template>
   <div v-if="isShow" class="loading">
        <div class="loading-content">
            <h1>Loading...</h1>
            <h2 @click="hide">x</h2>
        </div>
    </div>

</template>

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

const isShow = ref(false)//

const show = () => {
    isShow.value = true
}
const hide = () => {
    isShow.value = false
}
defineExpose({
    show,
    hide
})
</script>
<style  scoped lang="less">
----------------------------------------------------------
loading.js

import {  createVNode, render, } from 'vue';
import Loading from './loading.vue'
 
export default {
    install(app) {
        //createVNode vue提供的底层方法 可以给我们组件创建一个虚拟DOM 也就是Vnode
        const vnode = createVNode(Loading)
        //render 把我们的Vnode 生成真实DOM 并且挂载到指定节点
        render(vnode, document.body)
        // Vue 提供的全局配置 可以自定义
        app.config.globalProperties.$testLoading = {
            show: () => vnode.component?.exposed?.show(),
            hide: () => vnode.component?.exposed?.hide()
        }
 
    }
}

----------------------------------------------------------
main.js注册

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import Loading from "./libs/loading"
createApp(App).use(ElementPlus).use(Loading).mount('#app')

页面中使用:

test.vue页面
---------------------------------------------------------
<template>

    <el-button @click="testPlugin"> 测试插件</el-button>

</template>
<script setup>

import {getCurrentInstance, ref} from "vue"

const {proxy}=getCurrentInstance()

const testPlugin=()=>{   
    console.log("proxy",proxy)
    proxy.$testLoading.show()
}

</scritp>

特别注意:

(1)由于vue3提供了expose选项。用于向外部提供一些子组件内部的方法。这里插件的方法show和hide由于我们通过defineExpose()对外暴露。然后我们在注册到golobalProperties上的时候通过vnode.component.exposed就能拿到show和hide方法。;

(2)在页面中我们通过获取实例的方式去调用.$testLoading.show()的时候,通过const {proxy}=getCurrentInstance()就可以直接调用。无需通过instance.config.globalProperties.$testLoaidng.show()这样一长串的方式去调用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值