vue3.0+vite 个人学习

280 阅读1分钟

vue3.2 blog.vuejs.org/posts/vue-3…
重点: vue3为何放弃defineProperty,使用Proxy
还记得vue经常会出现一个问题 那就是数据改变但是视图没有改变 Proxy就是从这个角度去改变的也可以从这里抓起

创建项目

创建项目命令使用 NPM:

$ npm init vite@latest

使用 Yarn:

$ yarn create vite

使用 PNPM:

$ pnpm create vite

vite 最大的有点就是不用return data 或者setData <script setup lang="ts"></script> 这里的setup已经做了处理 同时引入组件无需注册

解决跨域

常规操作解决跨域问题 vite.config.ts

export default defineConfig({
  plugins: [vue()],
  server:{
    proxy:{
      '/api':{
        target:'https://c.m.163.com',
        changeOrigin:true,
        rewrite:(path)=>path.replace(/^\/api/,'')
      }
    }
  }
})

reactive ref toRefs

需要用的vue页面引入
reactive 和 ref 可以理解成vue中的初始化data onMounted 跟vue的mounted一样注意vue3 生命周期发生改变。
toRefs 结构出变量在dom上方便使用不用data.msg而是可以直接使用msg

import { onMounted, reactive, toRef, toRefs } from 'vue'
import axios from 'axios'
// 定义初始数据 reactive
const data = reactive({
  name:'test',
  type:1,
  areaTree: [],
  chinaDayList: [],
  chinaTotal: {},
  lastUpdateTime: "",
  overseaLastUpdateTime: ""
})
//vue3.0 生命周期中请求接口
onMounted(() => {
    axios().then(res=>{
        data.name = res.data.data.name
    })
})
// 主要作用就是省略调了data.type之类的写法 在html里面直接{{type}}
const {chinaTotal,type} = toRefs(data)

点击事件

 <div @click="changeNumber(1)">我点击了1</div>
 <div @click="changeNumber(2)">我点击了2</div>
 
 //点击的写法
 const changeNumber = (type:number)=>{
  data.type = type
}

vite 的改写 注意定义类型和引入方法有兴趣可以参照 没有可以直接无视查看组件通讯

创建type文件index.ts

interface IData{
      name:string,
      type:Number,
      areaTree:any[],
      chinaDayList: any[],
      chinaTotal: object,
      lastUpdateTime: string,
      overseaLastUpdateTime: string
}
export type {
    IData
}

创建pageJS/index.ts

import type {IData} from '../type/index'
import axios from 'axios'

class InitData implements IData {
    name: string = ""
    type: Number = 1
    areaTree: any[] = []
    chinaDayList: any[] = []
    chinaTotal: object = {}
    lastUpdateTime: string =""
    overseaLastUpdateTime: string=""
}
// 逻辑层使用的地方直接getData(data)
const getData = (data:InitData)=>{
    axios('/api/ug/api/wuhan/app/data/list-total?t=330415245809').then(res=>{
        console.log(res,"es");
        data.areaTree=res.data.data.areaTree
        data.chinaDayList=res.data.data.chinaDayList
        data.chinaTotal=res.data.data.chinaTotal
        data.lastUpdateTime=res.data.data.lastUpdateTime
        data.overseaLastUpdateTime=res.data.data.overseaLastUpdateTime
    })
}
export {
    InitData,
    getData
}

原页面

    import  {InitData,getData} from '../pageJS/index'
    // const data = reactive({
    //   name:'test',
    //   type:1,
    //   areaTree: [],
    //   chinaDayList: [],
    //   chinaTotal: {},
    //   lastUpdateTime: "",
    //   overseaLastUpdateTime: ""
    // })
    const data = reactive(new InitData())

    onMounted(() => {
      getData(data)
    })
    

组件的使用 vue3 之后引入组件将不需要注册组件可以直接使用

组件通讯

<template>
  <!-- 子组件 -->
  <child-components :list="list"></child-components>
  <!-- 父组件 -->
  <div class="child-wrap input-group">
    <input
      v-model="value"
      type="text"
      class="form-control"
      placeholder="请输入"
    />
    <div class="input-group-append">
      <button @click="handleAdd" class="btn btn-primary" type="button">
        添加
      </button>
    </div>
  </div>
