日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

的translate插件_知否 ?知否 ?React插件了解一下!

發(fā)布時間:2025/3/12 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 的translate插件_知否 ?知否 ?React插件了解一下! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

為什么選擇插件,而不是組件?

  • 調(diào)用簡單 ?this.$toast("xxx") ,不必再模板中提前定義 , 動態(tài)插入移除
  • 插件獨立于業(yè)務
  • 更新不影響代碼邏輯,做到熱更新
  • 抽象,封裝
  • 適用于toast,Dialog,Alert,Message,picker,Actionsheet等組件

react-toast-alert demo地址

使用方法:

import?$?from?'@/component/Toast/index';

...

$.toast({
?type:0,
?content:?"我是默認Toast",
?time:?1000,
?opacity:?.5,
?onSucc()?{
??console.log("我是Toast的回調(diào)!")
?}
?});

$.toast("我是默認Toast");


$.toast({
?type:3,
?content:?"我是默認loading",
?time:?1000,
});

setTimeout(()?=>?{??//3s后隱藏
?$.hide();
},?3000);


$.dialog({
?type:?0,
?opacity:0.5,
?title:?"我是title",
?content:?"我是content",
?btnSucc:?"我是成功",
?btnFail:?"我是取消",
?onSucc(e)?{
??e.stopPropagation();
??$.toast("我是默認Toast");
?},
?onFail(e)?{
??e.stopPropagation();
??console.log("我是失敗的回調(diào)!");
?}
});

Vue 插件

在Vue里,一般將toast,alert等非業(yè)務相關的寫成插件,掛載在Vue的原型鏈上,使用的時候直接this.$toast即可,非常方便!相關原理在這里就不說了,感興趣的可以查閱官網(wǎng). 先看看Vue的插件寫法:

@/components/vue-toast/index.js

import?ToastComponent?from?"./vue-toast.vue";?//?引入先前寫好的vue
var?Toast?=?{};
//避免重復install,設立flag
Toast.installed?=?false;
Toast.install?=?function(Vue,?options?=?{
?type:?"success",?//success?fail??warning?loading?toast
?msg:?"操作成功",
?time:?1000,
?callback()?{

?}
})?{
?if(Toast.installed)?return;
?var?obj;
?Vue.prototype.$toast?=?(config?=?{},?type)?=>?{
??if(type?==?'close')?{
???obj?&&?obj.removeToast();
???return?false;
??}
??if(typeof?config=="object"){
???config?=?{
????...options,
????...config
???}
??}else{
???config?=?{
????...options,
????...{
?????type:?"toast",?
?????????????????msg:?config
????}
???}
??}
??
??//?如果頁面有toast則不繼續(xù)執(zhí)行
??if(document.querySelector('.vue-toast'))?return;
??//?1、創(chuàng)建構(gòu)造器,定義好提示信息的模板
??const?toastTip?=?Vue.extend(ToastComponent);
??obj?=?new?toastTip();

??for(var?property?in?config)?{
???obj[property]?=?config[property];
??}

??//刪除彈框
??obj.removeToast?=?function()?{
???document.body.removeChild(tpl);
??}

??//插入頁面
??let?tpl?=?obj.$mount().$el;
??document.body.appendChild(tpl);
??Toast.installed?=?true;

??if(['success',?'fail',?'warning','toast'].indexOf(config.type)?>?-1)?{
???setTimeout(()?=>?{
????obj.removeToast();
????obj.callback();
???},?config.time)
??}

??['close'].forEach(function(type)?{
???Vue.prototype.$toast[type]?=?function(msg)?{
????return?Vue.prototype.$toast({},?type)
???}
??});
?};
};
//?自動安裝??,有了ES6就不要寫AMD,CMD了
if(typeof?window?!==?'undefined'?&&?window.Vue)?{
?window.Vue.use(Toast)
};

export?default?Toast

@/components/vue-toast/vue-toast.vue

