• React-Context实现水印功能


    1. Context简介

    Context提供了一个无需为每层组件手动添加Props,就能在组件树间进行数据传递的方法。

    • 若有一个值,在父组件定义过,想要在孙子组件中使用,使用props形式就需要将该值从父组件传给子组件,再从子组件传给孙组件,若层级更深则传起来十分复杂和麻烦。
    • Context提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树逐层传递props。

    2. Context使用

    使用场景: 我想要在App.js页面中注入某些内容,然后自定义一个水印组件。水印组件中的内容就是我在App.js中想要全局展示的固定内容。

    2.1 定义context.js const MyContext = React.createContext(defaultValue);

    • utils/context.js
    • 创建一个 Context 对象。当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider 中读取到当前的 context 值。
    • 只有当组件所处的树中没有匹配到 Provider 时,其 defaultValue 参数才会生效。此默认值有助于在不使用 Provider 包装组件的情况下对组件进行测试。注意:将 undefined 传递给 Provider 的 value 时,消费组件的 defaultValue 不会生效。
    import React from "react";
    
    let { Provider, Consumer } = React.createContext()
    
    export {
        Provider,
        Consumer
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.2 Provider

    • App.js 注入值
    • 每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。
    • Provider 接收一个 value 属性,传递给消费组件。一个 Provider 可以和多个消费组件有对应关系。多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据。
    • 当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。从 Provider 到其内部 consumer 组件(包括 .contextType 和 useContext)的传播不受制于 shouldComponentUpdate 函数,因此当 consumer 组件在其祖先组件跳过更新的情况下也能更新。
    import { Provider } from './utils/context';
    
    
    function App() {
      let userInfo ={
        name: 'Ably',
        age: 25,
        phone: 188******31, 
        email: '**********@163.com'
      }
      return (
        {sendItem: userInfo}}>
          
    ...
    ); } export default App;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2.3 Consumer

    • 一个 React 组件可以订阅 context 的变更,此组件可以让你在函数式组件中可以订阅 context。
    • 这种方法需要一个函数作为子元素(function as a child)。这个函数接收当前的 context 值,并返回一个 React 节点。传递给函数的 value 值等价于组件树上方离这个 context 最近的 Provider 提供的 value 值。如果没有对应的 Provider,value 参数等同于传递给 createContext() 的 defaultValue。
    • 想要给Myarticle页面组件增加水印组件Watermark
    • Myarticle/index.js 页面中使用水印组件
    import Watermark from '../../components/Watermark'
    
    render() {
    	return (
    	            
    // 水印组件 }>
    ) }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 水印组件,使用Consumer接收Provider提供的值
    • Watermark/index.js
    import { Component } from 'react';
    import { Consumer } from '../../utils/context';
    import './index.scss'
    
    export default class Watermark extends Component {
        render() {
            return (
                
    { ({sendItem}) => { return (
    {sendItem.name} {sendItem.email}
    ) } }
    ) } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • Watermark/index.css
    .watermark {
        transform: rotate(45deg);
        position: fixed; // 使用fixed固定定位,只要展示固定的值,那么之后这个无论页面如何滑动,都能保证下面的水印不被更改
        width: 100%;
        height: 100%;
        color: rgb(247, 243, 243);
        font-size: 44px;
        text-align: center;
        line-height: 100%;
        padding-top: 160px;
        z-index: -1;
    }
    
    .mr_8 {
        margin-right: 8px;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.4 水印效果图

    根据以上定义后,展示的水印效果如下
    在这里插入图片描述

    2.5 多方位水印

    只有固定某个位置有水印,一旦页面中的其他内容需要保密打水印时,容易产生遗漏情况,我们可以将满屏大多数位置上增加自己的水印

    2.5.1 实现思路

    • 若想满屏展示,那必然会是有一个大的list,横向铺满屏幕,大的list里面每一个小list纵向分布,铺满纵向
    • 外面大list,flex,横向均分
    • 里面小的list,纵向展示,铺满整个纵向屏幕
    • 此时页面内容已经铺满,然后将每一个小list里面的每一个item旋转

    2.5.2 代码实现

    • watermark.js
    import { Component } from 'react';
    import { Consumer } from '../../utils/context';
    import './index.scss'
    
    export default class Watermark extends Component {
        render() {
            let arrLenth = 6
            const list = Array.from({length: arrLenth})
            return (
                
    { ({sendItem}) => { return (
      { list.map((item, parentIndex) => { return
        { list.map((item, index) => { return
      • Ably {/* {sendItem.name} */} ********131 {/* {sendItem.email} */}
      • }) }
      }) }
    ) } }
    ) } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • watermark.css
    .watermark {
        position: fixed;
        width: 100vw;
        height: 100vh;
        color: rgb(247, 243, 243);
        font-size: 22px;
        line-height: 100%;
        z-index: -1;
        display: flex;
        justify-content: space-between;
        align-items: stretch;
        top: 0;
        left: 0;
    }
    
    .watermark_column {
        display: flex;
        flex-direction: column;
        justify-content: space-around;
    }
    
    .watermark_column_item {
        transform: rotate(45deg);
    }
    
    .mr_8 {
        margin-right: 8px;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    2.5.3 效果图

    在这里插入图片描述

    如果有用,点个赞呗~

    总结用法,希望可以帮助到你,
    我是Ably,你无须超越谁,只要超越昨天的自己就好~

  • 相关阅读:
    呼叫中心系统解决方案有哪些
    Hadoop入门(三):本地运行模式和完全分布模式,集群分发脚本、远程同步、集群分发
    【代码】Android|获取存储权限并创建、存储文件
    java计算机毕业设计基于安卓/Android/微信小程序的校园外卖点餐APP
    区间调度问题 ----- 贪心算法
    Hooks与事件绑定
    php在数字前面补0得到固定长度数字的两种方法
    【Spring Boot】错误处理及流程解析
    大学网课搜题公众号搭建教程(内含接口)
    DNS域名解析
  • 原文地址:https://blog.csdn.net/weixin_44593720/article/details/127635679