</template>
<script setup>
import { reactive, toRefs, onMounted, ref } from "vue";
import ChildComponents from "./components/child.vue";
const list = ref(["JavaScript", "HTML", "CSS"]);
const value = ref('')
const data = reactive({
  name: "ces",
  areaTree: [{ id: 0, name: "ces" }],
  num: 1,
});
const handleAdd = () => {
  list.value.push(value.value)
  value.value = ''
}
onMounted(() => {
//  接口使用的地方
});


</script>

defineProps

defineProps 子组件接收父组件传递过来的值

<template>
  <ul class="parent list-group">
    <li class="list-group-item" v-for="i in props.list" :key="i">{{ i }}</li>
  </ul>
</template>
<script setup>
import { defineProps } from 'vue'
const props = defineProps({
    list:{
        type:Array,
        default:()=>[]
    }
})
</script>

defineEmits

defineEmits 子组件传父组件

<li class="list-group-item" v-for="i in props.list" :key="i">{{ i }} <button @click="deleteListRow(i,key)">删除</button></li> 

deleteListRow 获取到下标

import { defineProps,defineEmits } from 'vue'
const emits = defineEmits(['deleteRow'])
   let index = Object.values(props.list).findIndex(item => item == value)
    // 传入下标
   emits('deleteRow',index)
}

子组件使用

<child-components :list="list" @deleteRow="deleteRow">

const deleteRow = value =>{
  console.log('接收子组件传递过来的下标',value);
}

ref + defineExpose

defineExpose 子组件自己暴露给父组件 (无论是对象还是数组或者是对象布尔值等等都可以)

子组件 child.vue

// 子组件
import { ref,defineExpose,reactive } from 'vue'

const aaa = ref('aaa')
defineExpose({
    aaa,
})

父组件使用ref <child-components ref="childRefs"></child-components>
<button @click="exposure">refs子组件暴露给父组件</button>

利用点击事件获取子组件暴露来的值

// 父组件
const childRefs = ref(null)

const exposure = () =>{
  console.log(childRefs.value.aaa);
}

provide/inject

provideinject是Vue中提供的一对API,该API可以实现父组件向子组件传递数据,无论层级有多深,都可以通过这对API实现。

父组件 // provide 不需要经过html

import { reactive, ref,provide } from "vue";

const  provideNum = ref('provide传递过来的参数')

provide('provideNum',provideNum.value)

子组件

import { inject } from 'vue'

const   injects = inject('provideNum')

console.log(injects,"inject"); // provide传递过来的参数 inject

mitt

Vue3 中没有了 EventBus 跨组件通信,但是现在有了一个替代的方案 mitt.js,原理还是 EventBus

先安装 npm i mitt -S

然后像以前封装 bus 一样,封装一下

import mitt from 'mitt'
const mitts = mitt()
export default mitts

child 子组件

<button @click="mittClick">Child-mitt传值

import mitts from '../../utils/mitt'
const mittClick = () =>{
  mitts.emit('handleChange','mitt.emit获取到的值')
}

child2 子组件

import mitts from '../../utils/mitt'
import { onUnmounted,ref} from 'vue'
const mitssName = ref("")
mitts.on('handleChange', (params)=> {
  mitssName.value = params
})
// 组件卸载
onUnmounted(()=>{
    mitt.off('handleChange',null)
})

image.png

image.png

vue

和vue2同理vuex没啥改变

// store/index.js
import { createStore } from "vuex"
export default createStore({
    state:{ count: 1 },
    getters:{
        getCount: state => state.count
    },
    mutations:{
        add(state){
            state.count++
        }
    }
})

// main.js
import { createApp } from "vue"
import App from "./App.vue"
import store from "./store"
createApp(App).use(store).mount("#app")

// Page.vue
// 方法一 直接使用
<template>
    <div>{{ $store.state.count }}</div>
    <button @click="$store.commit('add')">按钮</button>
</template>

// 方法二 获取
<script setup>
    import { useStore, computed } from "vuex"
    const store = useStore()
    console.log(store.state.count) // 1

    const count = computed(()=>store.state.count) // 响应式,会随着vuex数据改变而改变
    console.log(count) // 1 
</script>