<template>
??<div?class="mask?vue-toast">
????<div>
??????<div?class="toast"?v-if="['success',?'fail',?'warning','loading'].indexOf(type)?>?-1">
????????<div?class="icon"?v-if="['success',?'fail',?'warning'].indexOf(type)?>?-1">
??????????<div?v-if="type=='success'"?class="success-icon">div>
??????????<div?v-if="type=='fail'"?class="fail-icon">div>
??????????<div?v-if="type=='warning'"?class="warning-icon">div>
????????div>
????????<div?class="loading-icon"?v-else>
??????????<span>span>
??????????<span>span>
??????????<span>span>
??????????<span>span>
??????????<span>span>
??????????<span>span>
??????????<span>span>
??????????<span>span>
??????????<span>span>
??????????<span>span>
??????????<span>span>
??????????<span>span>
????????div>
????????<div?class="msg"?v-html="msg">div>
??????div>
??????<div?v-else?class="toast-msg"?v-html="msg">div>
????div>
??div>
template>
<script>export?default?{
??data()?{return?{msg:?"?",type:?"success"
????};
??}
};script>
<style?scoped="scoped?"?lang="less">
.mask?{
??width:?100%;
??height:?100%;
??background:?rgba(0,?0,?0,?0.4);
??position:?fixed;
??left:?0px;
??top:?0px;
??display:?flex;
??justify-content:?center;
??align-items:?center;
??z-index:?10000;
??.toast-msg?{
????font-size:?0.24rem;
????text-align:?center;
????position:?relative;
????transform:?translateX(-50%);
????color:?#fff;
????left:?50%;
????padding:?0.18rem?0.27rem;
????overflow:?hidden;
????border-radius:?4px;
????white-space:?nowrap;
????display:?block;
????background:?rgba(0,?0,?0,?0.7);
??}
??.toast?{
????font-size:?0rem;
????padding:?0.27rem?.090rem;
????width:?2.26rem;
????overflow:?hidden;
????display:?flex;
????align-items:?center;
????flex-direction:?column;
????color:?#f2f2f2;
????background:?rgba(51,?51,?51,?0.94);
????border-radius:?0.09rem;
????text-align:?center;
????.icon?{
??????width:?0.72rem;
??????height:?0.72rem;
??????border-radius:?50%;
??????border:?1px?solid?#f2f2f2;
??????position:?relative;
??????justify-content:?center;
??????align-items:?center;
??????display:?flex;
??????
??????position:?relative;
??????.success-icon?{
????????border-right:?1px?solid?#f2f2f2;
????????border-bottom:?1px?solid?#f2f2f2;
????????transform:?rotate(45deg);
????????width:?0.27rem;
????????height:?0.45rem;
????????margin-top:?-0.18rem;
??????}
??????.fail-icon?{
????????&:before?{
??????????content:?"?";
??????????position:?absolute;
??????????top:?50%;
??????????left:?50%;
??????????transform:?translate(-50%,?-50%)?rotate(45deg);
??????????border-top:?1px?solid?#f2f2f2;
??????????width:?0.5rem;
??????????height:?0px;
????????}
????????&:after?{
??????????content:?"?";
??????????content:?"?";
??????????position:?absolute;
??????????top:?50%;
??????????left:?50%;
??????????transform:?translate(-50%,?-50%)?rotate(-45deg);
??????????border-top:?1px?solid?#f2f2f2;
??????????width:?0.5rem;
??????????height:?0px;
????????}
??????}
??????.warning-icon?{
????????&:before?{
??????????content:?"?";
??????????position:?absolute;
??????????top:?50%;
??????????left:?50%;
??????????transform:?translate(-50%,?-500%)?rotate(90deg);
??????????border-top:?1px?solid?#f2f2f2;
??????????width:?0.27rem;
??????????height:?0px;
????????}
????????&:after?{
??????????content:?"?";
??????????content:?"?";
??????????position:?absolute;
??????????top:?50%;
??????????left:?50%;
??????????transform:?translate(-50%,?250%)?rotate(-45deg);
??????????background:?#f2f2f2;
??????????width:?3px;
??????????border-radius:?50%;
??????????height:?3px;
????????}
??????}
????}
????.msg?{
??????margin-top:?0.18rem;
??????font-size:?0.24rem;
????}
??}
}

