引用传参--面向对象的魅力

引用传参--面向对象的魅力

面向对象开发作为一种主流的软件开发方式,极大地改变了我们开发软件的方式。其遵从人类认识世界的普遍规矩,将现实中纷繁复杂的事物抽象为业务实体类,这就是由具体到抽象的认知过程;其积极响应软件工程的需求,其使我们开发的软件具有灵活性、扩展性、维护性的能力,极大地促进了软件开发的发展。

那么传递参数的时候,面向对象技术能给我们带来什么好处呢? 今天就以昨天碰到的问题作为引子,我们来简单的了解一下面向对象传参的魅力!

在web开发中,我们经常需要从父页面传递参数到子页面中,具体的代码如下,

function showModelDialog(xml) { var url = "child.htm?parameter=123456"; var parameter = "123456"; window.formXml = xml; window.showModalDialog(url, parameter); }

代码中,我们使用showModelDialog来打开一个模式对话框,这个时候我们往往会传递一些参数过去,一般情况我们会有两种方式实现

1. url传递参数

2. 通过showModelDialog的第二个参数传递

那么这两种方式有什么区别呢?

1. 前者传递的数据简单类型单一,只能作为字符串传递;

2. 前者传递的字符串不能包括特殊的字符,同时字符串的长度不能太长;

3. 基于浏览器安全的考虑,包含某些字符串的参数不能传递(比如跨站脚本攻击);

所以很多的时候,我们会更乐意使用第二种方式来传递参数,但是这种方式又有什么特点呢?又怎么能体现面向对象技术传递参数的魅力呢?先别急,还是先来简单的了解一下我遇到的问题吧,我们的产品在父页面中通过复杂的业务逻辑形成了一个xml格式的数据源,然后将这个数据源传递给子页面来展现。我是通过第二种方式实现的。本来一直运行相安无事,但是昨天事业部的客户反馈打开子页面的时候抛出异常;经检查配置的数据没有什么异常,唯一的差别就是配置形成的xml数据源字符串的长度比较大,那么会不会是由于参数传递有长度限制,截断了部分的字符串,导致子页面解析数据源的时候出错?想到这里,我就逐渐字符个数来测试,终于我测出来这个长度限制就是4096个字符,我们可以通过以下我写的例子测试

//测试类 var PassParameterTester = { //新的页面地址 url: "NewPage.htm" , //获取字符个数为4096的参数 getParameter4096: function () { return this.getParameter(4097); } , //获取参数的个数为4097的参数 getParameter4097: function () { return this.getParameter(4098); } , getParameter: function (count) { return new Array(count).join("x"); } , passValueParameter4096: function () { this.passValueParameter(this.getParameter4096()); } , passValueParameter4097: function () { this.passValueParameter(this.getParameter4097()); } , //参数作为值类型进行传递 passValueParameter: function (parameter) { this.showModelDialog(this.url, parameter.toString()); } , showModelDialog: function (url, parameter) { window.showModalDialog(url, parameter); } };

我们调用PassParameterTester.passValueParameter4097(),通过以下图片中显示的长度,我们可以看到字符串被截断了。

图 1. 过长字符串经历传递被截断后的长度

那么现在我们该怎么做了,我们既不能限制客户配置产生的字符串的长度,同时也不能从数据库、或者文件中获取,除了形成数据源需要复杂的业务逻辑,同时子页面也需要反复的保存客户的临时数据。那我是最终怎么实现的呢?我们知道js对象可以在创建后动态的添加成员,所以我将xml字符串赋值给window对象的formXml属性,然后在子页面中通过传递过去的window来获取。

后来静下来仔细想想,难道我们只能使用window对象吗?window是引用类型变量,那是不是任何引用变量都可以呢?我们可以通过以下的例子进行验证

//测试类 var PassParameterTester = { //新的页面地址 url: "NewPage.htm" , //获取字符个数为4096的参数 getParameter4096: function () { return this.getParameter(4097); } , //获取参数的个数为4097的参数 getParameter4097: function () { return this.getParameter(4098); } , getParameter: function (count) { return new Array(count).join("x"); } , passReferenceParameter4096: function () { this.passReferenceParameter(this.getParameter4096()); } , passReferenceParameter4097: function () { this.passReferenceParameter(this.getParameter4097()); } , //以引用类型进行传递 passReferenceParameter: function (parameter) { this.showModelDialog(this.url, { arg: parameter }) } , showModelDialog: function (url, parameter) { window.showModalDialog(url, parameter); } };

图 2. 大于4096的字符串成功传递了

