vite+typescript从入门到实战(三)

简介: vite+typescript从入门到实战

vite+typescript从入门到实战(二):https://developer.aliyun.com/article/1483572


vite中安装sass 预处理器

npm install --save-dev sass

三、关于sass的“.....Using / for division.....”报错


这是由于sass版本导致的问题,不影响项目编译,解决方法:
1.将 “/”的位置改为 match.dev(arg1,arg2)

@use "sass:math"; /* 头部不要忘记加入这个,不然会报错找不到math */
     
/* 将这个 */
@return ($px/$rem)+rem;
/* 改为下边这个 */
@return match.div($px,$rem)+rem;

2.使用官方sass-migrator工具

    $ npm install -g sass-migrator

环境变量文件


.env

# port 端口号
VITE_PORT = 8888

# open 运行 npm run dev 时自动打开浏览器
VITE_OPEN = false

# public path 配置线上环境路径(打包)、本地通过 http-server 访问时,请置空即可
VITE_PUBLIC_PATH = /vue-next-admin-preview/

.env.development

# 本地环境
ENV = 'development'

# 本地环境接口地址
VITE_API_URL = 'http://localhost:8888/'

.env.production

# 线上环境
ENV = 'production'

# 线上环境接口地址
VITE_API_URL = 'https://lyt-top.gitee.io/vue-next-admin-preview/'

组件传值


父传子


父组件:

<template>
   <div class="son">
     <son1 :toChild="toChild" />
   </div>
</template>
<script>
    import { reactive, toRefs } from 'vue'
    import son1 from './branch/son1.vue'
    export default {
      components: {
        son1
      },
      setup(props,context) {
        const data = reactive({
          toChild: '传递数据1'
        })
     
        return {
          ...toRefs(data)
        }
      }
    }
</script>

子组件

    // 第一种-------------------配置setup-------------------
    <script>
    export default {
      props: {  //这里必须写,不然setup中的props也拿不到
        toChild: {
          type: String,
          default: '无数据'
        }
      },
      setup(props, context) {
        console.log(props.toChild)  //  传递数据1
        return {};
      },
    };
    </script>
     
    // 第二种------------------setup语法糖--------------------
    <script setup>
      const props = defineProps({
        name: {
          type: String,
          default: ''
        }
      })
    </script>
 注意:defineProps只能直接暴露在setup下,不能放在回调中。不需要引入,直接调用即可

子传父


子组件

    // 第一种-----------------配置setup---------------------
    <script>
    import { ref } from "vue";
    export default {
      setup(props, context) {
        const { emit } = context
        const msg = ref('999')
        // 子传父
        const send = () => {
          emit('sonSend',msg)
        }
        return {
          msg,
          send
        };
      },
    };
    </script>
     
    // 第二种-----------------setup语法糖----------------------
    <script setup>
      const emit = defineEmits(['sonSend'])
      const btnClick = () => {
        emit('sonSend', '999')
      }
    </script>

注意:defineEmits只能直接暴露在setup下,不能放在回调中。不需要引入,直接调用即可.同defineProps


父组件

    <template>
      <div class="son">
        <son1 @sonSend="sonSend" />  //监听子组件的自定义事件
      </div>
    </template>
    <script>
    import son1 from './branch/son1.vue'
    export default {
      components: {
        son1
      },
      setup(props,context) {
        const sonSend = (val) => {
          console.log(val.value)  // 999
        }
        return {
          sonSend
        }
      }
    }
    </script>

兄弟之间传值


vue2 我们通过EventBus   new Vue的方式来实现。Vue3 中没有了 EventBus 跨组件通信,但是现在有了一个替代的方案 mitt.js,原理还是 EventBus


1.安装mitt

 npm install mitt --save
  1. 新建 bus.js
//bus.js 
    import mitt from 'mitt'
    const bus = mitt()
    export default bus

然后直接引用就可以了


兄弟组件1

      <template>
        <button @click="btn">我是兄弟组件b</button>
      </template>
     
      import bus from '@/utils/bus'
      function btn() {
        bus.emit("fromBother", '传给好兄弟'); //参数一为自定义事件名称,参数二是传递的参数
      }
      return{
          btn
      }

兄弟组件2

    import bus from '@/utils/bus'
    import { onUnmounted } from "vue"
     
    setup(props,context) {
      function fromBother(val) {
        console.log(val,'val--->>>兄弟传过来')
      }
      onMounted(() => {
        bus.on('fromBother',fromBother)   //监听兄弟组件传过来的值
      })
      onUnmounted(() => {  //销毁的时候 解绑
        bus.off('fromBother',fromBother)
      })
      return {}
    }

封装request.ts

