Vue3基础

目录

按需导入:defineComponent

定义变量

setup

ref

reactive

方法的定义和使用

父子组件传值

监听器

生命周期

Hook函数

shallowReactive和shallowRef

readonly和shallowReadonly

toRaw和markRaw

provide和inject

响应式数据的判断

Suspense(不确定的)


按需导入:defineComponent

import {defineComponent} from 'vue' export default defineComponent({})

定义变量

setup

变量需要在setup中定义,在生命周期beforeCreated之前执行,且只执行一次,在组件还没有加载时就生成,所以this无法使用,不能通过this去调用data、computed、methods、props;并且所有的compostionAPI相关回调函数都不可用

返回值:返回值是一个对象,内部的属性和方法是给html使用的

              返回对象中的属性会与data函数返回对象的属性合并为组件对象属性/方法

setup不能是async含函数,:返回值不再是return对象,而是promise,模板看不到return对象中的属性数据

ref

1.一般用来定义一个基本数据类型的响应式数据,js中需要操作使用ref.value获得数据,模板中不需要.value

2.获取页面中的元素

<input ref="inputRef" /> 
setup(){ const inputRef = ref<HTMLElement|null>(null) 
onMounted(()=>{inputRef.value && inputRef.value.focus()}) }

reactive

定义多个数据的响应式

返回一个proxy代理对象,被代理者就是reactive中的对象

不能直接结构出代理对象的属性,否则会丢失响应式,需要使用toRefs来结构

//ref方式,需要先引入ref,
import {defineComponent,ref} from 'vue'
export default defineComponent({})
setup(){
    let name = ref('tom'),
    let age = ref(18),
    return {//必须返回
        name,
        age
    }
}
// reactive方式,可搭配toRefs使用
import {defineComponent,reactive,toRefs} from 'vue'
export default defineComponent({})
setup(){
    let data = reactive({
        name:'tom',
        age:19
    })
    return {//必须返回
        data //直接返回data
        ...toRefs(data) //结构出data中的属性   
    }
}

方法的定义和使用

方法定义在setup中需要return出去

如果使用ref定义变量x则取值时需要x.value,使用reactive定义对象只需正常取值即可

<template>
  <div>
    <div @click="nameClick">{{name}}</div>
    <div @click="ageClick">{{age}}</div>
  </div>
</template>
<script>
import { defineComponent,ref,reactive,toRefs } from "vue";
export default defineComponent({
  name: "setupDemo",
  props: {},
  components: {
  },
  setup(props, ctx) {
    let name = ref('Tom')
    const data = reactive({
        age:99,
        gender:'男'
    })
    let nameClick = ()=>{
        console.log(name.value);//ref定义的变量,取值需要变量.value
    }
    let ageClick = ()=>{
        console.log(data.age);//reactive定义的对象,正常取值即可
    }
    return{
        name,
        ...toRefs(data),
        nameClick,//导出方法,调用方法与vue2相同
        ageClick
    }
  },
});
</script>

父子组件传值

{immediate:true,deep:true}

immediate默认会执行一次watch,deep:深度监视

//父组件
<template>
  <div>
    <div>这是父组件</div>
    <child :msg="msg" @send="send"></child>
  </div>
</template>

<script>
import { defineComponent, ref } from "vue";
import child from "../children/Child.vue";
export default defineComponent({
  components: {
    child,
  },

  setup(props, ctx) {
    let msg = ref("parent");
    let send = (val)=>{
        console.log(val)
    }
    return {
      msg,
      send
    };
  },
});
</script>

//子组件
<template>
  <div>
    <div>父->子组件的值{{msg}}</div>
    <button @click="send">子->父组件的值</button>
  </div>
</template>

<script>
import { defineComponent ,ref} from "vue";
export default defineComponent({
    props:{
        msg:{
            type:String,
            default:'默认值'
        }
    },
    setup(props,ctx){
        console.log(props.msg)
        let childMsg = ref('子组件的数据')
        let send=()=>{
            ctx.emit('send',childMsg.value) //通过ctx.emit分发事件
        }
        return {
            childMsg,
            send
        }
    }
})
</script>
//stroe.js
import { createStore } from 'vuex'
export default createStore({
  state: {
    list:[
      { title: "吃饭", complete: true },
      { title: "睡觉", complete: false },
      { title: "敲代码", complete: false },
    ]
  },
  getters: {
  },
  mutations: {//同修改
    addTodo(state,data){
      state.list.push(data)
    },
    delList(state,data){
      state.list.splice(data,1)
    },
    clear(state,data){
      state.list = data
    }
  },
  actions: {//异步修改
  },
  modules: {
  }
})

//home.vue
<template>
  <div class="container">
    <div>
      <nav-header></nav-header>
      <nav-main></nav-main>
      <nav-footer></nav-footer>
      <button @click="toPage">跳转</button>
    </div>
  </div>
