前端跨页面通信

同源页面间的跨页面通信

BroadCast Channel

BroadCast Channel可以用来创建一个用于广播的通信频道,所有同源页面都可以共享/监听(广播)频道,当其中某一个页面通过它发送发送的消息会被其他所有页面收到

创建

使用构造函数进行创建

const bc = new BroadcastChannel("demo")

接收一个string作为name标识channel,传入相同name使用同一个频道,可通过实例的.name属性获得

console.log(bc.name)
发送信息

通过调用实例上的postMessage方法发送消息

//可以传递一个对象用于发送消息
bc.postMessage({
    channelName: "bc"
})
bc.addEventListener("postMessage", {})
监听信息
bc.onmessage = function(e) {
    console.log("receive", e.data.channelName)
}
bc.addEventListener("message", e => {
    console.log("receive", e.data.channelName)
})

对于错误也可以绑定监听

bc.onmessageerror = function(e) {
    console.warn("error", e)
}
关闭

​ 1、第一种:取消或修改相应的massge事件监听

​ 2、第二种:使用Broadcast Channel 实例提供的close方法

bc.close();

取消message监听只是让页面不对广播消息进行响应,Broadcast Channel依然存在。

调用close方法会切断与Broadcast Channel的连接,浏览器能尝试回收该对象。

在关闭后调用postMessage会报错

Service Worker

长期运行在后台的一个worker,能够实现页面的双向通信。多页面共享间的Service Worker可以共享,将Server Worker作为消息的处理中心(中央站)即可实现广播效果

LocalStorage-StorageEvent

LocalStorage变化时,会触发storage事件。可利用这个特性,在发送消息时,把消息写入到某个LocalStorage中,然后在各个页面内通过监听storage事件即可收到通知

window.addEventListener('storage', (e) => {
    //console.log(e);
    if(e.key === 'test'){
        const data = e.newValue;
    }
})

在各个页面添加以上代码,即可监听到LocalStorage的变化

注意:storage事件只有在值真正发生变化时才会触发

window.localStorage.setItem("test", 124);
window.localStorage.setItem("test", 124);

第二次不会触发storage事件,因为传入的值与第一次一样都是124

可以通过添加一个当前毫秒的事件戳来触发

madata.st = +(new Data);
window.localStorage.setItem("test", JSON.stringify(mydata))

url传参

js中url传参

window.location属性 等同于 document.location

代码操作输出结果
window.location.href获取整个url字符串
window.location.hash获取#号后面的字符串#/lingshoustatis/?starttime=2018&endtime=2019
window.location.search获取href属性中?后的部分?starttime=2018&endtime=2019
window.location.protocal获取url协议部分http:
window.location.port获取端口号8000
window.location.pathname获取对象指定文件名或路径/bui/
window.location.host获取location或URL的hostname和port号码localhost:8000
  • decodeURIComponent() 函数 是对url 进行解析
  • unescape() 函数可对通过 escape() 编码的字符串进行解码。
  • location的8个属性都是可读写的,但是只有href与hash的写才有意义,href会重新定位到一个URL,hash会跳到当前页面中的anchor(<a id="name">或者<div id="name">)名字的标记处(如果有),而且页面不会被重新加载。
decodeURIComponent(window.location.hash.match(/pageFrom=(\w+)/g)).match(/=(\w+)/)
vue中路由传参

vue2与vue3路由传参写法差别不大

  • route获取到的是浏览器当前访问的路由信息对象,包含了当前路由的路劲、名称、参数、原信息等数据
  • router获取到的是整个系统总的路由实例对象,包含了路由的跳转、导航守卫等方法