.loading-icon?{
??font-size:?0px;
??box-sizing:?border-box;
??width:?0.72rem;
??height:?0.72rem;
??position:?relative;
??span {
????position:?absolute;
????height:?1px;
????left:?50%;
????top:?50%;
????width:?0.18rem;
????animation:?loading-fade-light?1.1s?infinite?linear;
????background:?rgba(255,?255,?255,?0.3);
????transform-origin:?-0.18rem?50%;
????margin-left:?0.18rem;
????&:nth-child(1)?{
??????animation-delay:?0s;
??????transform:?rotate(0deg);
????}
????&:nth-child(2)?{
??????animation-delay:?0.1s;
??????transform:?rotate(30deg);
????}
????&:nth-child(3)?{
??????animation-delay:?0.2s;
??????transform:?rotate(60deg);
????}
????&:nth-child(4)?{
??????animation-delay:?0.3s;
??????transform:?rotate(90deg);
????}
????&:nth-child(5)?{
??????animation-delay:?0.4s;
??????transform:?rotate(120deg);
????}
????&:nth-child(6)?{
??????animation-delay:?0.5s;
??????transform:?rotate(150deg);
????}
????&:nth-child(7)?{
??????animation-delay:?0.6s;
??????transform:?rotate(180deg);
????}
????&:nth-child(8)?{
??????animation-delay:?0.7s;
??????transform:?rotate(210deg);
????}
????&:nth-child(9)?{
??????animation-delay:?0.8s;
??????transform:?rotate(240deg);
????}
????&:nth-child(10)?{
??????animation-delay:?0.9s;
??????transform:?rotate(270deg);
????}
????&:nth-child(11)?{
??????animation-delay:?1s;
??????transform:?rotate(300deg);
????}
????&:nth-child(12)?{
??????animation-delay:?1.1s;
??????transform:?rotate(330deg);
????}
??}
}

@-webkit-keyframes?loading-fade-light?{
??0%?{
????background-color:?#fff;
??}
??100%?{
????background-color:?rgba(255,?255,?255,?0);
??}
}

@keyframes?loading-fade-light?{
??0%?{
????background-color:?#fff;
??}
??100%?{
????background-color:?rgba(255,?255,?255,?0);
??}
}
style>

入口文件注冊:

import?vueToast?from?'@/components/vue-toast'
Vue.use(vueToast);

React 插件toast的封裝

Toast/index.js

import?React?from?"react";
import?ReactDOM?from?'react-dom';
import?Toast?from?'./toast';
?
export?default?class?Global?{
?static?toastEle='';
?static?toast(option)?{
??var?setting={
???type:0,
????content:"默認信息",
????time:2000,
????opacity:0,
????onSucc:()=>{}
??};
??
??if(typeof?option?=="string"){
???setting={...setting,content:option,type:4}
??}else{
???setting={...setting,...option}
??}
??
??this.show(0,setting);
??
??if(setting.type!==3){???//loading需要手動關閉
???setTimeout(()?=>?{
????this.hide();
????setting.onSucc();
???},?setting.time);
??}
?}
?
?static?dialog(option)?{
???var?setting={
????type:0,
????title:"我是默認title",
????content:"我是默認content",
????btnSucc:"我是默認btn",
????CloseShow:false,
????onClose(){
?????console.log("蒙層回調(diào)");
??????},
????onSucc(){
?????console.log("成功回調(diào)");
??????},
??????onFail(){
???????console.log("失敗回調(diào)");
??????}
???};
???
???setting={...setting,...option};
???
???this.show(1,setting);
?}
???
?
?static?show(n,setting)?{
??
??var?div?=?document.createElement('div');
??var?id?=?document.createAttribute("id");
??
??this.toastEle='pluginEle-'+new?Date().getTime();
??
??id.value?=?this.toastEle;
??div.setAttributeNode(id);
??document.body.appendChild(div);
??ReactDOM.render(<Toast?setting={setting}?/>,?div);
?}
?static?hide()?{
??var?toastEle?=?document.querySelector("#"+this.toastEle);
??if(toastEle){
???ReactDOM.unmountComponentAtNode(toastEle);
??????document.body.removeChild(toastEle);
??}
?}
}