</template>
<script>
import { useStore } from "vuex";//引入vueStore
import { defineComponent, computed ,ref} from "vue";
export default defineComponent({
  name: "Home",
  setup(props, ctx) {
    let ref = ref('Jack')
    let store = useStore();
    let router = useRouter();
    //获取state时使用计算属性
    let list = computed(() => {
      return store.state.list;
    },{immediate:true},deep:true);
    let toPage = () => {
    //使用query,可以用path/name来表示router的地址
      router.push({
        path: "/setupDemo",
        query:{
          name:name.value,
          obj:JSON.stringify(obj)
        }
      });
      //使用params只能使用name表示route地址
      router.push = ()=>({
        name:'setupDemo',//params跳转需要用name
        params:{name:name.value,age:19,gender:'女'}
      })
    };
    return {
      store,
      list,
      toPage,
    };
  },
 </script>

监听器

immediate默认会执行一次watch,deep:深度监视(使用watchEffct则无需添加改属性)

watch(()=>{ {immediate:true,deep:true} })

监听多个变量且变量不为响应式的值时使用[()=>变量1,()=>变量2,()=>{函数体}]

watch([() => num1, () => num2], () => { console.log("====="); });

生命周期

export default defineComponent({
  name: "AA",
  setup() {
    console.log("setup");
    onBeforeMount(() => {
      console.log("onBeforeMount");
    });
    onMounted(() => {
      console.log("onMounted");
    });
    onBeforeUpdate(() => {
      console.log("onMounted");
    });
    onUpdated(() => {
      console.log("onUpdated");
    });
    onBeforeUnmount(() => {
      console.log("onBeforeUnmount");
    });
    onUnmounted(() => {
      console.log("onBeforeUnmount");
    });
  },
});

Hook函数

//hook函数
import { ref, onMounted, onBeforeUnmount } from "vue";
export default function () {
  const x = ref(-1);
  const y = ref(-1);
  const clickHandler = (event: MouseEvent) => {
    x.value = event.pageX;
    y.value = event.pageY;
  };
  onMounted(() => {
    window.addEventListener("click", clickHandler);
  });
  onBeforeUnmount(() => {
    window.removeEventListener("click", clickHandler);
  });
  return {
    x,
    y,
  };
}

//getPageXY.vue
<template>
  <h2>自定义Hook函数</h2>
  <h2>x:{{ x }},y:{{ y }}</h2>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import clickHandler from "@/hooks/useEventPage";

export default defineComponent({
  name: "getPageXY",
  setup() {
    const { x, y } = clickHandler();
    return {
      x,
      y,
    };
  },
});

shallowReactive和shallowRef

shallowReactive:只处理对最外层属性的响应式(浅响应式);结构较深且内层对象不会变化时使用

shallowRef:只处理value的响应式,不处理reactive的对象;产生的新对象替换当前对象

readonly和shallowReadonly

readonly:对象深度只读

shallowReadonly:对象浅只读,二层及更深层的数据都是可更改的

toRaw和markRaw

toRaw:把代理对象变为普通对象,数据已经变化,但是界面无响应

markRaw:被markRaw标记的对象数据从此之后都不能再成为代理对象

provide和inject

跨层级组件的数据传递

//父组件 provide('唯一标识',传递的变量) //子组件/孙子组件 inject('对应父组件的唯一标识')

响应式数据的判断

isRef、isReactive、isReadonly、isProxy

Suspense(不确定的)

等待异步组件渲染时的额外内容,提高用户体验

//parent.vue
<template>
  <h1>Suspense组件的使用</h1>
  <Suspense>
    <!-- 异步组件 -->
    <template #default>
      <!-- <AsyncComponent></AsyncComponent> -->
      <AsyncAddress></AsyncAddress>
    </template>
    <!-- 等待时显示的内容 -->
    <template v-slot:fallback> <div>loading...</div> </template>
  </Suspense>
</template>

<script lang="ts">
import { defineComponent } from "vue";
// vue2的动态引入方法在vue中无法使用
// const AsyncComponent = () => import("./components/Child.vue");

// vue3动态引入组件写法
// const AsyncComponent = defineAsyncComponent(
//   () => import("./components/Child.vue")
// );
// import AsyncComponent from "./components/Child.vue";
import AsyncAddress from "./components/AsyncAddress.vue";
export default defineComponent({
  name: "APP",
  components: {
    // AsyncComponent,
    AsyncAddress,
  },
  setup() {
    console.log(111);
  },
});
</script>

<style scope lang="scss"></style>



//child.vue
<template>
  <h1>AsyncAddress组件</h1>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import axios from "axios";
export default defineComponent({
  name: "APD",
  setup() {
    return axios.get("/data/address.json").then((res) => {
      return res.data;
    });
  },
});
</script>

<style scope lang="scss"></style>

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红藕香残玉簟秋.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值