从图中我们看到,参数已经被正确的传递过去了!那么这又是为什么呢?这个大于4096的字符串怎么传递过去的呢?难道这就是地址传参吗,我们知道js里是没有地址传参这回事的,其参数都是传值的,就是java和C#一般的情况下参数也是传值的,但是我们在C#里可以通过in、out、ref来实现地址传参的。

我们都知道传值传参的时候,我们在函数中改变了参数的值,其对应的变量的值并不改变,值类型传参就是将变量保存的内容复制到函数的形参中,他们是两个不同的变量,值不过保存的内容相同不了,具体如图3

图 3. 值类型传参

引用变量保存的是一个地址,这个地址里保存的是变量的具体值,而引用类型作为参数的时候,是将变量保存的地址值赋值到参数变量里,这样他们都指向了同一个内容,这样我们改变参数的成员的话,那么相应的变量的成员也会改变。

图 4. 引用类型传值传参

如果我们在函数中为参数重新赋值,那么对应的变量是不是也改变呢?答案是显然的,传值传参是不可能改变外部变量的。

图 5. 引用类型内部赋值

同样是传值传参,引用类型和值类型传参的本质是一样的,都是将变量保存的东西直接复制给形参,其实这跟赋值操作是一样的。但是由于引用对象的地址是一个数字,所以传参的时候,不过引用类型的值具体是多么大的数据,我们都可以安全的传递。

### Vue Router 中通过 `router-link` 传递对象作为参数 在 Vue Router 中,可以通过多种方式实现将对象作为参数传递给目标组件的功能。以下是几种常见的方法及其对应的代码示例。 #### 方法一:使用 `params` 属性传递对象 可以利用命名路由的方式,将整个对象作为参数传递到目标路由中。需要注意的是,这种方式不会将参数显示在 URL 地址栏中[^2]。 ```html <template> <div> <!-- 使用 params 将对象传递 --> <router-link :to="{ name: 'TargetRoute', params: { userData: userObject }}"> 跳转并传递对象 </router-link> </div> </template> <script> export default { data() { return { userObject: { id: 1, name: "Alice", email: "alice@example.com" } }; } }; </script> ``` 在目标组件中,可以通过 `$route.params.userData` 获取传递的对象: ```javascript // TargetComponent.vue export default { mounted() { console.log(this.$route.params.userData); // 输出传递过来的对象 } } ``` --- #### 方法二:使用 `query` 属性传递对象 如果希望将对象的属性展现在 URL 中,则可以使用 `query` 方式来传递数据。此时需要先将对象序列化为字符串形式再解析回对象[^1]。 ```html <template> <div> <!-- 使用 query 将对象转换成查询字符串 --> <router-link :to="{ path: '/target-route', query: { ...this.userObject } }"> 带 Query 的跳转 </router-link> </div> </template> <script> export default { data() { return { userObject: { id: 1, name: "Bob", email: "bob@example.com" } }; } }; </script> ``` 在目标组件中,可通过 `$route.query` 来获取这些参数,并重新组合为原始对象: ```javascript // TargetComponent.vue export default { computed: { parsedUserData() { const { id, name, email } = this.$route.query; return { id, name, email }; // 解析后的对象 } }, mounted() { console.log(this.parsedUserData); } }; ``` --- #### 方法三:借助 `props` 功能传递复杂对象 当配置路由时启用了 `props` 支持,可以直接向目标组件传递复杂的对象结构[^3]。 首先,在路由定义文件中设置 `props` 函数返回所需的数据: ```javascript const routes = [ { path: "/complex-object-passing", name: "ComplexPassing", component: () => import("@/components/TargetComponent"), props(route) { return { complexData: JSON.parse(decodeURIComponent(route.query.data)) }; } } ]; ``` 接着,在模板中编码该对象并通过 `query` 发送: ```html <template> <div> <router-link :to="{ path: '/complex-object-passing', query: { data: encodeURIComponent(JSON.stringify(userObject)) } }" > 复杂对象传递测试 </router-link> </div> </template> <script> export default { data() { return { userObject: { id: 2, name: "Charlie", details: { age: 30, address: "New York" } } }; } }; </script> ``` 最后,在目标组件内部接收到解码后的对象即可正常使用: ```javascript // TargetComponent.vue export default { props: ["complexData"], mounted() { console.log(this.complexData); // 完整的对象被成功传递到这里 } }; ``` --- ### 总结 以上三种方法分别适用于不同的场景需求: - **Params** 更适合隐藏式的参数传输; - **Query** 则用于公开透明化的地址栏展示; - **Props 结合自定义逻辑处理更灵活的大规模数据交换情况**。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值