Toast/toast.js

import?React?from?"react";
import?'./toast.less'

export?default?class?Toast?extends?React.Component?{
?constructor(props)?{
??super(props);
?}

?checkToast(n)?{
??switch(n)?{
???case?0:
????return?(<div?className="icon"><div?className="success-icon">div>div>)
????break;
???case?1:
????return?(<div?className="icon"><div?className="fail-icon">div>div>)
????break;
??????case?2:
????return?(<div?className="icon"><div?className="warning-icon">div>div>)
????break;
??????case?3:
????return?(
???????????????<div?className="loading-icon"><span>span><span>span><span>span><span>span><span>span><span>span><span>span><span>span><span>span><span>span><span>span><span>span>div>
???????????)
????break;
???default:
???????return?null
??}
?}

?render()?{

??let?{
???type,content,opacity?=?0
??}?=?this.props.setting;

??let?style?=?{
???"background":?`rgba(0,0,0,${opacity})`
??}

??return(
???<div?className="mask"?style={style}><div?className="toast">
???????????{this.checkToast(type)}<div?className="msg">{content}div>div>div>
??);
?}
}

Toast/toast.less

.mask?{
????width:?100%;
????height:?100%;
????background:?rgba(0,?0,?0,?0.4);
????position:?fixed;
????left:?0px;
????top:?0px;
????display:?flex;
????justify-content:?center;
????align-items:?center;
????z-index:?10000;
????.toast-msg?{
????????font-size:?24px;
????????text-align:?center;
????????position:?relative;
????????transform:?translateX(-50%);
????????color:?#fff;
????????left:?50%;
????????padding:18px?27px;
????????overflow:?hidden;
????????border-radius:?4px;
????????white-space:?nowrap;
????????display:?block;
????????background:?rgba(0,?0,?0,?0.7);
????}
????.toast?{
????????font-size:?0px;
????????padding:?27px?9px;
????????width:?226px;
????????overflow:?hidden;
????????display:?flex;
????????align-items:?center;
????????flex-direction:?column;
????????color:?#f2f2f2;
????????background:?rgba(51,?51,?51,?0.94);
????????border-radius:?9px;
????????text-align:?center;
????????.icon?{
????????????width:72px;
????????????height:72px;
????????????border-radius:?50%;
????????????border:?1px?solid?#f2f2f2;
????????????position:?relative;
????????????justify-content:?center;
????????????align-items:?center;
????????????display:?flex;
????????????position:?relative;
????????????margin-bottom:?18px;
????????????.success-icon?{
????????????????border-right:?1px?solid?#f2f2f2;
????????????????border-bottom:?1px?solid?#f2f2f2;
????????????????transform:?rotate(45deg);
????????????????width:27px;
????????????????height:?45px;
????????????????margin-top:?-18px;
????????????????
????????????}
????????????.fail-icon?{
????????????????&:before?{
????????????????????content:?"?";
????????????????????position:?absolute;
????????????????????top:?50%;
????????????????????left:?50%;
????????????????????transform:?translate(-50%,?-50%)?rotate(45deg);
????????????????????border-top:?1px?solid?#f2f2f2;
????????????????????width:?50px;
????????????????????height:?0px;
????????????????}
????????????????&:after?{
????????????????????content:?"?";
????????????????????content:?"?";
????????????????????position:?absolute;
????????????????????top:?50%;
????????????????????left:?50%;
????????????????????transform:?translate(-50%,?-50%)?rotate(-45deg);
????????????????????border-top:?1px?solid?#f2f2f2;
????????????????????width:?50px;
????????????????????height:?0px;
????????????????}
????????????}
????????????.warning-icon?{
????????????????&:before?{
????????????????????content:?"";
????????????????????display:?block;
????????????????????position:?absolute;
????????????????????top:?15px;
????????????????????left:?50%;
????????????????????background:#f2f2f2;
????????????????????width:1px;
????????????????????height:?30px;
????????????????}
????????????????&:after?{
????????????????????content:?"";
????????????????????position:?absolute;
????????????????????bottom:?14px;
????????????????????left:?50%;
????????????????????background:#f2f2f2;
????????????????????width:?6px;
????????????????????margin-left:?-2px;
????????????????????border-radius:?50%;
????????????????????height:?6px;
????????????????}
????????????}
????????}
????????.msg?{
????????????
????????????font-size:24px;
????????}
????}
}

