父传子传缓存
‘壹’ react <link 可以传值吗
处理 React 组件之间的交流方式,主要取决于组件之间的关系,然而这些关系的约定人就是你。
我不会讲太多关于 data-stores、data-adapters 或者 data-helpers 之类的话题。我下面只专注于 React 组件本身的交流方式的讲解。
React 组件之间交流的方式,可以分为以下 3 种:
【父组件】向【子组件】传值;
【子组件】向【父组件】传值;
没有任何嵌套关系的组件之间传值(PS:比如:兄弟组件之间传值)
一、【父组件】向【子组件】传值
初步使用
这个是相当容易的,在使用 React 开发的过程中经常会使用到,主要是利用 props 来进行交流。例子如下:
// 父组件
var MyContainer = React.createClass({
getInitialState: function () {
return {
checked: true
};
},
render: function() {
return (
<ToggleButton text="Toggle me" checked={this.state.checked} />
);
}
});
// 子组件
var ToggleButton = React.createClass({
render: function () {
// 从【父组件】获取的值
var checked = this.props.checked,
text = this.props.text;
return (
<label>{text}: <input type="checkbox" checked={checked} /></label>
);
}
});
进一步讨论
如果组件嵌套层次太深,那么从外到内组件的交流成本就变得很高,通过 props 传递值的优势就不那么明显了。(PS:所以我建议尽可能的减少组件的层次,就像写 HTML 一样,简单清晰的结构更惹人爱)
// 父组件
var MyContainer = React.createClass({
render: function() {
return (
<Intermediate text="where is my son?" />
);
}
});
// 子组件1:中间嵌套的组件
var Intermediate = React.createClass({
render: function () {
return (
<Child text={this.props.text} />
);
}
});
// 子组件2:子组件1的子组件
var Child = React.createClass({
render: function () {
return (
<span>{this.props.text}</span>
);
}
});
二、【子组件】向【父组件】传值
接下来,我们介绍【子组件】控制自己的 state 然后告诉【父组件】的点击状态,然后在【父组件】中展示出来。因此,我们添加一个 change 事件来做交互。
// 父组件
var MyContainer = React.createClass({
getInitialState: function () {
return {
checked: false
};
},
onChildChanged: function (newState) {
this.setState({
checked: newState
});
},
render: function() {
var isChecked = this.state.checked ? 'yes' : 'no';
return (
<div>
<div>Are you checked: {isChecked}</div>
<ToggleButton text="Toggle me"
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
/>
</div>
);
}
});
// 子组件
var ToggleButton = React.createClass({
getInitialState: function () {
return {
checked: this.props.initialChecked
};
},
onTextChange: function () {
var newState = !this.state.checked;
this.setState({
checked: newState
});
// 这里要注意:setState 是一个异步方法,所以需要操作缓存的当前值
this.props.callbackParent(newState);
},
render: function () {
// 从【父组件】获取的值
var text = this.props.text;
// 组件自身的状态数据
var checked = this.state.checked;
return (
<label>{text}: <input type="checkbox" checked={checked} onChange={this.onTextChange} /></label>
);
}
});
我觉得原文作者用代码不是很直观,接下来我话一个流程走向简图来直观描述一下这个过程:
这样做其实是依赖 props 来传递事件的引用,并通过回调的方式来实现的,这样实现不是特别好,但是在没有任何工具的情况下也是一种简单的实现方式
这里会出现一个我们在之前讨论的问题,就是组件有多层嵌套的情况下,你必须要一次传入回调函数给 props 来实现子组件向父组件传值或者操作。
Tiny-Tip: React Event System
在 onChange 事件或者其他 React 事件中,你能够获取以下东西:
【this】:指向你的组件
【一个参数】:这个参数是一个 React 合成事件,SyntheticEvent。
React 对所有事件的管理都是自己实现的,与我们之前使用的 onclick、onchange 事件不一样。从根本上来说,他们都是绑定到 body 上。
document.on('change', 'input[data-reactid=".0.2"]', function () {...});
上面这份代码不是来自于 React,只是打一个比方而已。
如果我没有猜错的话,React 真正处理一个事件的代码如下:
var listenTo = ReactBrowserEventEmitter.listenTo;
...
function putListener(id, registrationName, listener, transaction) {
...
var container = ReactMount.findReactContainerForID(id);
if (container) {
var doc = container.nodeType === ELEMENT_NODE_TYPE ? container.ownerDocument : container;
listenTo(registrationName, doc);
}
...
}
// 在监听事件的内部,我们能发现如下:
target.addEventListener(eventType, callback, false);
这里有所有 React 支持的事件:中文文档-事件系统
多个子组件使用同一个回调的情况
// 父组件
var MyContainer = React.createClass({
getInitialState: function () {
return {
totalChecked: 0
};
},
onChildChanged: function (newState) {
var newToral = this.state.totalChecked + (newState ? 1 : -1);
this.setState({
totalChecked: newToral
});
},
render: function() {
var totalChecked = this.state.totalChecked;
return (
<div>
<div>How many are checked: {totalChecked}</div>
<ToggleButton text="Toggle me"
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
/>
<ToggleButton text="Toggle me too"
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
/>
<ToggleButton text="And me"
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
/>
</div>
);
}
});
// 子组件
var ToggleButton = React.createClass({
getInitialState: function () {
return {
checked: this.props.initialChecked
};
},
onTextChange: function () {
var newState = !this.state.checked;
this.setState({
checked: newState
});
// 这里要注意:setState 是一个异步方法,所以需要操作缓存的当前值
this.props.callbackParent(newState);
},
render: function () {
// 从【父组件】获取的值
var text = this.props.text;
// 组件自身的状态数据
var checked = this.state.checked;
return (
<label>{text}: <input type="checkbox" checked={checked} onChange={this.onTextChange} /></label>
);
}
});
这是非常容易理解的,在父组件中我们增加了一个【totalChecked】来替代之前例子中的【checked】,当子组件改变的时候,使用同一个子组件的回调函数给父组件返回值。
三、没有任何嵌套关系的组件之间传值
如果组件之间没有任何关系,组件嵌套层次比较深(个人认
为 2 层以上已经算深了),或者你为了一些组件能够订阅、写入一些信号,不想让组件之间插入一个组件,让两个组件处于独立的关系。对于事件系统,这里有
2
个基本操作步骤:订阅(subscribe)/监听(listen)一个事件通知,并发送(send)/触发(trigger)/发布(publish)
/发送(dispatch)一个事件通知那些想要的组件。
下面讲介绍 3 种模式来处理事件,你能点击这里来比较一下它们。
简单总结一下:
(1) Event Emitter/Target/Dispatcher
特点:需要一个指定的订阅源
// to subscribe
otherObject.addEventListener(‘click’, function() { alert(‘click!’); });
// to dispatch
this.dispatchEvent(‘click’);
(2) Publish / Subscribe
特点:触发事件的时候,你不需要指定一个特定的源,因为它是使用一个全局对象来处理事件(其实就是一个全局
广播的方式来处理事件)
// to subscribe
globalBroadcaster.subscribe(‘click’, function() { alert(‘click!’); });
// to dispatch
globalBroadcaster.publish(‘click’);
(3) Signals
特点:与Event
Emitter/Target/Dispatcher相似,但是你不要使用随机的字符串作为事件触发的引用。触发事件的每一个对象都需要一个确切的名字
(就是类似硬编码类的去写事件名字),并且在触发的时候,也必须要指定确切的事件。(看例子吧,很好理解)
// to subscribe
otherObject.clicked.add(function() { alert(‘click’); });
// to dispatch
this.clicked.dispatch();
如果你只想简单的使用一下,并不需要其他操作,可以用简单的方式来实现:
// 简单实现了一下 subscribe 和 dispatch
var EventEmitter = {
_events: {},
dispatch: function (event, data) {
if (!this._events[event]) { // 没有监听事件
return;
}
for (var i = 0; i < this._events[event].length; i++) {
this._events[event][i](data);
}
},
subscribe: function (event, callback) {
// 创建一个新事件数组
if (!this._events[event]) {
this._events[event] = [];
}
this._events[event].push(callback);
}
};
otherObject.subscribe('namechanged', function(data) { alert(data.name); });
this.dispatch('namechanged', { name: 'John' });
如果你想使用 Publish/Subscribe 模型,可以使用:PubSubJS
React 团队使用的是:js-signals 它基于 Signals 模式,用起来相当不错。
Events in React
使用 React 事件的时候,必须关注下面两个方法:
componentDidMount
componentWillUnmount
在处理事件的时候,需要注意:
在 componentDidMount 事件中,如果组件挂载(mounted)完成,再订阅事件;当组件卸载(unmounted)的时候,在 componentWillUnmount 事件中取消事件的订阅。
(如果不是很清楚可以查阅 React 对生命周期介绍的文档,里面也有描述。原文中介绍的是 componentWillMount 个人认为应该是挂载完成后订阅事件,比如Animation这个就必须挂载,并且不能动态的添加,谨慎点更好)
因为组件的渲染和销毁是由 React 来控制的,我们不知道怎么引用他们,所以EventEmitter 模式在处理组件的时候用处不大。
pub/sub 模式可以使用,你不需要知道引用。
下面来一个例子:实现有多个 proct 组件,点击他们的时候,展示 proct 的名字。
(我在例子中引入了之前推荐的 PubSubJS 库,如果你觉得引入代价太大,也可以手写一个简版,还是比较容易的,很好用哈,大家也可以体验,但是我还是不推荐全局广播的方式)
// 定义一个容器
var ProctList = React.createClass({
render: function () {
return (
<div>
<ProctSelection />
<Proct name="proct 1" />
<Proct name="proct 2" />
<Proct name="proct 3" />
</div>
);
}
});
// 用于展示点击的产品信息容器
var ProctSelection = React.createClass({
getInitialState: function() {
return {
selection: 'none'
};
},
componentDidMount: function () {
this.pubsub_token = PubSub.subscribe('procts', function (topic, proct) {
this.setState({
selection: proct
});
}.bind(this));
},
componentWillUnmount: function () {
PubSub.unsubscribe(this.pubsub_token);
},
render: function () {
return (
<p>You have selected the proct : {this.state.selection}</p>
);
}
});
var Proct = React.createClass({
onclick: function () {
PubSub.publish('procts', this.props.name);
},
render: function() {
return <div onClick={this.onclick}>{this.props.name}</div>;
}
});
ES6: yield and js-csp
ES6 中有一种传递信息的方式,使用生成函数(generators)和 yield 关键字。可以看一下https://github.com/ubolonton/js-csp
(这里我写一个简单的 DEMO 介绍一下这种新的传递方式,其实大同小异)
function* list() {
for(var i = 0; i < arguments.length; i++) {
yield arguments[i];
}
return "done.";
}
var o = list(1, 2, 3);
var cur = o.next;
while(!cur.done) {
cur = o.next();
console.log(cur);
}
以上例子来自于屈屈的一篇博客:ES6 中的生成器函数介绍 屈屈是一个大牛,大家可以经常关注他的博客。
通常来说,你有一个队列,对象在里面都能找到一个引用,在定义的时候锁住,当发生的时候,立即打开锁执行。js-csp 是一种解决办法,也许以后还会有其他解决办法。
‘贰’ react路由中如何向组件传参数
处理 React 组件之间的交流方式,主要取决于组件之间的关系,然而这些关系的约定人就是你。
我不会讲太多关于 data-stores、data-adapters 或者 data-helpers 之类的话题。我下面只专注于 React 组件本身的交流方式的讲解。
React 组件之间交流的方式,可以分为以下 3 种:
【父组件】向【子组件】传值;
【子组件】向【父组件】传值;
没有任何嵌套关系的组件之间传值(PS:比如:兄弟组件之间传值)
一、【父组件】向【子组件】传值
初步使用
这个是相当容易的,在使用 React 开发的过程中经常会使用到,主要是利用 props 来进行交流。例子如下:
// 父组件
var MyContainer = React.createClass({
getInitialState: function () {
return {
checked: true
};
},
render: function() {
return (
<ToggleButton text="Toggle me" checked={this.state.checked} />
);
}
});
// 子组件
var ToggleButton = React.createClass({
render: function () {
// 从【父组件】获取的值
var checked = this.props.checked,
text = this.props.text;
return (
<label>{text}: <input type="checkbox" checked={checked} /></label>
);
}
});
进一步讨论
如果组件嵌套层次太深,那么从外到内组件的交流成本就变得很高,通过 props 传递值的优势就不那么明显了。(PS:所以我建议尽可能的减少组件的层次,就像写 HTML 一样,简单清晰的结构更惹人爱)
// 父组件
var MyContainer = React.createClass({
render: function() {
return (
<Intermediate text="where is my son?" />
);
}
});
// 子组件1:中间嵌套的组件
var Intermediate = React.createClass({
render: function () {
return (
<Child text={this.props.text} />
);
}
});
// 子组件2:子组件1的子组件
var Child = React.createClass({
render: function () {
return (
<span>{this.props.text}</span>
);
}
});
二、【子组件】向【父组件】传值
接下来,我们介绍【子组件】控制自己的 state 然后告诉【父组件】的点击状态,然后在【父组件】中展示出来。因此,我们添加一个 change 事件来做交互。
// 父组件
var MyContainer = React.createClass({
getInitialState: function () {
return {
checked: false
};
},
onChildChanged: function (newState) {
this.setState({
checked: newState
});
},
render: function() {
var isChecked = this.state.checked ? 'yes' : 'no';
return (
<div>
<div>Are you checked: {isChecked}</div>
<ToggleButton text="Toggle me"
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
/>
</div>
);
}
});
// 子组件
var ToggleButton = React.createClass({
getInitialState: function () {
return {
checked: this.props.initialChecked
};
},
onTextChange: function () {
var newState = !this.state.checked;
this.setState({
checked: newState
});
// 这里要注意:setState 是一个异步方法,所以需要操作缓存的当前值
this.props.callbackParent(newState);
},
render: function () {
// 从【父组件】获取的值
var text = this.props.text;
// 组件自身的状态数据
var checked = this.state.checked;
return (
<label>{text}: <input type="checkbox" checked={checked} onChange={this.onTextChange} /></label>
);
}
});
我觉得原文作者用代码不是很直观,接下来我话一个流程走向简图来直观描述一下这个过程:
这样做其实是依赖 props 来传递事件的引用,并通过回调的方式来实现的,这样实现不是特别好,但是在没有任何工具的情况下也是一种简单的实现方式
这里会出现一个我们在之前讨论的问题,就是组件有多层嵌套的情况下,你必须要一次传入回调函数给 props 来实现子组件向父组件传值或者操作。
Tiny-Tip: React Event System
在 onChange 事件或者其他 React 事件中,你能够获取以下东西:
【this】:指向你的组件
【一个参数】:这个参数是一个 React 合成事件,SyntheticEvent。
React 对所有事件的管理都是自己实现的,与我们之前使用的 onclick、onchange 事件不一样。从根本上来说,他们都是绑定到 body 上。
document.on('change', 'input[data-reactid=".0.2"]', function () {...});
上面这份代码不是来自于 React,只是打一个比方而已。
如果我没有猜错的话,React 真正处理一个事件的代码如下:
var listenTo = ReactBrowserEventEmitter.listenTo;
...
function putListener(id, registrationName, listener, transaction) {
...
var container = ReactMount.findReactContainerForID(id);
if (container) {
var doc = container.nodeType === ELEMENT_NODE_TYPE ? container.ownerDocument : container;
listenTo(registrationName, doc);
}
...
}
// 在监听事件的内部,我们能发现如下:
target.addEventListener(eventType, callback, false);
这里有所有 React 支持的事件:中文文档-事件系统
多个子组件使用同一个回调的情况
// 父组件
var MyContainer = React.createClass({
getInitialState: function () {
return {
totalChecked: 0
};
},
onChildChanged: function (newState) {
var newToral = this.state.totalChecked + (newState ? 1 : -1);
this.setState({
totalChecked: newToral
});
},
‘叁’ js中location.reload可以跨页面传值么
location.reload 方法是重新加载页面,这个相当于你按键盘的 F5 键,是不能带参数的。
按你说的意思,功能本身是可以实现的,但不是使用 location.reload ,而且是有前提条件的。
浏览器为了安全起见,是不能操作地址不同源的 iframe 标签里的内容的,只能对同源地址的iframe进行操作,什么是同源,如果你不了解,请先搜索一下”同源策略“,简单来说就是 iframe 标签所引入的页面,必须跟你的 主页面是同一个网站中的页面。
如果你上面的效果满足上述前提,也就是 iframe 中引入的页面跟主页面都是你自己写的,而且是同一个网站,那么实现的大概思路是这样的:
1, 点击主页面的查询,将数据显示在 iframe 页面里。
就是在主页面中发起查询请求,然后在iframe 页面中显示查询结果。这里需要js配合,有两种实现方式,一是通过地址栏传递参数,另一种是直接用 js 硬写入 iframe 页面中。 如果是通过地址栏传递参数,在点击主页面的查询之后,在js中使用 iframe.src = '.....html?key1=vaue1&key2=value2' 的方式传递给 iframe 页面,然后 iframe 页面中也需要用 js 来处理传递过来的参数,采用 location.search 来获取传递过来的所有参数,然后进行分割处理;如果是直接硬写入 iframe 页面中,则需要获取到 iframe 页面中相应的标签,获取当前页面中的某个元素,是用 document.get... 之类的方法,这里的 document 就是指当前页面的文档对象,那么获取 iframe ,当然得通过 iframe 页面的文档对象,获取iframe页面文档对象的方法是 iframe.contentWindow.document (iframe指的是 iframe标签,需要先用js获取到这个标签),获取到指定标签之后,就跟操作当前页面一样写数据了。
2,从iframe 子页面中返回数据到主页面中显示,这个跟上面第一步是一样的,也有两种实现思路,也是地址栏传递参数或者硬写,但因为地址栏传参会刷新页面,用户体验不好,所以还是采用硬写入的方式。 主页面写数据到iframe标签,需要先获取标签,反过来也是一样的,iframe页面中写数据到主页面,同样需要先获取到主页面中的标签,获取原理相通,先要找到主页面的文档对象,这里需要清楚整体的页面结构,主页面与 iframe 页面是直接的父子级关系,还是多层嵌套关系?如果是直接的父子关系,那就是 window.parent.contentWindow.document, 如果主页面是最顶层,那就是 window.top.contentWindow.document 。
‘肆’ 请教Ext高手我现在子窗口中如何得到父窗口中的值,没有分了请大家帮帮忙
parent.jsp
<% @ page language = " java " import = " java.util.* " pageEncoding = " GB2312 " %>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + " :// " + request.getServerName() + " : " + request.getServerPort() + path + " / " ;
%>
<! DOCTYPE HTML PUBLIC " -//W3C//DTD HTML 4.01 Transitional//EN " >
< html >
< head >
< base href = " <%=basePath%> " >
< title > Parent </ title >
< meta http - equiv = " pragma " content = " no-cache " >
< meta http - equiv = " cache-control " content = " no-cache " >
< meta http - equiv = " expires " content = " 0 " >
< meta http - equiv = " keywords " content = " keyword1,keyword2,keyword3 " >
< meta http - equiv = " description " content = " This is my page " >
< script type = " text/javascript " >
function openChild() {
// 把新打开的窗口放到最顶层,没有子窗口
// window.open("child.jsp", target="_top");
// 新打开一个窗口,用window.opener.document.all得到
window.open( " child.jsp " , target = " _blank " );
}
function scriptSubmit() {
// var formParent = document.formParent;
// 提交的action,可以直接写form名称,因为它是一个文档模型节点的子节点,直接可以获得。
formParent.action = " child.jsp " ;
// 强制弹出一个新页面
formParent.target = " _blank " ;
// 提交
formParent.submit();
}
// 回车提交表单
function enterSubmit() {
if (event.keyCode == 13 ) {
event.returnValue = false ;
event.cancel = true ;
formParent.login.click();
}
}
// 向table中添加tr
function add_tr() {
// alert("abc");
// all后面带id,否则报错
var my_tab = document.all( " addtrTable " );
var tab_rows = my_tab.rows.length; // 现有行数
var tab_cells = my_tab.cells.length; // 现有列数
// alert(tab_rows + " " + tab_cells);
var new_row = my_tab.insertRow(tab_rows - 1 ); // 在最后一个tr前插入一个tr
// 可以不定义,但是如果cell = "abc",则必须定义,不然报没有定义异常
cell = new_row.insertCell();
cell.innerHTML = ' <input type="button" name="delbtn" value="删除" onclick="hidden_tr()"> ' ;
cell = new_row.insertCell();
cell.innerHTML = ' <input type="text" name="username" value=""> ' ;
cell = new_row.insertCell();
cell.innerHTML = ' <input type="radio" name="sex" value="1" checked="checked">男<input type="radio" name="sex" value="0">女 ' ;
}
// 隐藏table中的tr
function hidden_tr() {
// alert(event.srcElement);
// alert(event.srcElement.parentElement.parentElement);
// 得到表格的所有节点
var my_tab = document.all( " addtrTable " );
// 得到事件的父元素的父元素
var tr = event.srcElement.parentElement.parentElement;
// 得到表格所有节点的长度
var len = my_tab.rows.length;
// 只有一个tr的时候不隐藏
// alert(len);
// var field2 = my_tab.rows[tr.rowIndex].cells[3].firstChild;
// 删除行
// my_tab.deleteRow(tr.rowIndex);
// 必须初始化
var iCount = 0 ;
// 循环时去掉第一个为table,最后一个为插入一行
for (var i = 1 ; i < len - 1 ; i ++ ) {
// alert(my_tab.rows[i].style.display);
if (my_tab.rows[i].style.display != " none " ) {
iCount ++ ;
}
}
// alert(iCount);
if (iCount == 1 ) {
alert( " 必须保留一行 " );
return ;
}
/**/ /* if(tr.rowIndex == 1) {
alert("授权号为必填项");
return;
} */
// 得到行索引
// alert("行索引" + tr.rowIndex);
// 把当前行的第4个单元格置空
// field2.value = "";
// 把tr设置为不可见
tr.style.display = " none " ;
}
</ script >
</ head >
< body >
<%--< %
// 清空缓存,也有的叫页面过期,有人误会以为清空缓存后,然后点击后退就会跳到一个页面,
// 上面有一个页面已过期,要刷新才能看到新页面,其实这里意思并不是这样,只是当您后退时
// 清空了文本框的值而已,密码是默认清空的,避免重复提交。
/**/ /* response.setHeader("pragma", "no-cache");
response.setHeader("cache-control", "no-cache");
response.setHeader("expires", "0"); */
%>--%>
< form name = " formParent " method = " post " >
< table style = " background-color: #D4E1EE;border-bottom-color: #cccccc " cellpadding = " 1 " cellspacing = " 0 " border = " 0 " >
< tr >
< td >
用户名
</ td >
< td >
< input name = " formname " type = " text " >
</ td >
</ tr >
< tr >
< td >
密码
</ td >
< td >
< input name = " password " type = " password " onkeydown = " enterSubmit() " >
</ td >
</ tr >
< tr >
< td >
<%-- window.open方法不能在submit触发,否则子窗口得不到父窗口的值 --%>
< input type = " submit " name = " login " value = " 登录 " >
</ td >
< td >
<%-- 按钮不能执行JavaScript提交 --%>
< input type = " button " name = " btn " value = " 跳转 " onclick = " openChild() " >
</ td >
</ tr >
</ table >
<%-- 强制在新窗口中打开超链接 --%>
< a href = " child.jsp " target = " _blank " > Child </ a >
</ form >
< form name = " addtrForm " method = " post " >
< table id = " addtrTable " name = " addtrTable " style = " background-color: #D4E1EE;border-bottom-color: #cccccc " cellpadding = " 1 " cellspacing = " 0 " border = " 0 " >
< tr align = " center " >
< td >
操作
</ td >
< td >
姓名
</ td >
< td >
性别
</ td >
</ tr >
< tr align = " center " >
< td >
< input type = " button " name = " delbtn " value = " 删除 " onclick = " hidden_tr() " >
</ td >
< td >
< input type = " text " name = " username " value = "" >
</ td >
< td >
< input type = " radio " name = " sex " value = " 1 " checked = " checked " > 男 & nbsp; < input type = " radio " name = " sex " value = " 0 " > 女
</ td >
</ tr >
< tr >
< td colspan = " 2 " >
< input type = " button " name = " addbtn " value = " 插入一行 " onclick = " add_tr() " >
</ td >
</ tr >
</ table >
</ form >
</ body >
</ html >
child.jsp
<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>Child</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript">
function getParentValue() {
// target="_blank"
var formname = window.opener.document.all.formParent.formname;
var password = window.opener.document.all.password;
alert("用户名:" + formname.value + "\n密码:" + password.value)
// 刷新父窗口
//window.opener.location.reload();
}
</script>
</head>
<body onload="getParentValue()">
<%
String username = request.getParameter("username");
String password = request.getParameter("password");
out.println("用户名:" + username + "<br>密码:" + password);
%>
</body>
</html>