当前位置:首页 > 程序开发 > Web > VUE3快速入门(5)——响应式数据

VUE3快速入门(5)——响应式数据

bnbplayer1年前 (2024-04-15)Web3144

扫描二维码推送至手机访问。

版权声明:本文由行者无疆发布,如需转载请注明出处。

本文链接:http://xinz.run/post/9.html

标签: VUE
分享给朋友:

“VUE3快速入门(5)——响应式数据” 的相关文章

VUE3快速入门(1)——搭建开发环境

VUE3快速入门(1)——搭建开发环境

教程其实是由站长自己的学习笔记整理而来。本系列教程用于VUE3的快速入门,仅讲解最基础的知识,旨在帮助大家搭建VUE技术的大致框架,从而在做实际项目的过程中快速定位问题,找到解决方向。教程直接从vite等工具的使用开始,以VUE最强大的组件为切入点,逐渐添加数据绑定、DOM事件处理、路由等内容,不断完善功能,让读者尽快上手小项目,缩短学习周期。 每篇教程后面留有拓展学习与思考小节,读者可通过该小节提出的问题或要求进行拓展学习,由点及面,丰富学习内容,并培养技术迁移和举一反三的能力。 特别地,本系列教程适合做过前端开发但技术较陈旧(jQuery、HTML4、前后端无分离)的读者学习,不会讲解HTML标签、CSS、JS/ES6语法等内容,因此不适合对前端开发一无所知的小白。学习本系列教程需要具备如下知识或能力: JavaScriptHTML及CSSES6语法(TypeScript)cmd命令系统环境变量配置面向对象的概念(方法、属性、字段等)具有控件的概念以及封装、复用的思想 如读者的上述知识有所欠缺,建议先完善web开发的基本知识体系。参考学习网站:菜鸟教程或百度、ChatGPT等。 站长自己学习的资料来源于《尚硅谷Vue3入门到实战,最新版vue3+TypeScript前端开发教程》,因此建议读者配合该视频学习更多技术细节。 1. 安装Node.js下载Node.js: NodeJS下载 到官网下载自己系统对应的版本,下载完成后解压,可以看到里面有一个node.exe的可执行文件。把Node添加到系统环境变量里面,打开cmd命令行,输入npm -v,如果出现版本号,说明已经安装正确。 设置国内镜像: npm config set registry http://registry.npmmirror.com 2. 创建工程安装好 npm 之后,直接可以创建vue3工程。执行命令: npm create vue@latest 其中第一次运行要求安装create-vue@latest,输入“y”回车即可。 3. 设置工程选项根据实际情况填写选项,其中建议使用TypeScript和Vue Router,工程名字不要出现中文和空格。参考配置如下: √ 请输入项目名称: ... vue3-test √ 是否使用 TypeScript 语法? ... 否 / 是 √ 是否启用 JSX 支持? ... 否 / 是 √ 是否引入 Vue Router 进行单页面应用开发? ... 否 / 是 √ 是否引入 Pinia 用于状态管理? ... 否 / 是 √ 是否引入 Vitest 用于单元测试? ... 否 / 是 √ 是否要引入一款端到端(End to End)测试工具? » 不需要 √ 是否引入 ESLint 用于代码质量检测? ... 否 / 是 4. 执行在cmd中用cd命令打开刚才的工程目录,再分别执行命令: npm install npm run dev 会看到npm将下载一些列的依赖包。执行第二条指令后,会出现如下类似的提示: VITE v5.1.4 ready in 708 ms [ Local: http://127.0.0.1:5173/ [ Network: use --host to expose [ press h + enter to show help 将地址复制到浏览器,会看到“You did it!”的页面。 5. 在VSCODE中开发下载并安装VSCode后,依次选择“文件”、“打开文件夹”,选择VUE工程目录即可。可根据IDE右下角的提示安装相关的拓展。 6. 拓展学习与思考6.1 npm常见命令速查6.1.1. npm本地安装与全局安装npm install <模块名> # 本地安装,则是将模块下载到当前命令行所在目录% npm install -g <模块名> # 全局安装,模块将被下载安装到【全局目录】中 6.1.2. 配置全局目录及缓存目录分别使用以下命令设置全局的安装包目录及缓存目录: npm config set prefix <目录> npm config set cache <目录> 6.1.3. 其他常见命令npm init # npm 初始化当前目录 npm i # 安装所有依赖 npm i <模块名> # 安装模块到默认dependencies npm i <模块名> -g # 会安装到配置的全局目录下 npm i <模块名> -S # 安装包信息将加入到dependencies生产依赖 npm i <模块名> -D # 安装包信息将加入到devDependencies开发依赖 npm i <模块名>\@1.8.3 # 安装指定的1.8.3版本 注意,i是install的简写。 npm uninstall <模块名> # 卸载模块,但不卸载模块留在package.json中的对应信息 npm uninstall <模块名> -g # 卸载全局模块 npm uninstall <模块名> --save # 卸载模块,同时卸载留在package.json中dependencies下的信息 npm uninstall <模块名> --save-dev # 卸载模块,同时卸载留在package.json中devDependencies下的信息 npm update <模块名> # 更新最新版本的模块 npm update <模块名>@2.1.0 # 更新到指定版本号的模块 npm install <模块名>@latest # 可以直接更新到最后一个新版本 npm root # 查看项目中模块所在的目录 npm root -g # 查看全局安装的模块所在目录 npm list 或者 npm ls # 查看本地已安装模块的清单列表 npm view <模块名> dependencies # 查看某个模块对于各种模块的依赖关系 npm view <模块名> version # 查看模块最新的版本号 npm view <模块名> versions # 查看模块所有历史版本号 npm view <模块名> # 查看最新的模块版本的信息 npm info <模块名> # 查看模块的详细信息,等同于上面的npm view npm list <模块名> 或 npm ls <模块名> # 查看本地已安装的模块的详细信息 npm view <模块名> repository.url # 查看模块的来源地址 6.2 思考 VUE技术栈相对于传...