.loading-icon?{
????font-size:?0px;
????margin-bottom:?18px;
????box-sizing:?border-box;
????width:?72px;
????height:?72px;
????position:?relative;
????span {
????????position:?absolute;
????????height:?1px;
????????left:?50%;
????????top:?50%;
????????width:?18px;
????????animation:?loading-fade-light?1.1s?infinite?linear;
????????background:?rgba(255,?255,?255,?0.3);
????????transform-origin:?-18px?50%;
????????margin-left:?18px;
????????&:nth-child(1)?{
????????????animation-delay:?0s;
????????????transform:?rotate(0deg);
????????}
????????&:nth-child(2)?{
????????????animation-delay:?0.1s;
????????????transform:?rotate(30deg);
????????}
????????&:nth-child(3)?{
????????????animation-delay:?0.2s;
????????????transform:?rotate(60deg);
????????}
????????&:nth-child(4)?{
????????????animation-delay:?0.3s;
????????????transform:?rotate(90deg);
????????}
????????&:nth-child(5)?{
????????????animation-delay:?0.4s;
????????????transform:?rotate(120deg);
????????}
????????&:nth-child(6)?{
????????????animation-delay:?0.5s;
????????????transform:?rotate(150deg);
????????}
????????&:nth-child(7)?{
????????????animation-delay:?0.6s;
????????????transform:?rotate(180deg);
????????}
????????&:nth-child(8)?{
????????????animation-delay:?0.7s;
????????????transform:?rotate(210deg);
????????}
????????&:nth-child(9)?{
????????????animation-delay:?0.8s;
????????????transform:?rotate(240deg);
????????}
????????&:nth-child(10)?{
????????????animation-delay:?0.9s;
????????????transform:?rotate(270deg);
????????}
????????&:nth-child(11)?{
????????????animation-delay:?1s;
????????????transform:?rotate(300deg);
????????}
????????&:nth-child(12)?{
????????????animation-delay:?1.1s;
????????????transform:?rotate(330deg);
????????}
????}
}

@-webkit-keyframes?loading-fade-light?{
????0%?{
????????background-color:?#fff;
????}
????100%?{
????????background-color:?rgba(255,?255,?255,?0);
????}
}

@keyframes?loading-fade-light?{
????0%?{
????????background-color:?#fff;
????}
????100%?{
????????background-color:?rgba(255,?255,?255,?0);
????}
}

使用

import?$?from?'@/component/Toast/index';

...

$.toast({
?type:0,
?content:?"我是默認Toast",
?time:?1000,
?opacity:?.5,
?onSucc()?{
??console.log("我是Toast的回調(diào)!")
?}
});
??
$.toast("我是默認Toast");

為什么不掛載在React原型鏈上?

有坑!主要原因還是React組件的this神出鬼沒!

ES6 toast插件


var?body?=?document.body
var?tip
var?timeout
var?time?=?3000
var?setStyleTime?=?50
function?Tip?(str,?time)?{
??if?(tip)?{
????clearTimeout(timeout)
????//?tip.find('p').html(str);
??}?else?{
????tip?=?document.createElement('div')
????tip.className?=?'__toast'
????tip.innerHTML?=?str
????//?tip.style.cssText?=?'z-index:?999;position:?fixed;webkit-transition:?opacity?.3s?ease;transition:?opacity?.3s?ease;opacity:?0;color:?#fff;border-radius:?8px;left:?50%;width:?80%;margin-left:?-40%;?/*px*/text-align:?center;line-height:?1.5;background:?rgba(0,0,0,.6);padding:?1%?1%;top:?45%;box-sizing:?border-box;font-size:?1.5em;';
????body.appendChild(tip)
????setTimeout(function?()?{
??????tip.style.opacity?=?1
????},?setStyleTime)
??}
??timeout?=?clear(time)
}