import axios from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Session } from '/@/utils/storage';

// 配置新建一个 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_API_URL as any,
  timeout: 50000,
  headers: { 'Content-Type': 'application/json' },
});

// 添加请求拦截器
service.interceptors.request.use(
  (config) => {
    // 在发送请求之前做些什么 token
    if (Session.get('token')) {
      config.headers.common['Authorization'] = `${Session.get('token')}`;
    }
    return config;
  },
  (error) => {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);

// 添加响应拦截器
service.interceptors.response.use(
  (response) => {
    // 对响应数据做点什么
    const res = response.data;
    if (res.code && res.code !== 0) {
      // `token` 过期或者账号已在别处登录
      if (res.code === 401 || res.code === 4001) {
        Session.clear(); // 清除浏览器全部临时缓存
        window.location.href = '/'; // 去登录页
        ElMessageBox.alert('你已被登出,请重新登录', '提示', {})
          .then(() => {})
          .catch(() => {});
      }
      return Promise.reject(service.interceptors.response);
    } else {
      return response.data;
    }
  },
  (error) => {
    // 对响应错误做点什么
    if (error.message.indexOf('timeout') != -1) {
      ElMessage.error('网络超时');
    } else if (error.message == 'Network Error') {
      ElMessage.error('网络连接错误');
    } else {
      if (error.response.data) ElMessage.error(error.response.statusText);
      else ElMessage.error('接口路径找不到');
    }
    return Promise.reject(error);
  }
);

// 导出 axios 实例
export default service;

使用request.ts

import request from '/@/utils/request';

/**
 * 用户登录
 * @param params 要传的参数值
 * @returns 返回接口数据
 */
export const signIn = (params: object): Object => request({ url: '/user/signIn', method: 'post', data: params })

getCurrentInstance 方法


1、概述:一个很重要的方法,获取当前组件的实例、上下文来操作router和vuex等。
2、使用:由vue提供,按需引入:import { getCurrentInstance} from 'vue';

import { getCurrentInstance } from 'vue';
// 获取当前组件实例
const instance = getCurrentInstance();

// 获取当前组件的上下文,下面两种方式都能获取到组件的上下文。
const { ctx }  = getCurrentInstance();  //  方式一,这种方式只能在开发环境下使用,生产环境下的ctx将访问不到
const { proxy }  = getCurrentInstance();  //  方式二,此方法在开发环境以及生产环境下都能放到组件上下文对象(推荐)
// ctx 中包含了组件中由ref和reactive创建的响应式数据对象,以及以下对象及方法;
proxy.$attrs
proxy.$data
proxy.$el
proxy.$emit
proxy.$forceUpdate
proxy.$nextTick
proxy.$options
proxy.$parent
proxy.$props
proxy.$refs
proxy.$root
proxy.$slots
proxy.$watch

使用 proxy

const { proxy } = getCurrentInstance() as any;

proxy.mittBus.emit('restoreDefault');

proxy.mittBus.on('setSendColumnsChildren', (res: any) => {
  state.menuList = res.children;
});

provide和inject


provide和inject,他们的使用时成组合使用,用于从父级组件向下级的子组件,孙组件传递值。
1、概述:实现嵌套组件树形数据传递与接收。
2、使用:由vue提供,按需引入:

import { provide, inject } from 'vue';
import { provide, inject } from 'vue'
// 父组件注入
const component = {
  setup() {
    provide('name', 'zhagn_san');
    // 如果是需要注入多个值则重复使用provide即可
  };
};
// 子组件接收
const children = {
  setup() {
    // inject的第二个参数为没有接收到注入的数据时的默认返回值,如果没有,则返回undefined
    const user = inject('name', 'li_si');
    // 需要接收多个注入的值也是重复使用inject即可
    return { user };
  };
};

4、实例:再实际使用过程中,往往我们需要将注入的值实现响应式变化,则需要注入响应式

// 父组件注入
const component = {
  setup() {
    const user = reactive({ name: 'zhagn_san', age: 20 });
    provide('user', user);
  };
};
// 子组件接收后,如果父组件中的user发生了改变,则子组件中也会发生响应式变化
const children = {
  setup() {
    const user = inject('user', {});
    return { user };
  };
};

5、注意:不建议在注入时对响应式变量进行改变(在子组件中改变注入的值),因为此操作会改变Vue的单向数据流。建议采用注入改变其值的方法来对响应式变量进行改变。

import { reactive, provide, inject } from 'vue'
// 父组件注入
const component = {
  setup() {
    const user = reactive({ name: 'zhagn_san', age: 20 });
    function changeHandler() {
        user.age = 30;
    }
    provide('user', user);
   provide('changeHandler', changeHandler);
  };
};
// 子组件接收后,通过调用注入的方法来对响应式变量进行改变
const children = {
  setup() {
    const user = inject('user', {});
    const changeHandler = inject('changeHandler');
    return { user, changeHandler };
  };
};

emits方法


1、概述:当前组件的通过emit的事件列表
2、类型:Array|Object
3、作用:Vue3.0中使用emit发起事件时会要求当前组件记录emit事件(没有则控制台会抛出警告)。
3、用途:用于记录当前组件emit的事件,当为对象时,则可以验证传入的值是否有效。

setup(prop, { emit }) {
    const changeOne = val => {
        emit('on-changeOne', val);
    };
    const changeTwo  = val => {
        emit('on-changeTwo', val);
    };
}

数组用法

export default {
    emits:['on-changeOne', 'on-changeTwo'],
    setup() {...}
}

对象用法,当emits为对象时,可以验证事件中的参数是否有效

export default {
    emits:{
        click: null,
        'on-changeOne': payload => {
            if(...) {
                return true; // 验证通过
            }
            console.warn('验证失败!')
            return false; // 验证失败,控制台打印vue警告及“验证失败!”警告
        },
        'on-changeTwo': payload => {...}
    },
    setup() {...}
}
// 当验证函数中没有返回值return时,默认返回true

emits无论是数组或者对象用法最终都会将事件给传递出去,数组或对象的使用只是为了记录实例中的emit事件,或者是验证事件中的参数。


参考文献


vite2 + Vue3 中 组件传值
https://blog.csdn.net/m0_51431448/article/details/122689619


在vue3中使用mitt,达到evenbus的效果
https://www.cnblogs.com/cn-oldboy/p/15791920.html


vite 安装及创建项目
https://www.jianshu.com/p/3178972c6815


(十四)Vue3.x核心之getCurrentInstance
https://www.jianshu.com/p/5558cadd10b9


Vue3.x中的emits选项
https://www.jianshu.com/p/2c9a08e9a8c1

相关文章
|
2月前
|
JavaScript 前端开发
【TypeScript入门】TypeScript入门篇——数据类型
我们人类可以很容易的分清数字与字符的区别,但是计算机并不能呀,计算机虽然很强大,但从某种角度上看又很傻,除非你明确的告诉它,1是数字,“汉”是文字,否则它是分不清1和‘汉’的区别的,因此,在每个编程语言里都会有一个叫数据类型的东东,其实就是对常用的各种数据类型进行了明确的划分,你想让计算机进行数值运算,你就传数字给它,你想让他处理文字,就传字符串类型给他。
17 3
|
3月前
|
JavaScript 前端开发 编译器
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)
TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)
66 0
|
3月前
|
编解码 JavaScript 前端开发
TypeScript【第三方声明文件、自定义声明文件、tsconfig.json文件简介、tsconfig.json 文件结构与配置】(六)-全面详解(学习总结---从入门到深化)
TypeScript【第三方声明文件、自定义声明文件、tsconfig.json文件简介、tsconfig.json 文件结构与配置】(六)-全面详解(学习总结---从入门到深化)
65 0
|
4月前
|
JavaScript
TypeScript【类的继承、访问修饰符、readonly 修饰符、存取器、实例方法与静态方法、实例属性与静态属性、静态属性、抽象类】(三)-全面详解(学习总结---从入门到深化)
TypeScript【类的继承、访问修饰符、readonly 修饰符、存取器、实例方法与静态方法、实例属性与静态属性、静态属性、抽象类】(三)-全面详解(学习总结---从入门到深化)
20 0
|
14天前
|
JavaScript
vite+typescript从入门到实战(二)
vite+typescript从入门到实战
39 0
|
14天前
|
JavaScript 前端开发
vite+typescript从入门到实战(一)
vite+typescript从入门到实战
64 0
|
21天前
|
JavaScript 前端开发
TypeScript极速入门笔记1
TypeScript极速入门笔记1
30 4
|
3月前
|
存储 JavaScript 前端开发
【HarmonyOS 4.0 应用开发实战】TypeScript入门之元组详讲
【HarmonyOS 4.0 应用开发实战】TypeScript入门之元组详讲
43 0
|
3月前
|
JavaScript 前端开发
【HarmonyOS 4.0 应用开发实战】TypeScript入门之模块化详讲
【HarmonyOS 4.0 应用开发实战】TypeScript入门之模块化详讲
33 0
|
3月前
|
JavaScript 前端开发 索引
【HarmonyOS 4.0 应用开发实战】TypeScript入门之接口详讲
【HarmonyOS 4.0 应用开发实战】TypeScript入门之接口详讲
40 0