VUE3快速入门(2)——自定义组件

VUE3快速入门(2)——自定义组件

本文介绍了VUE组件的基本使用,包括定义组件、导出组件、引入组件、使用组件的基本过程,尤其是特别提示了组合式API与选项式API交互的问题。 1. 准备工作 用VSCode打开上节课“VUE3快速入门(1)——搭建开发环境”的文件夹。在VSCode选择“终端”、“新建终端”,准备用命令行执行npm相关指令。打开/src/app.vue文件,删除掉顶部代码 import TheWelcome from ‘./components/TheWelcome.vue’ 同时删除约17行的<TheWelcome />的标签,该步骤是为了删除对TheWelcome组件的引用,稍后将替换成自己编写的组件。 2. 新建一个组件2.1 新建文件在/src/components目录下新建一个文件:MyComp.vue 2.2 添加组件模板代码模板代码用于描述模板架构,由H5标签组成。模板代码写在<template>标签内,Vue2版本要求必须被<div>标签包裹,Vue3则无此要求。 <template> <h1>门禁管理系统</h1> <h2>作者:{{ author }},联系邮箱:{{ mail }},电话:{{ tel }}</h2> </template> 2.2 添加组件控制代码控制代码用于描述控制逻辑,实现相关功能。整体结构是一个被导出的类。在Vue3中,内部数据、方法、计算属性、传入属性等均写在setup方法内,目前先使用内部数据。 <script lang="ts"> export default { //组件名称 name: "MyComp", //组合式API setup() { let author = "Jesse"; let mail = "3898xxxx@qq.com"; let tel = "136****615"; //返回外部需要的数据 return {author, mail, tel}; //上述代码返回的是一个键值对,当key=value时,可省略其中一个。否则需要写成key: value的形式,则外部需要通过key获取值:{{key}} } } </script> 2.3 添加组件样式代码控制代码用于描述组件外观,如字号、字体等,由css代码组成。样式代码写在<style>标签内。 <style scoped> font-size: 16px; </style> style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,通过该属性,可以使得组件之间的样式不互相污染。 3. 调用该组件3.1 引入组件在App.vue中的<script>标签内,增加语句: import MyComp from './components/MyComp.vue'; 3.2 使用组件在App.vue的<template>标签内,像使用H5标签那样,直接在期望展示的位置或者直接在刚才删掉<TheWelcome>处写上 <MyComp></MyComp> 即可。或简写为 <MyComp/> 4. 执行npm能热更新。当编译、构建完成无误后,页面将出现“作者:Jesse,联系邮箱:3898xxxx@qq.com,电话:136****615”的字样 5. 总结 组件分为<template>、<script>、<style>三个部分。<template>定义组件的骨架,<script>定义组件的业务逻辑,<style>定义样式。Vue2下<template>内的所有标签必须被<div>标签包裹,Vue3无此要求。export default用于导出该组件以便复用,其本质上是导出了一个类。如果做过C#、MFC的传统桌面端的开发,可以将组件理解为控件。Vue3下,外部需要的数据(包括内部数据、计算属性、方法等)均写在setup内,且通过return返回。使用组件需要先import引入,最后像使用H5标签一样调用该组件。建议所有组件样式都加上scoped属性,避免污染其他组件样式。 6. 特别提示 setup方法内不允许用this关键字。Vue2的data、methods等可以用this,且可以通过该关键字获取setup里的内容,但setup不能反过来获取data、methods等里面的内容。不要Vue2/3混用,即Vue3不要再用选项式API。 7. 拓展学习与思考 使用组件有什么好处?从创建组件到使用组件的步骤是什么样的?选项式API与组合式API有什么区别?...

VUE3快速入门(4)——Setup语法糖与数据绑定

VUE3快速入门(4)——Setup语法糖与数据绑定

本文讲述了如何使用Setup语法糖简化代码,以及如何获取表单数据。在本系列后续的文章中,均使用setup语法糖写法。 1. Setup语法糖使用Setup导出数据或者方法必须使用return,当代码过多时就变得复杂。使用Setup语法糖无需显式声明要导出的内容,也不必再写setup方法名。 1.1 声明组件导出首先将<script>代码中的setup方法部分全部移除,仅留下组件导出声明: <script lang="ts"> export default { name: "MyComp", } 1.2 创建setup语法糖其次,新增一个<script>片段,如下: <script lang="ts" setup> </script> 注意: lang属性对应的语言必须与上一个<script>的代码语言一致,不得JS、TS混用;setup语法糖所在的<script>必须增加一个setup属性 1.3 在setup语法糖标签内写代码最后将原本setup方法里面的内容除了return外全部放入后一个<script>标签内,完整代码如下: <script lang="ts" setup> let author = "Jesse"; let mail = "3898xxxx@qq.com"; let tel = "136****615"; function add(a: number, b: number): number{ return a + b; } function show(content: any): any { alert(content); } //无需return {author, mail, ...} </script> 这样,凡是在setup语法糖内定义的数据和方法全部自动导出,不用再return。 2. 数据绑定数据绑定是指获取表单中填写的值。 2.1 创建一个表单在合适位置增加一个表单标签: <input name=””/> 2.2 创建变量并绑定表单的值创建一个变量,用于接收表单的值: let input_content = "" 在表单标签内使用v-model指令将表单值与该变量绑定: <input name="" v-model="input_content"/> 2.3 测试修改button的click事件,单击时弹出表单的值: <button @click="show(input_content)">单击</button> 其中show方法代码: function show(content: any): any { alert(content); } 3. 总结 使用setup语法糖就无需再显式声明导出的内容,但要求两个<script>片段语言类型一致;v-model指令用于将表单值与变量绑定;v-model指令仅能用于表单相关的标签。...

VUE3快速入门(7)——监视

VUE3快速入门(7)——监视

本文讲述了监视基础数据类、对象数据类的方法。 1. 什么是监视监视是指,当被监视的对象发生变化时,执行某个逻辑,类似于控件的消息事件。从被监视的数据类型分类,可分为监视ref创建的普通类型、ref创建的对象类型、reactive创建的对象类型三类;从被监视数据的完整与否又可分为监视整个对象和监视部分属性。 2. ref类型的监视2.1 基础类型import { ref, watch } from 'vue'//引入watch let input_content = ref(0);//创建一个基础数据类型 //使用watch方法实现监视 watch(input_content, (newVal, oldVal)=>{ console.log("值:", newVal, oldVal) }); 关于watch方法的参数: 参数1: 需要时监视的变量;参数2: 回调函数,其中有两个传入参数,分别为新值和的值;也可以只有一个参数,即为新值;参数3: 配置对象,用于指定一些其他功能,如立即监视、深度监视等。 2.2 监视整个对象监视由ref定义的对象类型,其实是在监控对象类型的地址,因此部分字段的更新不会触发监视,需要手动开启深度监视。在这种情况下,任何一个字段的变化都会触发监视。 例子:监控员工年龄变化,当到达35岁时让其卷铺盖走人。HTML部分: <button @click="add()">+1</button> JS部分: import { ref, watch } from 'vue'//引入watch let worker = ref({ name: "张三", age: 32 }); function add(): any { worker.value.age += 1; } const stop = watch(worker, (newVal, oldVal)=>{ console.log("值:", newVal, oldVal) if(newVal.age > 35) { alert("卷铺盖走人"); stop();//停止监视 } }, {deep: true});//第三个参数开启深度监视 提示: 上述代码中,watch返回了一个函数,调用该函数时会停止当前的监视;watch的第三个参数开启了深度监视选项,这样仅变化对象成员时,也会触发监视调用;控制台打印的newVal, oldVal值均相同,因为对象的地址没有发生变化。 2.3 监视对象的属性(部分监视)很多时候,我们仅需要关注对象的某几个字段是否发生了变化,即部分监视。对象的部分属性又可能是基础类型,也可能是一个嵌套的对象。因此部分监视又分为基础数据类型和对象数据类型两种。 2.3.1 属性为基础数据类型需要将被监视的数据包装为getter函数 import { ref, watch } from 'vue'//引入watch let worker = ref({ name: "张三", age: 32 }); function add(): any { worker.value.age += 1; } const stop = watch(()=>{ return worker.value.age }, (newVal, oldVal)=>{ console.log("值:", newVal, oldVal) if(newVal > 35) { alert("卷铺盖走人"); stop();//停止监视 } }); 注意箭头函数也可以简写成: ()=> worker.value.age 2.3.2 属性为对象类型即嵌套对象,修改worker代码,增加银行存款账户的嵌套对象类属性: let worker = ref({ name: "张三", age: 32, accounts: { icbc: 2000, bc: 1200 } }); 增加存款和清零的功能: <button @click="icbc()">存入工行</button> <button @click="bc()">存入中行</button> <button @click="clear()">清零存款</button> function icbc() { //改变accounts的一个属性 worker.value.accounts.icbc += 1000; } function bc() { //改变accounts的一个属性 worker.value.accounts.bc += 1000; } function clear() { //改变整个accounts worker.value.accounts = {bc: 0, icbc: 0}; } 仅监视存款清零: watch(() => worker.value.accounts, (newVal, oldVal)=>{ console.log("账户变动:", newVal, oldVal) }); 监视存款清零和增加存款: watch(() => worker.value.accounts, (newVal, oldVal)=>{ console.log("存款清零:", newVal, oldVal) },{deep: true});//开启了深度监视 提示: 与整个对象的监视不同,部分监视即使该部分是对象,也必须写成getter函数形式,在这种情况下监视的是部分对象的地址;监视嵌套对象的内部属性,开启深度监视即可;最佳编码方式是,由ref创建的对象,只要是部分监视,则一律写成getter函数。 3. reactive类型的监视将worker修改为由reactive定义的响应式对象,特别注意整体修改accounts属性的写法: function clear() { Object.assign(worker.accounts, {bc: 0, icbc: 0}); } 监视accounts属性: watch(worker.accounts, (newVal, oldVal)=>{ console.log("账户变动:", newVal, oldVal) }); 当accou...

VUE3快速入门(8)——属性

VUE3快速入门(8)——属性

本文讲述了组件属性的实现方法,以及如何限制属性的数据类型。 1. 什么是组件的属性组件的属性是指可以由组件的调用者动态设置的参数,组件在运行时根据这些参数展现调用者需要的数据。组件的属性等同于HTML标签的属性。 2. 最简单的一个属性本节实现一个展现员工信息的列表,第一步先传入一个“department”属性用于显示员工所属的部门。 2.1 属性的定义定义属性: import { defineProps } from "vue";//引入defineProps,该函数属于宏函数,实际无需引入 let props = defineProps(["department"]);//声明department为一个属性 defineProps方法传入一个字符串数组,其内容是将要被设为属性的变量名称。该方法同时返回一个对象,该对象由传入该组件所有属性的名称和值组成。 模板部分: <template> <p>所属部门: {{ department }}</p> </template> 2.2 使用组件并设置属性<WorkerTable department="宣传科"></WorkerTable> 3. 强制类型限定接下来新增一个属性:data,该属性是描述员工信息的数组,用于表格展示。其中模板部分如下: <template> <h1>所属部门:{{ department }}</h1> <table id="main"> <thead> <tr> <th scope="col">员工号码</th> <th scope="col">姓名</th> <th scope="col">性别</th> <th scope="col">电话</th> </tr> </thead> <tbody> <tr v-for=" (item, index) in data" :key="item.id"> <th scope="col">{{ item.id }}</th> <td scope="col">{{ item.name }}</td> <td scope="col">{{ item.sex ? '男' : '女' }}</td> <td scope="col">{{ item.tel }}</td> </tr> </tbody> </table> </template> 根据模板的展示需求,员工信息需要包括ID、姓名、性别、电话等字段,如果上级组件传入的属性数据不符合员工字段的要求,则组件会出现显示异常。为避免这样的问题,需要检查属性数据的类型,当类型不符合要求时,禁止上级组件的属性赋值。 3.1 定义新类型利用TS的接口类,定义一个员工数据类型,并导出:(建议新建一个名为WorkerTable的文件夹,该文件夹包含一个子文件夹src,用于存放组件的辅助代码,而组件的入口文件则与src同级) //file:@/component/WorkerTable/src/IWorker.ts export interface IWorker{ // 序列号 id: number, // 姓名 name: string, // 性别 sex: boolean, // 电话(可选) tel?: string } export type IWorkerArray = IWorker[]; 该文件定义了一个员工类:IWorker以及它的数组类型:IWorkerArray。 3.2 类型检查修改组件TS代码: import { type IWorkerArray } from "@/components/WorkerTable/src/IWorker"; defineProps<{department: string, data: IWorkerArray}>();//通过泛型进行类型检查并声明属性 上述代码有两个注意点: 引入类型需要使用type关键字通过泛型的方式进行类型检查时,所有属性均需进行类型检查(要么所有,要么都不) 3.3 属性赋值最后调用该组件的TS部分: import WorkerTable from '@/components/WorkerTable/WorkeTable.vue'; import { ref } from "vue"; let workers = ref([ {id: 1234, sex: true, name: "张三", tel: "13600000000"}, {id: 1235, sex: false, name: "李四", tel: "13600000001"}, {id: 1235, sex: false, name: "王五", tel: "13600000002"}, {id: 1234, sex: false, name: "赵六"} ]); 也可以向ref(reactive)传递泛型,在此处限定workers的类型: import { type IWorkerArray } from '@/components/WorkerTable/src/IWorker'; import { ref } from "vue"; let workers = ref<IWorkerArray>(...); 但由于WorkerTable组件已经进行了类型检查,因此上述代码的写法似乎没必要。 模板部分: <WorkerTable department="办公室" :data="workers"></WorkerTable> 注意: 当传入的属性不符合类型要求时,代码将无法运行,避免显示异常。属性的“:”表示后面的内容作为表达式解析,如果不加“:”,则将会把“worker...

VUE3快速入门(9)——插槽

VUE3快速入门(9)——插槽

插槽可以实现组件的样式由调用者决定的功能。本文讲述了默认插槽、具名插槽以及作用域插槽的三种使用方式。 1. 什么是插槽插槽是指组件的部分或全部HTML样式由调用者决定,即动态的Template。例如组件的列表有可能是无序列表、有序列表或图片列表,无法在设计组件时指定,在这种情况下需要使用插槽。 2. 默认插槽默认插槽类似HTML的嵌套标签。本节在上一节的基础上对员工列表组件进行改造(WorkerTableEx),上一节组件的列表标题使用了<h1>标签,但调用者可能希望行换成其他的形式,这里使用默认插槽实现。 组件代码如下: <template> <slot></slot><!-- 使用默认插槽形成占位符 --> <table id="main"> <!-- 表格部分省略 --> </table> </template> 则调用该组件的代码为: <WorkerTableEx><h2>部门:办公室</h2></WorkerTableEx> <WorkerTableEx><p>部门:办公室</p></WorkerTableEx> <WorkerTableEx><img src="..."/></WorkerTableEx> 这样,表格的标题展示形式由调用者决定,它可以是头部标题、段落或者图片以及其他。 通过在<template>中使用<slot></slot>形成占位符,当调用者在组件标签中插入HTML片段或另一个组件时,VUE将会把插入的内容放到占位符中(有几个占位符就放几个)。 3. 具名插槽有时希望多个占位符展示的内容不一样,这种情况需要使用具名插槽。假如要求表格底部可以显示备注信息,这就需要与展示标题的插槽区分开来: <template> <slot name="title"></slot><!-- 使用具名插槽,标题显示部分 --> <table id="main"> <!-- 表格部分代码省略 --> </table> <slot name="description"></slot><!-- 使用具名插槽,备注显示部分 --> </template> 则调用该组件的代码为: <WorkerTableEx> <template v-slot:title><!-- 使用v-slot指令 --> <h3>部门:办公室</h3> </template> <template #description><!-- v-slot语法糖 --> <p>导出时间:2024年6月26日</p> </template> </WorkerTableEx> 提示: 使用v-slot指令可以指明内容放在组件的哪个插槽内,同时v-slot指令可以简写为“#”。v-slot指令只能用在<template>标签和组件标签上,不能用在HTML标签上,因此使用具名插槽必须把普通HTML代码用<template>标签包裹。由于使用了具名插槽,因此组件展示的内容顺序与调用者的编码顺序无关。 4. 作用域插槽有时会有这样的需求:数据由组件生成(如请求服务器得到后端数据),但展示形式却由调用者决定,这种情况需要使用作用域插槽。作用域插槽常见于UI框架。 继续改造WorkerTableEx组件,其中该组件仅提供数据(员工、部门及导出时间)以及头部、正文和注脚三个具名插槽: let ajax_data = ref( { workers: [ {id: 1234, sex: true, name: "张三", tel: "13600000000"}, {id: 1235, sex: false, name: "李四", tel: "13600000001"}, {id: 1235, sex: false, name: "王五", tel: "13600000002"}, {id: 1234, sex: false, name: "赵六"} ], department: "技术部", exp_t: "2024年6月27日20:22:37" });//实际开发从应从服务器获取 组件的模板部分: <template> <slot :title="ajax_data.title" name="header"></slot> <slot :workers="ajax_data.workers" name="content"></slot> <slot :exp_t="ajax_data.exp_t" name="footer"></slot> </template> 上述代码使用了具名作用域插槽,将ajax_data的title、workers和exp_t属性分别绑定到三个不同的具名插槽。 则调用者的代码为: <WorkerTableEx> <template #header="parame"> <h3>部门:{{ parame.title }}</h3> </template> <template #footer="parame"> <p>导出时间:{{ parame.exp_t }}</p> </template> <template #content="parame"> <table id="main"> <thead> <tr> <th scope="col">员工号码</th>...

关于“拓源纯净主题”引发的Undefined array key "pro" 的修复

关于“拓源纯净主题”引发的Undefined array key "pro" 的修复

本博客使用的是由拓源 推出的“纯净主题”。目前发现一个由于IP查询接口触发的问题,导致主题需要显示IP归属地的页面(如留言、评论页等)会出现如下错误: 经检查,该主题的 tpure_IP函数使用了一个“https://whois.pconline.com.cn/ipJson.jsp” 接口查询IP归属地,但该接口不稳定,时常返回空,所以触发了上述问题。修改方式如下: 1 定位到函数在该主题的安装目录下(位置:/zblog的安装目录/zb_users/theme/tpure),打开includes.php 在编辑器中按“Ctrl+F”搜索函数:tpure_IP。找到如下代码: function tpure_IP($ip) { $ch = curl_init(); $url = 'https://whois.pconline.com.cn/ipJson.jsp?ip='.$ip; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false ); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $location = curl_exec($ch); curl_close($ch); $location = mb_convert_encoding($location, 'utf-8','GB2312'); $location = substr($location, strlen('({')+strpos($location, '({'),(strlen($location) - strpos($location, '})'))*(-1)); $location = str_replace('"',"",str_replace(":","=",str_replace(",","&",$location))); parse_str($location,$ip_location); return $ip_location['pro']; } 2 更换查询接口,实现自己的解析方式在function tpure_IP($ip)代码前增加函数ip_parser($ip),完整代码如下: function ip_query($ip) { $url = "https://opendata.baidu.com/api.php?query={$ip}&co=&resource_id=6006&oe=utf8";//此处使用百度API $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false ); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $location = curl_exec($ch); curl_close($ch); $ip_obj = json_decode($location, true); if(0 != count($ip_obj['data']) && array_key_exists('location', $ip_obj['data'][0])) return $ip_obj['data'][0]['location']; else return '未知'; } 注意,该代码一定要放在tpure_IP函数的前面。 3 注释原来的代码,调用新的函数将tpure_IP函数体内的代码全部用/**/注释,并在最后添加ip_query的调用代码,如下: function tpure_IP($ip) { /* $ch = curl_init(); $url = 'https://whois.pconline.com.cn/ipJson.jsp?ip='.$ip; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false ); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $location = curl_exec($ch); curl_close($ch); $location = mb_convert_encoding($location, 'utf-8','GB2312'); $location = substr($location, strlen('({')+strpos($location, '({'),(strlen($location) - strpos($location, '})'))*(-1)); $location = str_replace('"',"",str_replace(":","=",str_replace(",","&",$location))); parse_str($location,$ip_location); return $ip_location['pro']; */ return ip_query($ip); } 相当于不再使用原本的实现,而使用自己的实现,但函数名称不变,保存即可。有动手能力的大佬也可以将API换成其他的,但是解析代码也同样要换。 点击下列链接可以下载本人修改好的文件进行替换。请注意备份好源文件!!!include.php...

VUE3快速入门(10)——路由的基础使用

VUE3快速入门(10)——路由的基础使用

1. 什么是路由路由是指根据不同的URL加载不同的组件,其典型应用是后台页面,点击不同的菜单显示不同的页面。通过使用路由,能实现SPA页面、无刷新加载、部分页面加载的功能,是VUE最为典型的一种功能。 2. 准备工作2.1 搭建导航区与展示区框架本文实现一个功能:导航有三个按钮,分别是“首页”、“新闻”、“关于”。点击三个按钮在展示区显示不同的页面。App.vue代码如下: <template> <!--这是导航区--> <nav> <ol> <li><a href="#">首页</a></li> <li><a>新闻</a></li> <li><a>关于</a></li> </ol> </nav> <!--这是展示区--> <div id="content"></div> </template> 2.2 创建路由视图页在源码目录下新建views目录,用于单独存放路由视图组件,目录内建立Home.vue、News.vue、About.vue,分别对应“首页”、“新闻”、“关于”的具体内容。具体代码略。 2.3 安装路由npm install vue-router 上述代码将会自动安装VUE3的路由组件。 3. 使用路由3.1 定义路由(History模式)在源码目录新建目录router,再创建index.ts文件作为路由定义文件。首先引用路由以及需要使用的路由视图: import { createRouter, createWebHistory } from 'vue-router' //三个准备好的路由视图 import Home from '@/views/Home.vue' import News from '@/views/News.vue' import About from '@/views/About.vue' 其次定义路由,关键是路径与路由视图的对应关系: const router = createRouter({ //路由模式 history: createWebHistory(), //路由映射关系 routes: [ { path: '/home',//路径 component: Home,//加载的组件 }, { path: '/news', component: News, }, { path: '/about', component: About, } ], }) createRouter函数中传入对象的history属性用于指定路由模式为“WebHistory”模式,routes用于指明路径与页面的映射关系,类型为键值对数组。注意:创建路由时,必须指定使用哪一种路由模式。 记得将定义好的路由暴露出去 export default router 3.2 加载路由在main.ts入口文件中,引用定义好的路由,在原始代码基础上新增如下代码: import router from '@/router/index' app.use(router)//注意该代码放在const app = createApp(App)之后 3.3 处理视图首先添加引用:import { RouterLink, RouterView } from ‘vue-router’其次将App.vue的a标签替换为RouterLink组件: <li><RouterLink to="/home">首页</RouterLink></li> <li><RouterLink to="/news">新闻</RouterLink></li> <li><RouterLink to="/about">关于</RouterLink></li> 最后在原本要展示内容的位置写上RouterView标签:<RouterView></RouterView> 最终效果:在页面上点击三个按钮,可以看到浏览器地址的路径在变化,同时页面展示区显示了三个按钮对应的页面。 4. 更换路由模式(Hash模式)在上述示例代码中使用了History模式,现在替换为Hash模式。修改路由定义文件@/router/index.js更改引用: import { createRouter, createWebHashHistory } from 'vue-router' //... 更改创建路由的代码: const router = createRouter({ history: createWebHashHistory(),//此处修改为了createWebHashHistory //... }) 此时浏览器中出现了一个“/#/”部分。 5. RouterLink组件“to”属性的两种写法5.1 字符串写法见前文。 5.2 对象写法5.2.1 对象的路径属性代码如下: <li><RouterLink :to="{path:'/home'}">首页</RouterLink></li> <li><RouterLink :to="{path:'/news'}">新闻</RouterLink></li> <li><RouterLink :to="{path:'/about}">关于</RouterLink></li> 该写法传入了一个包含path属性的对象。 5.2.1 对象的名字属性(命名路由)修改路由定义文件,增加name属性: //@/router/index.ts const router = createRouter({ history: createWebHashHistory(), routes: [ { name: 'home', path: '/home', component: Home, } //... ], }) 将对象写法的path属性改为name即可: <li><Rout...

VUE3快速入门(11)——路由的嵌套与传参

VUE3快速入门(11)——路由的嵌套与传参

1. 嵌套路由1.1 什么是嵌套路由嵌套路由是指一个路由视图中又包含一个路由视图,通常用于多级分类的SPA。比如一个新闻SPA,分为板块与列表二级。单击不同的板块出现不同的文章列表,再点击列表则出现新闻正文。本文基于上一节内容增加新闻列表和新闻详情的展示功能。 1.2 创建显示新闻详情的视图组件在“@/views/”路径下,新增一个Content.vue组件,HTML部分如下: <template> <div id="detail"> <h2>新闻标题</h2> <p>这是新闻的具体内容</p> </div> </template> 1.2 定义新闻数据修改上一节的News.vue代码的ts部分,增加新闻数据: <script lang="ts" name="News" setup> import { ref } from 'vue'; const news_data = ref([ { id: 1, title: '新闻1', content: '新闻内容1' }, { id: 2, title: '新闻2', content: '新闻内容2' }, { id: 3, title: '新闻3', content: '新闻内容3' }, { id: 4, title: '新闻4', content: '新闻内容4' } ]); </script> 1.3 新增子路由定义在路由定义文件的新闻路径下增加一个子路由: import Content from '@/views/Content.vue'//新增引入 const router = createRouter({ history: createWebHashHistory(), routes: [ //... { name: 'news', path: '/news', component: News, //增加children属性,注意为数组 children: [ { name: 'content', path: 'content',//注意:子路由无需再用“/” component: Content, }], }, //... ], }) 1.4 修改新闻列表视图修改News.vue的HTML部分如下: <template> <h1>新闻列表</h1> <div id="warpper"> <!-- 左侧新闻列表 ---> <div id="list"> <ul> <li v-for="item in news_data" :key="item.id"> <p><RouterLink :to='{path: "/news/content"}'>{{ item.title }}</RouterLink></p> </li> </ul> </div> <!-- 右侧新闻内容 --> <div id="content"> <RouterView></RouterView> </div> </div> </template> 注意二级路由的写法。 修改完成后,可以在新闻导航内看到左侧的新闻列表,点击链接在右侧展示的新闻内容。 2. 路由传参上述代码中点击每个新闻链接展示的内容都一样,现在需要根据链接展示不同的新闻,该功能需要用路由传参来实现。 2.1 Query传参路由定义文件见前文。 2.1.1 直接字符串拼接(不推荐)修改New.vue的RouterLink组件调用代码: <p> <RouterLink :to='`/news/content?title=${ item.title }&content=${ item.content }`'>{{ item.title }}</RouterLink> </p> 注意VUE的字符串模板语法:`…${变量名1}…${变量名2}…`。修改Content.vue的代码,取参数:ts部分: import { useRoute } from 'vue-router'//引入useRoute import { toRefs } from 'vue'//响应式 const route = useRoute() const { query } = toRefs(route)//从useRoute中解构query属性,该属性保存了传递的参数。 html部分: <template> <div id="detail"> <!-- 从query属性获取title参数--> <h2>{{ query.title }}</h2> <!-- 从query属性获取content参数--> <p>{{ query.content }}</p> </div> </template> 注意:由于是直接把传递的参数进行动态显示,所以在解构时需要转换为响应式类型。或者不解构,则写法为: <...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。