function?clear?(time)?{
??return?setTimeout(remove,?time)
}

function?remove?()?{
??if?(tip)?{
????body.removeChild(tip)
????tip?=?null
??}
}

function?entry?(msg,?expire)?{
??msg?=?msg?||?''
??if?(!expire?||?expire?<=?setStyleTime)?{
????expire?=?time
??}

??Tip(msg,?expire)
};

export?default?entry

附:React開發(fā)技巧

自動注冊全局組件或函數(shù) require.context

我的業(yè)務場景大部分是中后臺,雖然封裝和使用了很多第三方組件,但還是免不了需要自己封裝和使用很多業(yè)務組件。但每次用的時候還需要手動引入,真的是有些麻煩的。

/**
?*?@desc?webpack打包入口文件??
?*?@example?自動引入子目錄下所有js文件
?*/
let?moduleExports?=?{};

const?r?=?require.context('./',?true,?/^\.\/.+\/.+\.js$/);
r.keys().forEach(key?=>?{
????let?attr?=?key.substring(key.lastIndexOf('/')?+?1,?key.lastIndexOf('.'));
????moduleExports[attr]?=?r(key);
});

module.exports?=?moduleExports;

我們其實可以基于 webpack 的require.context來實現(xiàn)自動加載組件并注冊的全局的功能。相關原理在之前的文章中已經(jīng)闡述過了。具體代碼如下

我們可以創(chuàng)建一個GlobalComponents文件夾,將你想要注冊到全局的組件都放在這個文件夾里,在index.js里面放上如上代碼。之后只要在入口文件main.js中引入即可。

//main.js
import?'./components/Table/index'?//?自動注冊全局業(yè)務組件

這樣我們可以在模板中直接使用這些全局組建了。不需要再繁瑣的手動引入了。

一把梭改變state值

this.setState({
???[name]:?value
??});
const?{?data?}?=?this.state;
this.setState({?data:?{...data,?key:?1?}?});

另外一種可以通過callback的方式改變state的值

this.setState(({?data?})?=>?({?data:?{...data,?key:?1?}?}));

還可以:

this.setState((state,?props)?=>?{
????return?{?counter:?state.counter?+?props.step?};
});

還可以一把梭:

this.state.a=1;
this.state.b="張三";
this.state.c=true;
this.state.xxx=...
...

this.setState(this.state);???//一把梭

this.setState支持異步async await

?this.setState((prevState)?=>?({
??isFiltered:?!prevState.isFiltered
?}),?()?=>?{
??this.filterData();
?});
?clickMe=(e)=>{
????this.setState((prevState)=>{
??????return?{num:prevState.num+1}
????});
?}
??async?clickMe1(){
????await?this.setState((prevState)=>{
??????return?{num:prevState.num+1}
????});
????await?this.setState((prevState)=>{
??????return?{num:prevState.num+1}
????});
????await?this.setState((prevState)=>{
??????return?{num:prevState.num+1}
????});
??}

唯一key

react數(shù)組循環(huán),基本都會設置一個唯一的key,表格的對象數(shù)組循環(huán)一般沒什么問題,數(shù)據(jù)基本都會有一個id。那有種情況就比較坑了,出現(xiàn)在表單形式的頁面結(jié)構(gòu)中,對某個數(shù)組進行增刪改操作,一般對于非對象數(shù)組而言,沒有id,可能很多人會偷懶,循環(huán)的時候,直接設置數(shù)組的下標index作為key,當出現(xiàn)增刪改時候,就會出現(xiàn)數(shù)據(jù)對不上或者重新渲染組件的問題等。解決方案有很多種,例如把字符串數(shù)組等重組對象數(shù)組,每個元素設置一個唯一id等。另外有個方式:推薦使用shortid生成唯一key的數(shù)組,和數(shù)據(jù)數(shù)組一起使用,省去提交數(shù)據(jù)時再重組數(shù)組。