//vue2
this.$router
this.$route
//vue3
import { useRouter, useRoute } from 'vue-router';
const router = useRouter();
const route = useRouter();
  1. 动态路由传参

    getDescribe(id){
        this.$router.push({
            path: `/describe/${id}`
        })
    }
    

    对应路由配置

    {
        path: '/describe/:id',
        name: 'Describe',
        component: Describe
    }
    

    获取路由传参

    this.$route.params.id
    
  2. name匹配路由-params传参

    this.$router.push({
         name: 'Describe',
         params: {
          id: id
         }
        })
    

    对应路由配置: 这里可以添加:/id也可以不添加,添加数据会在url后面显示,不添加数据就不会显示

    {
       path: '/describe',
       name: 'Describe',
       component: Describe
      }
    

    获取传参

    this.$route.params.id
    
  3. path匹配路由-query传参

    query传递的参数会显示在url后面?id=?

    this.$router.push({
         path: '/describe',
         query: {
          id: id
         }
    })
    

    对应路由配置:

    {
       path: '/describe',
       name: 'Describe',
       component: Describe
      }
    

    获取参数

    this.$route.query.id
    

注意:后两种方式传参时,参数需要以字段的形式加入到对象大括号 {}

react中路由传参
类组件
  • params传参

    • 刷新页面后参数不会消失
    • 参数会在地址栏中显示
    • 需要在Route中配置参数名称
    • 缺点:传值太多不方便,且url会变很长;只能传递字符串,无法传递对象,解决方法:将json对象 -> 字符串传递,接收后将字符串 -> json对象JSON.stringify() JSON.parse()

    路由配置页面

    <Route path="/Capacity/view/:Id" component={production} />
    
    

    link跳转页面,并传参

    {
        render: (value, record) => {
            const { id } = record || {}; // recoed 就是选中行的信息 ,解构赋值id ,拼接给跳转的路由
            return <Link to={`/Capacity/view/${id}`}>{value}</Link>;
        }
    	//或者<Link to={{pathname: '/Capacity/view/' + '121212'}}>跳转</Link>
    }
    
    this.props.history.push(`/Capacity/view/${id}`)
    

    页面接收参数

    export default class UserPage extends React.Component{
        constructor(props) {
        super(props);
        this.state = {
            id: this.props?.match?.params?.id
        }
    }
    async componentDidMount() {
        this.setState({
            id: this.props?.match?.params?.id
        });
        await this.findDetail(this.state.id)
    }
    render() {
         return(<div>this.props.match.params.id</div>)
        }
    }
    
  • query传参

    • 路由不需要配置
    • 刷新页面参数丢失
    • 参数为明文传递
    • 不推荐

    页面传参

    <Link to={{pathname:'/production',query:{productionId:120,productionType:'fruits'}}}>跳转</Link>
    //使用js传参
    this.props.router.push({pathname:'/production',query:{productionId:120,productionType:'fruits'}});
    //或者
    hashHistory.push({pathname:'/production',query:{productionId:120,productionType:'fruits'}});
    //this.props.history.push()
    

    获取参数

    var { productionId } = this.props.location.query
    
  • state传参

    • 路由不需要配置
    • 刷新页面参数不消失,参数不会在地址栏中显示

    页面传参

    var data = {id:3,name:sam,age:36};
    var path = {
      pathname:'/user',
      state:data,
    }
    
    <Link to={path}>用户</Link>
    
    hashHistory.push(path);
    //this.props.history.push(path)
    
    this.props.router.push(path);
    

    获取参数

    var { productionId } = this.props.location.state
    
  • search传参 ?后面传递的参数

    • 地址栏显示参数
    • 路由不需要配置

    页面传参

    <link to="web/departManange?tenantId=12121212">xxx</Link>
    //或者
    this.props.history.push({pathname:"/web/departManange?tenantId" + row.tenantId});
    

    获取参数

     this.props.location.search
    
