明:本篇測試是react+jest+@testing-library+react-router-dom+react-redux,如果react有疑問的,可以google,資源Supernumerary
我們已經講完了表單內容,那么現場來一個案例試試水~
這里完成的任務主要是將以上所講內容進行整合,同時發起一次api請求。
首先我們在express/index.js中加入一個post請求:
...
import bodyparser from 'body-parser';
// 解析body
app.use(bodyparser.urlencoded({extended:false}));
app.post('/home',(req,res) => {
const body = req.body;
console.log(body);
res.send({
status: 0,
msg: 'submit success'
})
})
如果您不知道為啥這里突然加了一個借口,建議回顧一下我當時項目搭建的過程:
https://www.toutiao.com/article/7250691387551826432/
接著新建網絡請求api/detail.ts文件
import axios from "axios";
const commonUrl = '/api';
interface Obj {
username: string,
age: string,
email: string,
city: string,
like: string,
isLike: boolean
}
export const submitData = async (data: Obj) => {
const path = commonUrl + '/home';
const res = await axios.post<any>(
path,
{...data},
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
);
return res.data
}
然后我們寫一個組件page/detail/Com/submit.tsx
import React,{useEffect,useState} from "react";
import {
Grid,
styled,
Box,
MenuItem,
Button
} from '@mui/material';
import ZlInput from "src/component/common/Input";
import RadioButtonsGroup from "src/component/common/radioGroup";
import Zl_checkbox from "src/component/common/checkbox";
import { submitData } from "../../../api/detail";
const ItemStyle = styled('div')({
[`& .MuiFormControl-root `]: {
verticalAlign: 'bottom',
marginLeft: '20px'
},
[`& span`]: {
display: 'inline-block',
width: '80px',
textAlign: 'right'
},
width: '100%'
})
const RadioStyle = styled('div')({
display: 'flex',
alignItems: 'center',
[`& .MuiFormControl-root `]: {
verticalAlign: 'bottom',
marginLeft: '20px'
},
[`& .radio-left`]: {
width: '80px',
textAlign: 'right',
},
})
const LikeStyle = styled('div')({
display: 'flex',
alignItems: 'center',
marginTop: '-10px',
[`& .MuiButtonBase-root`]: {
marginLeft: '6px'
},
[`& .radio-left`]: {
width: '80px',
textAlign: 'right',
},
})
const CityStyle = styled('div')({
[`& .MuiFormControl-root `]: {
verticalAlign: 'bottom',
marginLeft: '20px'
},
[`& span`]: {
display: 'inline-block',
width: '80px',
height: '42px',
textAlign: 'right'
},
width: '100%'
})
const SubmitStyle = styled('div')({
[`& .MuiButtonBase-root `]: {
verticalAlign: 'bottom',
marginLeft: '20px'
},
[`& span`]: {
display: 'inline-block',
width: '80px',
height: '42px',
textAlign: 'right'
},
width: '100%'
})
interface Item {
value: string,
label: string
}
interface Obj {
username: string,
age: string,
email: string,
city: string,
like: string,
isLike: boolean
}
const dd = [
{ value: 'apple', label: 'apple'},
{ value: 'apple2', label: 'apple2'},
{ value: 'apple3', label: 'apple3'},
]
const currencies = [
{
value: 'beijing',
label: 'beijing',
},
{
value: 'shanghai',
label: 'shanghai',
},
{
value: 'shenzhen',
label: 'shenzhen',
}
];
export default function Submit() {
const [obj,setObj] = useState<Obj>({
username: '',
age: '',
email: '',
city: '',
like: '',
isLike: false
})
const [like,setLike] = useState('');
const handleLikeOption = (event: React.ChangeEvent<HTMLInputElement>) => {
// console.log(event.target.value,'like');
const target = event.target;
if ( target.checked ) {
setLike(event.target.value);
setObj({
...obj,
like: event.target.value
})
} else {
setLike('')
}
}
const City = () => {
return (
<ZlInput id="city" data-testid='city' inputType='select' label='city' handleInputChange={changeCity} placeholder="please input" defaultValue={currencies[0].value} variant="standard" helperText="Please select your city" sx={{ width: '400px'}}>
{currencies.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</ZlInput>
)
}
const changeCity = (event: React.ChangeEvent<HTMLInputElement>) => {
setObj({
...obj,
city: event.target.value
})
}
const handleChangeLike = (event: React.ChangeEvent<HTMLInputElement>) => {
setObj({
...obj,
isLike: event.target.checked
})
}
const handleSubmit = async () => {
console.log('--submit data--',obj)
const res = await submitData(obj)
console.log(res,'submit')
}
const changeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const val = e.target.value;
if ( e.target.labels?.length ) {
// 這里有一個BUG,明明給了age輸入框一個label,但是labels獲取的NodeList為空數組,其他的卻正常
const labelValue = e.target?.labels[0]?.textContent;
switch(labelValue) {
case 'username':
setObj({
...obj,
username: val
})
break;
case 'age':
setObj({
...obj,
age: val
})
break;
case 'email':
setObj({
...obj,
email: val
})
}
} else {
// console.log(e.target.labels,'kkk')
setObj({
...obj,
age: val
})
}
}
return (
<Box sx={{ display: 'flex', flexWrap: 'wrap', width: '800px' }}>
<Grid container spacing={2} sx={{ padding: '20px'}}>
<Grid item xs={12}>
<ItemStyle>
<span>username: </span><ZlInput label='username' data-testid='username' handleInputChange={changeChange} defaultValue={obj.username} id="usename" placeholder="please input" variant="standard" sx={{ width: '400px'}} />
</ItemStyle>
</Grid>
<Grid item xs={12}>
<ItemStyle>
<span>age: </span><ZlInput id="age" label='age' data-testid='age' handleInputChange={changeChange} defaultValue={obj.age} placeholder="please input" variant="standard" sx={{ width: '400px'}} />
</ItemStyle>
</Grid>
<Grid item xs={12}>
<ItemStyle>
<span>email: </span><ZlInput id="email" data-testid='email' handleInputChange={changeChange} label='email' defaultValue={obj.email} placeholder="please input" variant="standard" sx={{ width: '400px'}} />
</ItemStyle>
</Grid>
<Grid item xs={12}>
<CityStyle>
<span>city: </span><City />
</CityStyle>
</Grid>
<Grid item xs={12}>
<RadioStyle>
<div className="radio-left">like: </div><RadioButtonsGroup data-testid='likeOptions' id="like-btn" dd={dd} handleChange={handleLikeOption} value={like} />
</RadioStyle>
</Grid>
<Grid item xs={12}>
<LikeStyle>
<div className="radio-left">like apple: </div><Zl_checkbox
checked={obj.isLike}
handleChange={handleChangeLike}
data-testid='like_apple'
/>
</LikeStyle>
</Grid>
<Grid item xs={12}>
<SubmitStyle>
<span></span>
<Button variant="contained" data-testid='submit' color="success" onClick={handleSubmit}>Submit</Button>
</SubmitStyle>
</Grid>
</Grid>
</Box>
)
}
看起來寫了很長,但是仔細閱讀,無非就是一些表單子內容,我們這里用到的是mui,可以賦值跑通,結果大概長這個樣子:
頁面展示效果
最后我們就可以寫測試文件__tests__/react/com/submit.test.tsx
import { fireEvent, screen } from '@testing-library/dom'
import { render, waitFor } from "@testing-library/react";
import * as utils from '../../../api/detail';
jest.mock('../../../api/detail');
const submitDD = jest.spyOn(utils,'submitData');
submitDD.mockImplementation(
(): Promise<any> => {
return new Promise((resolve) => {
resolve({
status: 0,
msg: 'submit success2'
})
})
}
)
// 引入jest-dom的匹配內容
import '@testing-library/jest-dom';
import {
setRadio,
getSelectValue,
InputField,
changeCheckbox
} from '../utils';
import Submit from 'src/page/detail/Com/submit';
describe('test react submit', () => {
it('test input',async () => {
console.log('kkk')
const Com = (
<Submit />
)
const container = render(Com);
// 三個輸入框
InputField({
testId: 'username',
value: 'jack'
})
InputField({
testId: 'age',
value: '12'
})
InputField({
testId: 'email',
value: '111@qq.com'
})
// 選擇城市
getSelectValue({
testId: 'city',
value: 'shanghai'
})
// 選擇喜歡項
const likeValue = setRadio({
value: 'apple2'
})
// 確定是否要apple
const checked2 = changeCheckbox({
testId: 'like_apple'
})
// 提交
const submitBtn = screen.getByTestId('submit');
fireEvent.click(submitBtn);
await waitFor(() => {
expect(submitDD).toHaveBeenCalled();
})
expect(container).toMatchSnapshot('submit-input')
})
})
當我們成功跑通的時候,我們就會看到如下的打印
表明模擬了表單提交
注意事項:
表單組件基本元素為這些了,那么對于列表list以及表格這塊怎么說呢,其實這兩個我們只需要給個初始值,他能夠正常渲染,覆蓋率基本上就很高了,而表格的一些高級操作,比如過濾,搜索等,如果你寫了方法,那么確實要測試一下,這個實現思路跟utils/index.ts里面的方法類似,模擬的時候操作了一遍,就能覆蓋到。
好了,上面這個例子希望大家去嘗試,加深一下組件測試。
庫,本質上是一些函數的集合。每次調用函數,實現一個特定的功能,接著把控制權交給使用者
框架,是一套完整的解決方案,使用框架的時候,需要把你的代碼放到框架合適的地方,框架會在合適的時機調用你的代碼
雖然沒有完全遵循 MVVM 模型,Vue 的設計無疑受到了它的啟發。因此在文檔中經常會使用 vm (ViewModel 的簡稱) 這個變量名表示 Vue 實例
<!-- 指定vue管理內容區域,需要通過vue展示的內容都要放到找個元素中 通常我們也把它叫做邊界 數據只在邊界內部解析-->
<div id="app">{{ msg }}</div>
<!-- 引入 vue.js -->
<script src="vue.js"></script>
<!-- 使用 vue -->
<script>
var vm = new Vue({
// el:提供一個在頁面上已存在的 DOM 元素作為 Vue 實例的掛載目標
el: '#app',
// Vue 實例的數據對象,用于給 View 提供數據
data: {
msg: 'Hello Vue'
}
})
</script>
var vm = new Vue({
data: {
msg: '大家好,...'
}
})
vm.$data.msg === vm.msg // true
<h1>Hello, {{ msg }}.</h1>
<p>{{ 1 + 2 }}</p>
<p>{{ isOk ? 'yes': 'no' }}</p>
<!-- !!!錯誤示范!!! -->
<h1 title="{{ err }}"></h1>
/* defineProperty語法 介紹 */
var obj = {}
Object.defineProperty(obj, 'msg', {
// 設置 obj.msg = "1" 時set方法會被系統調用 參數分別是設置后和設置前的值
set: function (newVal, oldVal) { },
// 讀取 obj.msg 時get方法會被系統調用
get: function ( newVal, oldVal ) {}
})
<!-- 示例 -->
<input type="text" id="txt" />
<span id="sp"></span>
<script>
var txt = document.getElementById('txt'),
sp = document.getElementById('sp'),
obj = {}
// 給對象obj添加msg屬性,并設置setter訪問器
Object.defineProperty(obj, 'msg', {
// 設置 obj.msg 當obj.msg反生改變時set方法將會被調用
set: function (newVal) {
// 當obj.msg被賦值時 同時設置給 input/span
txt.value = newVal
sp.innerText = newVal
}
})
// 監聽文本框的改變 當文本框輸入內容時 改變obj.msg
txt.addEventListener('keyup', function (event) {
obj.msg = event.target.value
})
</script>
var vm = new Vue({
data: {
stu: {
name: 'jack',
age: 19
}
}
})
/* Vue.set */
Vue.set(vm.stu, 'gender', 'male')
/* Object.assign 將參數中的所有對象屬性和值 合并到第一個參數 并返回合并后的對象*/
vm.stu = Object.assign({}, vm.stu, { gender: 'female', height: 180 })
methods: {
fn() {
this.msg = 'change'
this.$nextTick(function () {
console.log('$nextTick中打印:', this.$el.children[0].innerText);
})
console.log('直接打印:', this.$el.children[0].innerText);
}
}
推薦大家使用Fundebug,一款很好用的BUG監控工具~
body {font-size:100%;}
h1 {font-size:3.75em;}
h2 {font-size:2.5em;}
p {font-size:0.875em;}
復制代碼
.aa{
background-image: url(arrow.png)no-repeat right center;
background-image:url(nav-bar.jpg);
background-repeat:no-repeat;
background-position:right center;
}
復制代碼
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
復制代碼
我自己是一名從事了多年開發的web前端老程序員,目前辭職在做自己的web前端私人定制課程,今年我花了一個月整理了一份最適合2020年學習的web前端學習干貨,各種框架都有整理,送給每一位前端小伙伴,想要獲取的可以關注我的頭條號并在后臺私信我:前端,即可免費獲取。
一蒙版出現禁止頁面滾動
1 window.onscroll=function(){
document.body.scrollTop = 0
};
2 $('html,body').animate({scrollTop:'0'},100);
$(".tan").bind('touchmove',function(e){ //禁止彈出框出來時進行滑動
e.preventDefault();
});
3 document.body.style.overflow='hidden';
若鍵盤點擊的話,就要加上:
var move=function(e){
e.preventDefault && e.preventDefault();
e.returnValue=false;
e.stopPropagation && e.stopPropagation();
return false;
}
var keyFunc=function(e){
if(37<=e.keyCode && e.keyCode<=40){
return move(e);
}
}
document.body.onkeydown=keyFunc;
復制代碼
var button=$(':button');
button.on('click',function(){
button.css('background-color','white');
$(this).css('background-color','#FB3336');
})
復制代碼
首先聲明一下:
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
然后
html,body {width:100%;height:100%;overflow-x:hidden;}
復制代碼
1.<body scoll=no> 全禁止
2.<body style="overflow:scroll;overflow-y:hidden"> 禁止縱向滾動條
3.<body style="overflow:scroll;overflow-x:hidden"> 禁止縱向滾動條
4.overflow屬性: 檢索或設置當對象的內容超過其指定高度及寬度時如何顯示內容
5.overflow: auto; 在需要時內容會自動添加滾動條
6.overflow: scroll; 總是顯示滾動條
7.overflow-x: hidden; 禁止橫向的滾動條
8.overflow-y: scroll; 總是顯示縱向滾動條
復制代碼
.mui-bar-nav{
-webkit-box-shadow: none;
box-shadow: none;
}
復制代碼
$(".shanchu").click(function(){
$(this).parent().remove()
})
復制代碼
需要對元素屬性的css的cursor進行設置
1、default 默認光標(通常是一個箭頭)
2、auto 默認。瀏覽器設置的光標。
3、crosshair 光標呈現為十字線。
4、pointer 光標呈現為指示鏈接的指針(一只手)
5、move 此光標指示某對象可被移動。
6、e-resize 此光標指示矩形框的邊緣可被向右(東)移動。
7、ne-resize 此光標指示矩形框的邊緣可被向上及向右移動(北/東)。
8、nw-resize 此光標指示矩形框的邊緣可被向上及向左移動(北/西)。
9、n-resize 此光標指示矩形框的邊緣可被向上(北)移動。
10、se-resize 此光標指示矩形框的邊緣可被向下及向右移動(南/東)。
11、sw-resize 此光標指示矩形框的邊緣可被向下及向左移動(南/西)。
12、s-resize 此光標指示矩形框的邊緣可被向下移動(南)。
13、w-resize 此光標指示矩形框的邊緣可被向左移動(西)。
14、text 此光標指示文本。
15、wait 此光標指示程序正忙(通常是一只表或沙漏)。
16、help 此光標指示可用的幫助(通常是一個問號或一個氣球)。
要實現鼠標移上去顯示手形、需要在你的提交按鈕上增加css cursor屬性,并將它的值設置為pointer;
如下:<input type="submit" name="submit" value="發布留言" class="subimt" onclick="display_alert()" style="cursor:pointer" />
復制代碼
$("#test tbody").html("");
復制代碼
var bv=$("#tabd tr").length-1;
$("#sp4").html(bv); //動態的獲取注數
復制代碼
$(".jixuan input[type=button]").toggle(function(){
$(this).css("background-color","yellow");
$(this).css("cursor","pointer")
},function(){
$(this).css("background-color","white");
$(this).css("cursor","pointer");
})
復制代碼
<input type="radio" name="gender" value="男" checked />
常用屬性迅美科技整理如下:
1.type="radio"
type屬性設置為radio,表示產生單一選擇的按鈕,讓用戶單擊選擇;
2.name="gender"
radio組件的名稱,name屬性值相同的radio組件會視為同一組radio組件,而同一組內只能有一個radio組件被選擇;
3.value="男"
radio組件的值,當表單被提交時,已選擇的radio組件的value值,就會被發送進行下一步處理, radio組件的value屬性設置的值
無法從外觀上看出,所以必須在radio組件旁邊添加文字,此處的文字只是讓用戶了解此組件的意思.
4.checked
設置radio組件為已選擇,同一組radio組件的name性情值必須要相同
復制代碼
1、<?php include("header.html");?>
2、使用ssi技術頁面生成shtml文件,只用在頭部文件位置加入<!--#include file="header.htm" -->,
然后修改的時候只要修改header.htm文件就可以了。使用shtml的好處是對搜索引擎比較友好,需要處理的文件在服務器端完成的,
不會加重訪問者的瀏覽器負擔。
復制代碼
if (window.location.hash.indexOf('#') >= 0) {
$('html,body').animate({
scrollTop: ($(window.location.hash).offset().top - 50) + "px"
},
300);
}; //主要修復評論定位不準確BUG
$('#comments a[href^=#][href!=#]').click(function() {
var target = document.getElementById(this.hash.slice(1));
if (!target) return;
var targetOffset = $(target).offset().top - 50;
$('html,body').animate({
scrollTop: targetOffset
},
300);
return false;
}); //主要修復評論定位不準確BUG
復制代碼
能用css自然不想用js解決,因為在加載方面,css總是先加載,并且速度很快。
typecho的評論HTML結構是這樣的:
<li id="comment-277" class="comment-body comment-child comment-level-odd comment-even comment-by-author">
我們給comment-body加上css
.comment-body {
position: relative;
padding-top: 50px;
margin-top: -50px;
}
/*修復評論跳轉定位問題*/
完美兼容chrome和Firefox,其他瀏覽器未測試。
復制代碼
.ovfHiden{overflow: hidden;height: 100%;}
$('.bzh .l1 a').click(function(){
$(".baok").show();
$(".baod").show();
$('html,body').addClass('ovfHiden');
});
$('.baod .img1').click(function(){
$('html,body').removeClass('ovfHiden');
$(".baok").hide();
$(".baod").hide();
});
復制代碼
$("#compute").click(function(){
$('input').live('click',function(){
//alert($('input:checked').length);
$("#show").html($('input:checked').length);
});
});
復制代碼
1.js
$('footer ul li').click(function(){
var index = $(this).index();
$(this).attr('class',"content").siblings('ul li').attr('class','ss');
$('.content').eq(index).show(200).siblings('.content').hide();
});
$('.ka ul li').click(function(){
var index = $(this).index();
$(this).attr('class',"zi").siblings('ul li').attr('class','ll');
$(this).parent().next().find(".zi").hide(). eq(index).show();
});
復制代碼
2.html
<div class="carindex-cnt">
<ul class="nav">
<li>續保方案</li>
<li>熱銷方案</li>
<li>自定義方案</li>
</ul>
<div class="tabcontent">
<div class="zi">
<p class="altp">此方案為您上一年的投保記錄</p>
<ul class="xiur">
<li>
<label for="saveType2">交強險</label>
<div class="right-cnt">
<input type="text" class="coverage" disabled="disabled" value="不投保"/>
<ul class="datas" style="display: none;">
<li ref="1">投保</li>
<li ref="2">不投保</li>
</ul>
</div>
</li>
<li>
<label for="saveType2">商業險</label>
<div class="right-cnt">
<input type="text" class="coverage" disabled="disabled" value="不投保"/>
<ul class="datas" style="display: none;">
<li ref="1">投保</li>
<li ref="2">不投保</li>
</ul>
</div>
</li>
</ul>
<p class="title">商業主險</p>
<ul class="xiur">
<li>
<span>車輛損失險</span>
<label for="abatement0" class="labels">
<input class="mui-checkbox checkbox-green" type="checkbox" name="abatement" >
</label>
<div class="right-cnt">
<input type="text" class="coverage" disabled="disabled" value="不投保"/>
<ul class="datas" style="display: none;">
<li ref="1">投保</li>
<li ref="2">不投保</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="zi" style="display: none">
<ul class="xiur">
<li>
<label for="saveType2">交強險</label>
<div class="right-cnt">
<input type="text" class="coverage" disabled="disabled" value="不投保"/>
<ul class="datas" style="display: none;">
<li ref="1">投保</li>
<li ref="2">不投保</li>
</ul>
</div>
</li>
<li>
<label for="saveType2">商業險</label>
<div class="right-cnt">
<input type="text" class="coverage" disabled="disabled" value="不投保"/>
<ul class="datas" style="display: none;">
<li ref="1">投保</li>
<li ref="2">不投保</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
</div>
復制代碼
3.js
$('.nav li').click(function () {
var index = $(this).index();
$(this).parent().next().find(".zi").hide().eq(index).show();
})
復制代碼
$(function(){
$('.main button').click(function(){
if(($('.ip1').val() !="") && ($('.ip2').val() !="")){
$('.main button').css('background','#ff8100');
$('.main button').attr('disabled', true);
}else{
$('.main button').css('background','#D0D0D0');
$('.main button').attr('disabled', false);
}
})
})
復制代碼
$(window).scroll(function(){
var scrollTop = $(this).scrollTop(); //滾動條距離頂部的高度
var scrollHeight =$(document).height(); //當前頁面的總高度
var windowHeight = $(this).height(); //當前可視的頁面高度
if(scrollTop + windowHeight >= scrollHeight){ //距離頂部+當前高度 >=文檔總高度 即代表滑動到底部
alert("上拉加載,要在這調用啥方法?");
}else if(scrollTop<=0){ //滾動條距離頂部的高度小于等于0
alert("下拉刷新,要在這調用啥方法?");
}
}); ——>移動端
$(function(){
$(window).scroll(function() {
var scrollTop = $(this).scrollTop(),scrollHeight = $(document).height(),windowHeight = $(this).height();
var positionValue = (scrollTop + windowHeight) - scrollHeight;
if (positionValue == 0) {
//do something
}
});
});
復制代碼
var obj;
var startx;
var starty;
var overx;
var overy;
for(var i=1;i<=$("li").length;i++){ //為每個li標簽添加事件
obj = document.getElementById(i); //獲取this元素
evenlistener(obj); //調用evenlistener函數并將dom元素傳入,為該元素綁定事件
}
function evenlistener(obj){
obj.addEventListener('touchstart', function(event) { //touchstart事件,當鼠標點擊屏幕時觸發
startx = event.touches[0].clientX; //獲取當前點擊位置x坐標
starty = event.touches[0].clientY; //獲取當前點擊位置y坐標
$(".sdf").text("x:"+startx+",y:"+starty+"") //賦值到頁面顯示
} , false); //false參數,設置事件處理機制的優先順序,具體不多說,true優先false
obj.addEventListener('touchmove', function(event) { //touchmove事件,當鼠標在屏幕移動時觸發
overx = event.touches[0].clientX; //獲取當前點擊位置x坐標
overy = event.touches[0].clientY; //獲取當前點擊位置y坐標
var $this = $(this); //將dom對象轉化為jq對象,由于項目用到jquery,直接使用其animate方法
if(startx-overx>10){ //左滑動判斷,當左滑動的距離大于開始的距離10進入
$($this).animate({marginLeft:"-55px"},150); //實現左滑動效果
}else if(overx-startx>10){ //右滑動判斷,當右滑動的距離大于開始的距離10進入
$($this).animate({marginLeft:"0px"},150); //恢復
}
} , false);
obj.addEventListener('touchend', function(event) { //touchend事件,當鼠標離開屏幕時觸發,項目中無用到,舉例
$(".sf").text("x:"+overx+",y:"+overy+"")
} , false);
}
復制代碼
var Sys = {};
var ua = navigator.userAgent.toLowerCase();
var s;
(s = ua.match(/rv:([\d.]+)\) like gecko/)) ? Sys.ie = s[1] :
(s = ua.match(/msie ([\d.]+)/)) ? Sys.ie = s[1] :
(s = ua.match(/firefox\/([\d.]+)/)) ? Sys.firefox = s[1] :
(s = ua.match(/chrome\/([\d.]+)/)) ? Sys.chrome = s[1] :
(s = ua.match(/opera.([\d.]+)/)) ? Sys.opera = s[1] :
(s = ua.match(/version\/([\d.]+).*safari/)) ? Sys.safari = s[1] : 0;
if (Sys.ie){
$("*").css({fontFamily:"微軟雅黑"});
};
if (window.ActiveXObject){
Sys.ie = ua.match(/msie ([\d.]+)/)[1];
if (Sys.ie<=9){
alert('你目前的IE版本為'+Sys.ie+'版本太低,請升級!');
location.href="http://windows.microsoft.com/zh-CN/internet-explorer/downloads/ie";
}
}
var UA=navigator.userAgent;
if(is360se = UA.toLowerCase().indexOf('360se')>-1 ){
}else{
$("*").css({fontFamily:"微軟雅黑"});
}
360瀏覽器基于IE內核的,360急速瀏覽器內核基于谷歌的
復制代碼
button,input type=button按鈕在IE和w3c,firefox瀏覽器區別:
1、當在IE瀏覽器下面時,button標簽按鈕,input標簽type屬性為button的按鈕是一樣的功能,不會對表單進行任何操作。
2、但是在W3C瀏覽器,如Firefox下就需要注意了,button標簽按鈕會提交表單,而input標簽type屬性為button不會對表單進行任何操作。
為button按鈕增加一個type=”button”屬性。
復制代碼
<textarea name="" id="sign" maxlength=30 onKeyUp="keypress1()"></textarea>
<div class="tish">
<span id="number">0</span><span>/30</span>
</div>
function keypress1() //text輸入長度處理
{
var text1=document.getElementById("sign").value;
var len=text1.length;
var show=len;
document.getElementById("number").innerText=show;
}
復制代碼
$('#ifrme').load(function(){
$('#ifrme').contents().find('.baod .img1').click(function(){
$(.ifrme').contents().find('.baod').hide();
$('.baok',window.parent.document).hide();
$('html,body',window.parent.document).removeClass('ovfHiden');
});
})
* .ifrme父頁面的ID為iframe的父級
.baod .img1是iframe頁面里的元素
復制代碼
$('.baod .bt1').click(function(){
$('.baod').hide();
$('.edit',window.parent.document).hide();
$(".baok", window.parent.document).hide();
$('html,body',window.parent.document).removeClass('ovfHiden');
});
*.baod .bt1子頁面里的元素
window.parent.document父級窗口
.edit父級頁面元素
復制代碼
$('.other .pg').click(function(){
$(this).toggleClass ("pots");
$('.below').slideToggle(300);
})
* .other .pg元素名稱
pots 點擊元素要切換的圖標(以background()形式的圖標)
.below要進行toggle的內容
復制代碼
$(".btnDel").click(function() {
//$(".box-mask").css({"display":"block"});
$(".box-mask").fadeIn(500);
center($(".box"));
//載入彈出窗口上的按鈕事件
checkEvent($(this).parent(), $(".btnSure"), $(".btnCancel"));
}); *center 彈框名稱
function center(obj) {
//obj這個參數是彈出框的整個對象
var screenWidth = $(window).width(), screenHeigth = $(window).height();
//獲取屏幕寬高
var scollTop = $(document).scrollTop();
//當前窗口距離頁面頂部的距離
var objLeft = (screenWidth - obj.width()) / 2;
///彈出框距離左側距離
var objTop = (screenHeigth - obj.height()) / 2 + scollTop;
///彈出框距離頂部的距離
obj.css({
left:objLeft + "px",
top:objTop + "px"
});
obj.fadeIn(500);
//彈出框淡入
isOpen = 1;
//彈出框打開后這個變量置1 說明彈出框是打開裝填
//當窗口大小發生改變時
$(window).resize(function() {
//只有isOpen狀態下才執行
if (isOpen == 1) {
//重新獲取數據
screenWidth = $(window).width();
screenHeigth = $(window).height();
var scollTop = $(document).scrollTop();
objLeft = (screenWidth - obj.width()) / 2;
var objTop = (screenHeigth - obj.height()) / 2 + scollTop;
obj.css({
left:objLeft + "px",
top:objTop + "px"
});
obj.fadeIn(500);
}
});
//當滾動條發生改變的時候
$(window).scroll(function() {
if (isOpen == 1) {
//重新獲取數據
screenWidth = $(window).width();
screenHeigth = $(window).height();
var scollTop = $(document).scrollTop();
objLeft = (screenWidth - obj.width()) / 2;
var objTop = (screenHeigth - obj.height()) / 2 + scollTop;
obj.css({
left:objLeft + "px",
top:objTop + "px"
});
obj.fadeIn(500);
}
});
復制代碼
css
:nth-child(odd){background-color:#FFE4C4;}奇數行
:nth-child(even){background-color:#F0F0F0;}偶數行
復制代碼
js
$("table tr:nth-child(even)").css("background-color","#FFE4C4"); //設置偶數行的背景色
$("table tr:nth-child(odd)").css("background-color","#F0F0F0"); //設置奇數行的背景色
復制代碼
jquery中的live()方法在jquery1.9及以上的版本中已被廢棄了,如果使用,會拋出TypeError: $(...).live is not a function錯誤。
解決方法:
之前的用法:
.live(events, function)
新方法:
.on(eventType, selector, function)
若selector不需要,可傳入null
例子1:
之前:
$('#mainmenu a').live('click', function)
之后:
$('#mainmenu').on('click', 'a', function)
例子2:
之前:
$('.myButton').live('click', function)
之后(應使用距離myButton最近的節點):
$('#parentElement').on('click', ‘.myButton’, function)
若不知最近的節點,可使用如下的方法:
$('body').on('click', ‘.myButton’, function)
復制代碼
iframe嵌入的滾動條可以用iframe里面頁面的大小覆蓋掉iframe的滾動條
復制代碼
<a class="downs" style="display:'+display+'" onclick="downimg(\''+list[i].skuTieTu+'\')">下載</a>
復制代碼
js方法
/**
* 圖片單獨下載
*/
function downimg(skuTieTu){
console.log(skuTieTu)
let src = skuTieTu;
var canvas = document.createElement('canvas');
var img = document.createElement('img');
img.onload = function(e) {
canvas.width = img.width;
canvas.height = img.height;
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0, img.width, img.height);
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
canvas.toBlob((blob)=>{
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'zzsp';
link.click();
}, "image/jpeg");
}
img.setAttribute("crossOrigin",'Anonymous');
img.src = src;
復制代碼
$.ajax({
type: "post",
data:
contentType:
url:
beforeSend: function () {
if(){
}else{
};
},
success: function (data) {
alert("保存失敗");
},
error: function (data) {
alert("保存成功");
}
});
復制代碼
$.ajax({
type:"post",
url: API,
data: {
'a':'project.kujiale.plan.YongliaoUser'
},
dataType: "json",
async: true,
beforeSend: function () {
layer.load(1);
},
success: function(data) {
var item =data.data;
list = item
if(data.code==0){
layer.closeAll();
var url = '/module/designplan/searchplan/searchlist.jsp';
layer.open({
type: 2,
title: "搜索方案",
shadeClose: true,
shade: 0.8,
area: ['700px','500px'],
content: [url]
});
}else{
layer.msg(data.msg);
}
}
});
復制代碼
jquery
$("a[id=search]").attr("data-search")
原生js
document.querySelector("a[id=search]").getAttribute("data-search") //根據當前元素的屬性獲取該元素其他屬性的值
document.querySelector("a[id=search]").text //根據當前屬性獲取該元素的值
document.querySelector("a[id=search]").innerText //根據當前屬性獲取該元素的值
復制代碼
JSON.stringify(userList)
復制代碼
layer.msg('分配成功',{time: 1000},function () {
var index = parent.layer.getFrameIndex(window.name);
parent.layer.close(index);
})
復制代碼
window.location.reload();//刷新當前頁面
window.parent.location.reload();//刷新父級頁面
復制代碼
download(data.data);
function downpdf(data){
var link = document.createElement('a');
link.href = data;
link.target = '_blank';
link.click();
delete link;
}
復制代碼
const isYoung = age => age < 25;
const message = msg => "He is "+ msg;
function isPersonOld(age, isYoung, message) {
const returnMessage = isYoung(age)?message("young"):message("old");
return returnMessage;
}
// passing functions as an arguments
console.log(isPersonOld(13,isYoung,message))
// He is young
復制代碼
遞歸是一種函數在滿足一定條件之前調用自身的技術。只要可能,最好使用遞歸而不是循環。你必須注意這一點,瀏覽器不能處理太多遞歸和拋出錯誤。
下面是一個演示遞歸的例子,在這個遞歸中,打印一個類似于樓梯的名稱。我們也可以使用for循環,但只要可能,我們更喜歡遞歸。
復制代碼
function printMyName(name, count) {
if(count <= name.length) {
console.log(name.substring(0,count));
printMyName(name, ++count);
}
}
console.log(printMyName("Bhargav", 1));
/*
B
Bh
Bha
Bhar
Bharg
Bharga
Bhargav
*/
// withotu recursion
var name = "Bhargav"
var output = "";
for(let i=0; i<name.length; i++) {
output = output + name[i];
console.log(output);
}
作者:山水有輕音
鏈接:https://juejin.im/post/6873003814065012750
*請認真填寫需求信息,我們會在24小時內與您取得聯系。