vue3+TS的项目记录一

本文介绍了在Vue3项目中使用Pinia进行状态管理,包括defineStore和Pinia的核心概念,以及如何在实际项目中应用。同时,讨论了Vue3的组合式API,如reactive、ref、watch等,并展示了如何使用接口和元组。此外,还涵盖了正则表达式在处理输入事件中的应用,以及动态添加表格行的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、defineStore() & pinia 是什么东西

学习过程一:上网搜索

  1. https://pinia.vuejs.org/zh/core-concepts/
    核心概念:
    定义 Store (setup Store,Option Store)
    State:访问state,重置state- $reset(), 变更state- $patch((state)=>{…}),替换state, 订阅state
    Getter
    Action
    插件
    组件外的 Store
    2.[前端开发]Vue3中Pinia的介绍与使用: https://zhuanlan.zhihu.com/p/519634541
    3.一文搞懂pinia状态管理(保姆级教程): https://zhuanlan.zhihu.com/p/533233367
    4.轻松搞定Vue3+Pinia-4-多个store:https://www.jianshu.com/p/2c8409f28a25
    5.Vue中的Pinia状态管理工具 | 一篇文章教会你全部使用细节: https://blog.csdn.net/m0_71485750/article/details/125982691

学习过程二:看书

《循序渐进vue.js3前端开发实战》张益珲著
(vue3+vueX+vue-route+elementPlue+vue-Axios+vue cli+vite)

第十三章 vue状态管理
涉及知识点:状态管理、vuex框架、state状态、getter方法、mutation、action、module
主要学习:

1.vuex框架的安装与简单使用
2.多组件共享状态的管理方法
3.多组件驱动同一状态的方法

摘录:

1.vuex采用集中的方式管理所有组件的状态

学习过程三:项目应用

扩展知识:1. 元组tuple; 2.只读的数组/元组;

// 文件路径 src> store> modules> useEnumDic.ts
import {defineStore} from pinia

export type dicTuple = readonly [number, string];// 这里涉及到 元组tuple 的概念; readonly 
export type EnumDic = dicTuple[];

export const useEnumDicStore = defineStore(
	EnumDic'
	()=> {
		const getDicValue = (key: number, dicet: EnumDic) => {
			const dic = (dicSet. find (item => item[0] = key))
			if (dic) {
				return dic[1]
			} else {
				return  '末定义的枚举项!'
			}
		}
		const getDickey = (val: string, dicset: EnumDic) => {
			const dic = (dicset.find (item => item[1] - val))
			if (dic) (
				return dic[e]
			} else {
				return '末定义的枚举值!'
			}
		}
		const serviceStatusSet: EnumDic = [[0,"等待中"],[1,"处理中"],[2,"运行中"],[3,'关闭'],[4,'异常']];
		const serviceStatusColorSet: EnumDic = [[0,"#ffbfee"],[1,"#0e77d1"],[2,"#bffbf"]];
		const serviceTypeSet: EnumDic = [[0,"TMS"],[1,"WMS"],[2,"巷道"],[3,"WMTS"],[4,"WFS"]];
		const datasourceTypeset: EnumDic = [[0,"CAD"],[1,"SHP"]];
		return { getDicvalue, getDickey, serviceStatusSet, serviceStatusColorSet, serviceTypeSet, datasourceTypeset}
	}
)

在这里插入图片描述

// .vue文件
<template>
	<a-select ref="select" v-model:value="selectServiceType" :options="serviceTypeSet" @change="handleChange"
		:fieldName="{ label:'1', value:'0'}">
	</a-select>
</template>
import { getDicValue , useEnumDicStore } from "@/store/modules/useEnumDic"

setup(){
	const { serviceTypeSet} = useEnumDicStore();
	const typeName = ref<string[]>([]);
	const selectServiceType = ref(4);
	function aaa(){
		res.forEach(ele=>{
			typeName.value.push( getDicValue(ele.type as number, serviceTypeSet) );
		})
	}
	return {
		serviceTypeSet
	}
}

二、组合式API