函数组件
  1. 路由参数 url params在/之后的参数

    路由跳转

    import {Link,NavLink} from 'react-router-dom'
    import {useNavigate} from 'react-router-dom';
    
    <Link to="/login/123">跳转到登录</Link>
    
    const navigate = useNavigate();
    navigate("/login/123");
    
    

    配置路由

    <Route path="login/:code" element={<Login />}></Route>
    <Route path="login" element={<Login/>}/>
    

    获取路由参数

    import { useParams } from 'react-router-dom'
    export default function Login() {
    const {code} = useParams();
    return <div>{code}</div>
    }
    
  2. 路由参数 search params 在?后面的参数

    路由跳转

    navigate("/login?a=10&b=20");
    

    接收参数

    import { useSearchParams } from 'react-router-dom'
    
    const [searchParams, setSearchParams] = useSearchParams();
    //第一种方式
    const 变量名 = searchParams.get("键名");
    //第二种方式
    const items =searchParams.entries()/values()/keys();
    for(let item of items){
        
    }
    

IndexedDB/cookie

使用一些全局性(支持跨页面)的存储方案:IndexedDB、cookie

消息发送方:将消息存储到IndexedDB中

接收方:通过轮询去获取最新的消息

Shared Worker

支持两种消息:一种是post,Shared Worker收到后会将该数据保存下来;另一种是get,Shared Worker收到该消息后会将保存的数据通过postMessage传给注册它的页面

Shared Worker无法主动通知所有页面,会使用轮询的方式,拉取最新的数据

window.open + window.opener

使用window.open()打开页面时,该方法会返回一个被打开的页面的window引用,而在未显示指定noopener时,被打开的页面可以通过window.opener获取到打开它的页面的引用——将页面之间建立起了一种树形结构的连接

1、将所有window.open打开的页面的window对象收集起来

let childWins = [];
document.getElementById('btn').addEventListener('click', function(){
    const win = window.open('./some/sample');
    childWins.push(win);
})

2、发送消息时,页面需要同时通知它打开的所有页面与打开它的页面

// 过滤掉已经关闭的窗口
childWins = childWins.filter(w => !w.closed);
if (childWins.length > 0) {
    mydata.fromOpenner = false;
    childWins.forEach(w => w.postMessage(mydata));
}
if (window.opener && !window.opener.closed) {
    mydata.fromOpenner = true;
    window.opener.postMessage(mydata);
}

3、消息接收方,需要展示数据,还需要将消息再传递给它所知道的页面(打开它与被它打开)

注意:需要避免消息回传给发送方,防止消息在两者之间形成死循环传递

window.addEventListener('message', function (e) {
    const data = e.data;
    const text = '[receive] ' + data.msg + ' —— tab ' + data.from;
    // 避免消息回传
    if (window.opener && !window.opener.closed && data.fromOpenner) {
        window.opener.postMessage(data);
    }
    // 过滤掉已经关闭的窗口
    childWins = childWins.filter(w => !w.closed);
    // 避免消息回传
    if (childWins && !data.fromOpenner) {
        childWins.forEach(w => w.postMessage(data));
    }
});
window.open()

用于打开一个新的浏览器窗口或者查找一个已命名的窗口

window.open(URL, name, features, replace)

//新打开一个没有菜单栏、标题栏、工具栏,但是有滚动条、状态栏、地址栏且可伸缩窗口的方法调用如下:
window.open("index.html", "newWindow", "width=1024, height=700, top=0, left=0, titlebar=no, menubar=no, scrollbars=yes, resizable=yes, status=yes, , toolbar=no, location=yes");

URL:可选字符串,声明了要在新窗口显示的文档URL,省略或为空字符串时,新窗口不会显示任何文档

name:可选字符串,为新打开窗口的名字,可以通过改名字获取该窗口对象;也可以是<a>``<form>标签的target属性_blank,将在新标签页打开新窗口

features:可选字符串,只要配置了该参数,新窗口将在新窗口打开,是浏览器窗口的特征

replace:可选布尔值,规定装载到窗口的URL是否创建一个历史记录,还是替换

​ true:替换

​ false:新创建

window.opener

opener属性:可读可写,可返回对创建该窗口的window对象的引用(父窗口的引用),可使用它的属性和函数