import?React?from?'react';
import?shortid?from?'shortid';

class?Demo?extends?React.Component?{
????constructor(props)?{
??super(props);
??this.state?=?{
???data:?['a',?'b',?'c']
??}
??this.dataKeys?=?this.state.data.map(v?=>?shortid.generate());
?}
?
????deleteOne?=?index?=>?{?//?刪除操作
????????const?{?data?}?=?this.state;
????????this.setState({?data:?data.filter((v,?i)?=>?i?!==?index)?});
????????this.dataKyes.splice(index,?1);
????}
????
????render()?{
?????return?(
?????????<ul>
???????????????{
???????????????????data.map((v,?i)?=>?<li?onClick={i?=>?this.deleteOne(i)}??
????????????????????????key={this.dataKeys[i]}
????????????????????>
????????????????????????{v}li>
????????????????????)
???????????????}?ul>
?????)
?}
}
//?稍微抽取,可以封裝一個通用的組件

三目運算

通過判斷值是否存在來控制元素是否顯示,一般三目運算可以達到此效果,最簡單的還是用短路的寫法:

//?不錯
const?flag?=?'something';
flag?&&?<div>div>

//?很好
//?注意一般可能上面寫法多一些,但當flag為0?的時頁面上會顯示0,用!!將其轉(zhuǎn)為boolean避免坑,
//?代碼也更規(guī)范
const?flag?=?'something';
!!flag?&&?<div>div>

使用組件,傳遞props

const?{?data,?type,?something?}?=?this.state;
<Demo?data={data}type={type}something={something}
/>

也許另外一種傳遞方式更簡潔:

const?{?data,?type,?something?}?=?this.state;
<Demo?
????{...{?data,?id,?something?}}
/>

簡化props

組件的props有時候會定義很多,但是調(diào)用組件傳遞props的時候又想一個個傳,不想一次性傳遞一個option對象,通過擴展運算符和解構(gòu)賦值可以簡化此操作:

const?Demo?=?({?prop1,?prop2,?prop3,?...restProps?})?=>?(
????<div>
????????xxxx
????????{?restProps.something?}div>
)
//?父組件使用Demo
????prop1={xxx}
????prop2={xxx}
????something={xxx}
/>

優(yōu)化React 性能

React 性能優(yōu)化有很多種方式,那常見的一種就是在生命周期函數(shù)shouldComponentUpdate里面判斷某些值或?qū)傩詠砜刂平M件是否重新再次渲染。

判斷一般的字符串,數(shù)字或者基礎的對象,數(shù)組都還是比較好處理,那嵌套的對象或者數(shù)組就比較麻煩了,對于這種,可以轉(zhuǎn)成字符串處理,但屬性值的位置不同時,那就無效了。

推薦使用lodash(或者其他的類似庫)的isEqual對嵌套數(shù)組或?qū)ο筮M行判斷(相比其他方式更簡單些)

shouldComponentUpdate(nextProps,?nextState)?{
????if?(_.isEqual(nextState.columns,?this.state.columns))?return?false;
????return?true;
}

創(chuàng)建彈層

創(chuàng)建彈層的三種方式:

1.普通組件通過state和樣式控制,在當前組件中顯示彈層-每次引入組件并且render里面控制顯示,掛載節(jié)點在某組件里面

//?彈層?
const?Dialog?=?()?=>?<div>彈層div>
//?某組件
render()?{
????return?(
????????this.state.showDialog?&&?<Dialog?/>
????)
}

2.通過Portals創(chuàng)建通道,在根節(jié)點外部掛載組件-但還是需要每次引入并且在render里面調(diào)用