1. import { reactive, ref, watch } from ‘vue’

const data = reactive<any[]>([]);
 
watch(
	()=>value,
	(newVal,old)=>{
	console.log(newVal,old)
	}
)

https://vue3js.cn/reactivity/reactive.html
vue3保姆级教程
https://cn.vuejs.org/guide/typescript/composition-api.html#typing-component-emits

2.import { toRaw } from ‘vue-router’

3.import { defineComponent, useRouter, PropType } from ‘vue-router’

setup{
	const router = useRouter();
	router.push({ name:"aaa", query:{ id:id.....}})
}

vue路由管理

三、InstanceType

 <change-pwd-form ref="ChangePwdFormRef"></change-pwd-form>
 import ChangePwdForm from './ChangePwdForm.vue'
 
 setup{
  const ChangePwdFormRef = ref<InstanceType<typeof ChangePwdForm> | null>(null);
  //console.log(ChangePwdFormRef);
  return{ ChangePwdFormRef }
 }

1.Vue3+Ts 项目中 定义 ref 实例 的类型:https://juejin.cn/post/6978035248487464974

四、interface 怎么使用

1. 示例1

interface ValueType<T>{
 value: T
}
setup{
   const tableData= reactive<ValueType<CADData[]>>({ value: []})
}

Vue & TypeScript 初体验 - TypeScript中的Interface:https://juejin.cn/post/6844904017957486599

2.示例2

interface Data {
	[key:string]: Array<T>  //这里会提示找不到名称T
}

props:{
	tabledata:{
		type:Array,
		defult:[]
	},
	tablecolumns:{
		type:Array,
		defult:[]
	},
},
setup(props:Data){
	const { tabledata } = toRefs(props)
}

https://www.codenong.com/56835492/

五、input输入框事件

键盘事件
keydown:当用户按下键盘上的任意按键时触发,如果按住不放,会重复触发此事件。
keyup:当用户释放键盘上的按键时触发。

enter回车键:@keyup.enter.native
@mouseover.native
@mouseout.native

六、正则表达式

需求:页面输入关键词,多个关键词用逗号或空格分隔。点击搜索按钮,接口要求 逗号分隔的字符串
在这里插入图片描述

//vue3
//正则 查找字符串中的,和空格 转换成,
const searchString=ref('')
searchString.value.replace(/[\ |\,]/g,',')

\ 空格
\,逗号
| 竖线
\n 换行
.replace(/\r+|\n+/g,‘,’) // 把 所有的回车和换行 转换成 , (逗号) (+代表所有的,去重)
Vue中的正则表达式

七、动态添加行

在这里插入图片描述
第一种方式:表格实现

  <el-table :data="tableData">
     <el-table-column prop="attrname"
                      label="属性">
       <template slot-scope="scope">
         <el-input v-model="scope.row.attrname"
                   size="mini"
                   placeholder="名称" />
       </template>
     </el-table-column>
     <el-table-column prop="attrtype"
                      label="数值类型">
       <template slot-scope="scope">
         <el-select v-model="scope.row.attrtype"
                    placeholder="请选择">
           <el-option v-for="item in attrtypes"
                      :key="item.value"
                      :label="item.name"
                      :value="item.value">
           </el-option>
         </el-select>
       </template>
     </el-table-column>
    <el-table-column>
      <template slot="header"
                slot-scope="scope">
        <el-button type="primary"
                   @click="addField()">新增</el-button>
      </template>
      <el-table-column prop="operate"
                       label="操作">
        <template slot-scope="scope">
          <el-button @click="deleteAttr(scope.$index, tableData)">删除</el-button>
        </template>
      </el-table-column>
    </el-table-column>
  </el-table>
  
  addField: function () {
    var a = {
      'attrname': '名称',
      'attrtype': 'string'
    };
    this.tableData.push(a);
    return;
  },
  deleteAttr: function (index, rows) {
    rows.splice(index, 1);
  }

第二种方式:自定义

<div style="display:flex; flex-direction:column;">
	<template v-for="(item,idx) in dataSource" :key="idx">
		<div style="display:flex;">
		</div>
	</template>