非同源页面间的跨页面通信

iframe

通过嵌入同源iframe作为,将非同源页面通信转换为同源页面通信

由于iframe与父页面之间可以通过指定origin来忽略同源策略,可以在每个页面中嵌入一个iframe,iframe的src都使用同一个url,因此属于同源页面,在通信上可以复用上面同源页面的各种通信方式

1、需要在页面中监听iframe发来的消息

window.addEventListener('message', function(e){
    
})

2、当页面需要向其他非同源页面通信时,会先给iframe发送消息

接收两个参数,第二个参数是targetOrigin,用于指定哪些窗口能接收到消息事件可以设置为iframe的URL

window.frames[0].window.postMessage(mydata, "*");

3、在所有iframe页面中,使用任意一种同源页面的跨页面通信方式传递信息

/** iframe内代码*/
const bc = new BroadcastChannel('demo');
//接收来自页面的消息后,通过BroadcastChannel在所有iframe之间传递
window.addEventListener('message', function(e) {
    bc.postMessage(e.data);
})

4、其他iframe页面接收到通知后,将消息同步给所属业务页面

/** iframe内代码*/
// 对于收到的(iframe)广播消息,通知给所属的业务页面
bc.onmessage = function (e) {
    window.parent.postMessage(e.data, '*');
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue前端页面的详细设计可以包括以下几个方面: 1. 页面布局:使用Vue的组件系统来构建页面布局,可以使用ElementUI框架提供的组件来快速搭建页面结构。例如,可以使用`el-row`和`el-col`组件来创建栅格布局,使用`el-container`组件来创建容器布局。 2. 数据绑定:Vue使用双向数据绑定的方式来实现页面和数据的同步更新。可以使用`v-model`指令将表单元素与数据进行绑定,也可以使用插值表达式`{{}}`将数据显示在页面上。 3. 事件处理:Vue提供了丰富的事件处理机制,可以使用`v-on`指令来监听DOM事件,并在触发时执行相应的方法。例如,可以使用`v-on:click`来监听点击事件,使用`v-on:submit`来监听表单提交事件。 4. 条件渲染:Vue提供了`v-if`和`v-else`指令来实现条件渲染。可以根据数据的值来决定是否显示某个元素或组件。 5. 列表渲染:Vue提供了`v-for`指令来实现列表渲染。可以使用`v-for`指令遍历数组或对象,并根据每个元素生成相应的DOM元素。 6. 组件通信:Vue提供了多种方式来实现组件之间的通信,包括父子组件通信、兄弟组件通信级组件通信。可以使用`props`属性来传递数据给子组件,使用自定义事件来在子组件中触发父组件的方法。 7. 路由管理:Vue提供了Vue Router插件来实现前端路由管理。可以使用Vue Router来定义路由规则,并在不同的路由之间进行切换。 8. 状态管理:Vue提供了Vuex插件来实现全局状态管理。可以使用Vuex来管理应用的状态,并在不同的组件中共享数据。 9. 动画效果:Vue提供了`transition`组件和`transition-group`组件来实现动画效果。可以使用这些组件来给页面元素添加过渡效果或动画效果。 10. 接口调用:在前端页面中,通常需要与后端接口进行数据交互。可以使用Vue的`axios`库来发送HTTP请求,并处理接口返回的数据。 下面是一个简单的示例,演示了如何使用Vue和ElementUI框架来设计一个前端页面: ```html <template> <div> <el-row> <el-col :span="12"> <el-input v-model="name" placeholder="请输入姓名"></el-input> </el-col> <el-col :span="12"> <el-button type="primary" @click="submit">提交</el-button> </el-col> </el-row> <el-row v-if="submitted"> <el-col :span="24"> <p>您好,{{ name }}!</p> </el-col> </el-row> </div> </template> <script> export default { data() { return { name: '', submitted: false } }, methods: { submit() { // 调用接口进行数据提交 // ... this.submitted = true; } } } </script> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值