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
}

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 (
    
      
...
); } export default App;

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 (
	            
// 水印组件 }>
) }
  • 水印组件,使用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}
) } }
) } }
  • 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;
}

2.4 水印效果图

根据以上定义后,展示的水印效果如下
React-Context实现水印功能_第1张图片

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} */}
    • }) }
    }) }
) } }
) } }
  • 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;
}

2.5.3 效果图

React-Context实现水印功能_第2张图片

如果有用,点个赞呗~

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

你可能感兴趣的:(前端,react.js,javascript,前端)