</div>

八、前端拼接&拆分sql语句

前端开发是创建WEB页面或APP等前端界面呈现给用户的过程,通过HTML、CSS及JavaScript以及衍生出来的各种技术、框架、解决方案,来实现互联网产品的用户界面交互。 前端开发从网页制作演变而来,名称上有很明显的时代特征。在互联网的演化进程中,网页制作是Web1.0时代的产物,早期网站主要内容都是静态,以图片和文字为主,用户使用网站的行为也以浏览为主。随着互联网技术的发展和HTML5、CSS3的应用,现代网页更加美观,交互效果显著,功能更加强大。 前端开发的流程主要包括: 需求分析:明确网页或应用程序的功能、目标用户、界面风格等。 项目规划:制定详细的项目计划,包括制定项目的时间表、任务分配和前端技术选型等。 设计阶段:进行网页或应用程序的设计工作,包括制定整体布局、设计界面的风格、色彩搭配、字体选用等。 前端开发:根据设计稿进行页面切图,将页面的设计转化为代码,然后使用HTML、CSS和JavaScript等技术语言进行页面的搭建和开发,同时关注页面的交互效果、动画效果等。 前端测试:测试页面的兼容性、响应式布局、用户体验等方面。 上线发布:经过测试确认无误后,将网站或应用程序上线发布。 在前端开发中,会涉及到些重要的前端技术栈,如vue.js、react.js、node.js前端安全、react-native等。同时,也需要借助些工具,如代码编辑工具(WebStorm、VS Code)、代码版本控制工具(Git、SVN)、代码包管理工具(npm、Yarn)、前端构建工具(Webpack、Vite)等,来提升开发效率和质量。 总的来说,前端开发是个不断发展与进步的领域,随着新的样式解决方案和组件库的不断涌现,以及前端框架的不断更新和演进,前端开发的技术栈和工具链也在不断完善和丰富。未来,前端社区将继续充满朝气与活力,为互联网产品的用户界面交互带来更多的创新和突破。
<think>好的,我现在需要帮助用户在Vue3TypeScript项目中实现记录用户访问IP的功能。首先,我得回忆下相关的知识,并结合用户提供的引用内容来找到解决方案。根据引用[1],用户提到了通过插入script调用上传接口来统计数据,存储IP和访问时间,并提到后期可以根据IP获取城市信息。这可能涉及到后端接口的调用,前端需要获取用户的IP并发送到后端存储。接下来,我需要确定前端如何获取用户的IP地址。通常,前端无法直接获取用户的真实IP,尤其是在经过代理或NAT的情况下。不过,可以通过第三方服务或者后端来获取。例如,使用诸如ipapi.co这样的服务,或者让后端从请求头中提取IP。但用户的问题可能更关注前端如何配合后端记录IP,所以可能需要前端发送请求到后端,后端再获取IP。然后,引用[1]中的代码示例是个异步的pageUpload方法,接收id和ip,保存到数据库。这说明后端已经有个接口来处理IP的存储,前端需要调用这个接口并传递IP。但前端如何获取IP呢?可能需要前端调用个外部API来获取客户端的IP,或者依赖后端在接收请求时获取IP。不过,通常更常见的做法是后端在处理请求时直接从请求头中获取客户端IP,而不是前端传递。因为前端传递的IP可能不可靠,比如经过代理后可能获取的是内网IP。但用户的需求是前端实现,可能需要前端主动获取IP并发送到后端。 所以可能的步骤是:在Vue3前端,当用户访问特定页面时,调用个获取IP的API(比如https://api.ipify.org?format=json),然后将获取的IP通过调用后端的/page/upload接口(如引用[1]中的pageUpload方法)保存到数据库。 另外,需要考虑何时触发获取IP并发送。可能是在页面加载时,或者路由导航时。引用[2]提到通过监听路由或使用导航守卫来触发数据加载,这可以用来在每次路由变化时记录访问。例如,使用VueRouter的导航守卫,在每次路由进入时触发IP记录。同时,引用[4]展示了通过轮询的方式获取信息,但这里可能不需要轮询,只需要在页面加载或路由变化时执行次。接下来,代码实现部分需要:1.Vue3组件或全局路由守卫中,当路由变化时,获取用户IP。2.调用第三方API获取IP,例如使用axios或fetch。 3.将获取的IP发送到后端接口进行保存。4.处理可能的错误,比如权限问题、网络错误等。需要注意,第三方IPAPI可能需要HTTPS,尤其是在生产环境,否则浏览器可能会阻止请求。引用[3]中提到调用摄像头需要HTTPS,可能类似的情况,所以需要确保使用HTTPS来获取IP。另外,如果后端可以直接从请求中获取客户端IP,可能更可靠,这样前端就不需要主动获取IP,而是由后端在处理请求时记录。但用户的问题明确要求在前端实现,所以可能需要前端主动获取。总结步骤:-使用路由守卫触发IP记录。 -调用外部API获取IP。-发送IP到后端保存。-处理错误和边缘情况。现在需要将这些步骤转化为具体的代码示例,并考虑TypeScript的类型定义。同时,要确保代码符合Vue3TypeScript的最佳实践,比如使用CompositionAPI,正确处理异步操作等。</think>在Vue3TypeScript项目中实现记录用户访问IP的功能,可以通过以下步骤实现: ### 前端获取用户IP #### 1. 创建获取IP的服务 ```typescript // src/services/ipService.ts import axios from &#39;axios&#39;; export const getClientIP = async (): Promise<string> => { try { const response = await axios.get(&#39;https://api.ipify.org?format=json&#39;); return response.data.ip; } catch (error) { console.error(&#39;获取IP失败:&#39;, error); return &#39;unknown&#39;; } }; ``` #### 2. 创建页面访问记录服务 ```typescript // src/services/pageStatisticsService.ts import axios from &#39;axios&#39;; export const recordPageAccess = async (pageId: string, ip: string) => { try { await axios.post(&#39;/api/page/upload&#39;, { id: pageId, ip }); // 对应引用[1]的后端接口 } catch (error) { console.error(&#39;记录访问失败:&#39;, error); } }; ``` ### 二、路由监听实现 #### 1. 配置路由守卫 ```typescript // src/router/index.ts import { createRouter, createWebHistory } from &#39;vue-router&#39;; import { getClientIP } from &#39;@/services/ipService&#39;; import { recordPageAccess } from &#39;@/services/pageStatisticsService&#39;; const router = createRouter({ history: createWebHistory(), routes: [/* 路由配置 */] }); router.afterEach(async (to) => { const ip = await getClientIP(); recordPageAccess(to.path, ip); // 使用路由路径作为pageId }); ``` ### 三、全局组件挂载(可选) ```vue <!-- src/components/PageTracker.vue --> <script setup lang="ts"> import { onMounted } from &#39;vue&#39;; import { getClientIP } from &#39;@/services/ipService&#39;; import { recordPageAccess } from &#39;@/services/pageStatisticsService&#39;; onMounted(async () => { const ip = await getClientIP(); recordPageAccess(window.location.pathname, ip); }); </script> <template> <!-- 空组件仅用于触发逻辑 --> </template> ``` ### 四、注意事项 1. **HTTPS要求**:调用摄像头等敏感接口需要HTTPS协议[^3],IP获取接口同样建议使用HTTPS 2. **隐私合规**:需在隐私政策中声明IP收集行为 3. **代理处理**:实际IP可能被NAT设备修改,可通过`X-Forwarded-For`头获取更准确IP(需后端配合) 4. **错误处理**:添加try-catch块防止程序崩溃 ### 五、扩展方案 ```typescript // 组合式API封装 // src/composables/usePageTracking.ts import { getClientIP } from &#39;@/services/ipService&#39;; import { recordPageAccess } from &#39;@/services/pageStatisticsService&#39;; export default function usePageTracking() { const trackPage = async (pageId: string) => { const ip = await getClientIP(); await recordPageAccess(pageId, ip); }; return { trackPage }; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值