//?彈層?
class?Dialog?extends?React.Component?{
??constructor(props)?{
????super(props);
????this.el?=?document.createElement('div');
??}
??componentDidMount()?{
????modalRoot.appendChild(this.el);
??}
??componentWillUnmount()?{
????modalRoot.removeChild(this.el);
??}

??render()?{
????return?ReactDOM.createPortal(
??????this.props.children?||?<div>xxxxdiv>,
??????this.el,
????);
??}
}
//?某組件
render()?{
????return?(
????????this.state.showDialog?&&?<Dialog?/>
????)
}

3.推薦使用ReactDom.render創(chuàng)建彈層-掛載根節(jié)點外層,使用也更方便

//?demo
let?dialog;
class?Dialog?{
????show(children)?{????//?顯示
????????this.div?=?document.createElement('div');
????????document.body.appendChild(this.div);

????????ReactDom.render(children?||?<div>xxxxdiv>,?this.div);
????}
????destroy()?{?????//?銷毀
????????ReactDom.unmountComponentAtNode(this.div);
????????this.div.parentNode.removeChild(this.div);
????}
}
export?default?{
????show:?function(children)?{
????????dialog?=?new?Dialog();
????????dialog.show(children);
????},
????hide:?xxxxx
};
//?某組件
import?Dialog?from?'xxx';
alert?=?()?=>?{
????Dialog.show(xxxx);
}
render()?{
????return?(
????????<button?onClick={this.alert}>點擊彈層button>
????)
}

插槽:children

render props是現(xiàn)在很流行的一種渲染方式,通過回調(diào)函數(shù),渲染子組件,參數(shù)可為父組件的任意屬性值(官網(wǎng)也有相應的介紹)新版的contextApi也采用了這個模式。

很多種場景使用此方式的做法:

//?權限控制組件,只需要封裝一次connect,
//?通過render?props向子組件傳遞權限
class?AuthWidget?extends?Component?{
????render()?{
????????return?this.props.children(this.props.auth);
????}
}

const?mapStateToProps?=?state?=>?{
????const?{?auth?}?=?state;
????return?{?auth:?state.auth?};
};
export?default?connect(mapStateToProps)(AuthWidget);

//?其他組件使用
????children={auth?=>?auth.edit?&&?編輯}
/>

//?使用antd的form時
const?Test?=?({?form,?children?})?=>?{
????return?children(form);
};
const?FormTest?=?Form.create()(Test);

class?Demo?extends?Component?{
????render()?{
????????return?(
????????????
????????????????xxxxx
????????????????????{?form?=>?{
????????????????????????this.form?=?form;
????????????????????????return?(
????????????????????????????????????{getFieldDecorator('field',?xxx)(
????????????????????????????????????)}
????????????????????????)
????????????????????}}
????????)
????}
}

子組件改變父組件的state

子組件改變父組件的state方式有很多種,可以在父組件設置一個通用函數(shù),類似:setParentState,通過子組件回調(diào)處理時,就可以更方便的統(tǒng)一處理:

//?父組件
state?=?{
????data:?{}
}
setParentState?=?obj?=>?{
????this.setState(obj);
}
//?子組件
onClick?=?()?=>?{
????this.props.setParentState({?data:?xxx?});
}

永遠不要直接設置state的值

永遠不要直接設置state的值:this.state.data = { a: 1 }。這個會導致幾個問題: 1:組件不會重新渲染
2:shouldComponentUpdate(nextProps, nextState) 函數(shù)里面 this.state的值是已經(jīng)改變了,和nextState的值相同。

舉個栗子:

//?wrong
const?{?data?}?=?this.state;
data.a?=?1;?????//?等價于this.state.data.a?=?1;
this.setState({?data?});
//?shouldComponentUpdate里面觀察到?this.state?和nextState的值是相同的
//?此時函數(shù)里面性能相關的優(yōu)化是無效的

//?correct??需要用到當前state值的寫法
this.setState(state?=>?({?data:?{...state.data,?a:?1}?}))

總結(jié)

以上是生活随笔為你收集整理的的translate插件_知否 ?知否 ?React插件了解一下!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。