復(fù)制到瀏覽器即可使用,注意別忘了引入vue哦
<div id="app">
<div>{{pmsg}}</div>
<menu-item :title='ptitle' :content='ptitle'></menu-item>
</div>
<script type="text/javascript" src="vue.js"></script>
<script type="text/javascript">
//父組件向子組件傳值-基本使用
Vue.component('menu-item', {
props: ['title', 'content'],
data: function() {
return {
msg: '子組件本身的數(shù)據(jù)'
}
},
template: `<div>
<p>{{msg}}</p>
<p>{{title}}</p>
<p>{{content}}</p>
</div>`
});
var vm = new Vue({
el: '#app',
data: {
pmsg: '父組件中內(nèi)容',
ptitle: '動(dòng)態(tài)綁定屬性'
}
});
</script>
————————————————
版權(quán)聲明:本文為CSDN博主「溫柔的堅(jiān)持」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_43745003/article/details/104908639
前言
在學(xué)習(xí)JS中的原型,原型鏈,繼承這些知識之前,我們先學(xué)習(xí)下基礎(chǔ)知識:函數(shù)和對象的關(guān)系。
我們一直都知道,函數(shù)也是對象的一種,因?yàn)橥ㄟ^instanceof就可以判斷出來。但是函數(shù)和對象的關(guān)系并不是簡單的包含和被包含的關(guān)系,這兩者之間的關(guān)系還是有點(diǎn)復(fù)雜的。接下來我們就來捋一捋。
首先,闡述一點(diǎn),對象都是通過函數(shù)創(chuàng)建的
對于下面這種類型的代碼,一般叫做“語法糖”
var obj = {a:10,b:20};
var arr = [5, 'x', true];
但是,其實(shí)上面這段代碼的實(shí)質(zhì)是下面這樣的:
//var obj = { a: 10, b: 20 };
//var arr = [5, 'x', true];
var obj = new Object();
obj.a = 10;
obj.b = 20;
var arr = new Array();
arr[0] = 5;
arr[1] = 'x';
arr[2] = true;
function Fn() { }
Fn.prototype.name = '張三';
Fn.prototype.getAge = function () {
return 12;
};
var fn = new Fn();
console.log(fn.name);
console.log(fn.getAge ());
即,F(xiàn)n是一個(gè)函數(shù),fn對象是從Fn函數(shù)new出來的,這樣fn對象就可以調(diào)用Fn.prototype中的屬性。
但是,因?yàn)槊總€(gè)對象都有一個(gè)隱藏的屬性——“proto”,這個(gè)屬性引用了創(chuàng)建這個(gè)對象的函數(shù)的prototype。即:fn.proto === Fn.prototype
那么,這里的_proto_到底是什么呢?
其實(shí),這個(gè)__proto__是一個(gè)隱藏的屬性,javascript不希望開發(fā)者用到這個(gè)屬性值,有的低版本瀏覽器甚至不支持這個(gè)屬性值。
var obj = {};
console.log(obj.__proto__);

isPrototypeOf()函數(shù),用于檢測兩個(gè)對象之間似乎否存在原型關(guān)系,使用方法如下:
// 查看 Fn 的 prototype 對象,是否是 f 原型 Fn.prototype.isPrototypeOf(f);
//// 查看 f 對象是否是構(gòu)造函數(shù) Fn 的實(shí)例
//console.log(f instanceof Fn);
//// 查看 f 對象是否是構(gòu)造函數(shù) Fn 的實(shí)例
//console.log(f instanceof Object);
function Fn(){}
function Fun(){}
var f = new Fn();
console.log( f.__proto__ === Fn.prototype ); // t
console.log( Fn.prototype.isPrototypeOf(f) ); // t
console.log( Fun.prototype.isPrototypeOf(f) ); // f
console.log( Object.prototype.isPrototypeOf(f) ); // t
console.log( f instanceof Fn ); // t
console.log( f instanceof Fun ); // f
console.log( f instanceof Object ); // t
//兩種使用,如果是返回ture,如果不是返回false;
//注意:instanceof運(yùn)算符右側(cè)為構(gòu)造函數(shù),并且js中所有原型都來自O(shè)bject構(gòu)造函數(shù)。
JS解析器訪問屬性順序
當(dāng)訪問實(shí)例 f 的屬性或方法時(shí),會先在當(dāng)前實(shí)例對象 f 中查找,如果沒有,則沿著__proto__繼續(xù)向上尋找,如果找到最頂頭的Object還是找不到,則會拋出undefined。如果在實(shí)例中找到,或某層原型中找到,就會讀取并使用,同時(shí)停止向上找尋。
由此可見,解析器的解析順序遵循就近原則,如果在最近的位置發(fā)現(xiàn)屬性存在,便不會繼續(xù)向上找尋。
原型的應(yīng)用
數(shù)組去重:
Array.prototype.noRepeat = function(){
var m = [];
for(var i=0;i<this.length;i++){
if(m.indexOf(this[i]) == -1){
m.push(this[i]);
}
}
return m;
}
var arr = [3,4,5,6,7,6,5,4,3,2,1];
var res = arr.noRepeat();
console.log(res);
var arr1 = ["a","b","c","b","a"];
var res1 = arr1.noRepeat();
console.log(res1);
function Parent(){
}
Parent.prototype.show = function(){
console.log("哈哈哈");
}
function Child(){
}
for(var i in Parent.prototype){
Child.prototype[i] = Parent.prototype[i];
}
Child.prototype.show = function(){
console.log("hello");
}
var p = new Parent();
p.show();
console.log(p.name);
var c = new Child();
c.show();
console.log(c.name);
var newvue = new Vue()
觸發(fā)事件
newvue.$emit('自定義事件名', 參數(shù))
監(jiān)聽事件
newvue.on('自定義事件名', 觸發(fā)方法名)
銷毀事件
newvue.off('自定義事件名')
案例
放在html頁面上即可顯示,注意要引入vue
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div>父組件</div>
<div>
<button @click='handle'>銷毀事件</button>
</div>
<test-tom></test-tom>
<test-jerry></test-jerry>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
兄弟組件之間數(shù)據(jù)傳遞
*/
// 提供事件中心
var hub = new Vue();
Vue.component('test-tom', {
data: function(){
return {
num: 0
}
},
template: `
<div>
<div>TOM:{{num}}</div>
<div>
<button @click='handle'>點(diǎn)擊</button>
</div>
</div>
`,
methods: {
handle: function(){
hub.$emit('jerry-event', 2);
}
},
mounted: function() {
// 監(jiān)聽事件
hub.$on('tom-event', (val) => {
this.num += val;
});
}
});
Vue.component('test-jerry', {
data: function(){
return {
num: 0
}
},
template: `
<div>
<div>JERRY:{{num}}</div>
<div>
<button @click='handle'>點(diǎn)擊</button>
</div>
</div>
`,
methods: {
handle: function(){
// 觸發(fā)兄弟組件的事件
hub.$emit('tom-event', 1);
}
},
mounted: function() {
// 監(jiān)聽事件
hub.$on('jerry-event', (val) => {
this.num += val;
});
}
});
var vm = new Vue({
el: '#app',
data: {
},
methods: {
handle: function(){
hub.$off('tom-event');
hub.$off('jerry-event');
}
}
});
</script>
</body>
</html>
————————————————
版權(quán)聲明:本文為CSDN博主「溫柔的堅(jiān)持」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_43745003/article/details/104919633
環(huán)境準(zhǔn)備
創(chuàng)建項(xiàng)目
npx create-react-app my-react
進(jìn)入項(xiàng)目并啟動(dòng)
cd my-react && npm start
1
src/index.js
先把src里面的東西全部刪掉,重寫了index.js
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component{
render(){
return (
<div>Hellow, World</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
JSX
一個(gè)React組件中,render方法中return出去的內(nèi)容就是這個(gè)組件將要渲染的內(nèi)容,然后Babel 會把 JSX 轉(zhuǎn)譯成一個(gè)名為 React.createElement() 函數(shù)調(diào)用。
React.createElement(
'div',
{},
'Hello, World'
)
React.createElement() 接收三個(gè)參數(shù):
第一個(gè)參數(shù)是必填,傳入的是似HTML標(biāo)簽名稱: ul, li, div;
第二個(gè)參數(shù)是選填,表示的是屬性: className;
第三個(gè)參數(shù)是選填, 子節(jié)點(diǎn): 要顯示的文本內(nèi)容;
React.createElement() 會預(yù)先執(zhí)行一些檢查,以幫助你編寫無錯(cuò)代碼,但實(shí)際上它創(chuàng)建了一個(gè)這樣的對象:
// 注意:這是簡化過的結(jié)構(gòu)
const element = {
type: 'div',
props: {
className: '',
children: 'Hello, world!'
}
};
元素渲染
與瀏覽器的 DOM 元素不同,React 元素是創(chuàng)建開銷極小的普通對象。React DOM 會負(fù)責(zé)更新 DOM 來與 React 元素保持一致。
想要將一個(gè) React 元素渲染到根 DOM 節(jié)點(diǎn)中,只需把它們一起傳入 ReactDOM.render():
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));
render方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)為我們的 React 根級組件,第二個(gè)參數(shù)接收一個(gè) DOM 節(jié)點(diǎn),代表我們將把和 React 應(yīng)用掛載到這個(gè) DOM 節(jié)點(diǎn)下,進(jìn)而渲染到瀏覽器中。
組件 & props
組件,從概念上類似于 JavaScript 函數(shù)。它接受任意的入?yún)ⅲ?“props”),并返回用于描述頁面展示內(nèi)容的 React 元素。
函數(shù)組件:
function Welcome(props){
renter (
<h1> Hello, {props.name} </h1>
)
}
<Welcome name="World"/>
該函數(shù)是一個(gè)有效的 React 組件,因?yàn)樗邮瘴ㄒ粠в袛?shù)據(jù)的 “props”(代表屬性)對象與并返回一個(gè) React 元素。這類組件被稱為“函數(shù)組件”,因?yàn)樗举|(zhì)上就是 JavaScript 函數(shù)。
class組件:
class Welcome extends React.Component {
render(){
renter (
<h1> Hello, {thhis.props.name} </h1>
)
}
}
<Welcome name="World"/>
組件名稱必須以大寫字母開頭。
組件無論是使用函數(shù)聲明還是通過 class 聲明,都決不能修改自身的 props。
State & 生命周期
State 與 props 類似,但是 state 是私有的,并且完全受控于當(dāng)前組件。
class Clock extends React.Component {
constructor(props){
super(props)
this.state = {
date : new Date()
}
}
componentDidMount() {
//這里是Clock組件第一次被渲染到DOM時(shí)會調(diào)用,也就是掛載
}
componentWillUnmount() {
//當(dāng)DOM組件Clock被刪除時(shí),會調(diào)用,也就是卸載
}
render(){
return (
<div>
<h1>Hello, World</h1>
<h2>It's {this.state.date.toLocaleTimeString()}</h2>
</div>
)
}
}
修改state中數(shù)據(jù):
class Clock extends React.Component {
constructor(props){
super(props)
this.state = {
date: new Date()
}
}
componentDidMount() {
//這里是Clock組件第一次被渲染到DOM時(shí)會調(diào)用,也就是掛載
this.timer = setInterval(()=>{
this.tick()
},1000)
}
tick(){
this.setState({
date: new Date()
})
}
componentWillUnmount() {
//當(dāng)DOM組件Clock被刪除時(shí),會調(diào)用,也就是卸載
clearInterval(this.timer)
}
render(){
return (
<div>
<h1>Hello, World</h1>
<h2>It's {this.state.date.toLocaleTimeString()}</h2>
</div>
)
}
}
不要直接修改 State,構(gòu)造函數(shù)是唯一可以給 this.state 賦值的地方
this.setState({name: 'World'})
1
State 的更新可能是異步的,要解決這個(gè)問題,可以讓setState接受一個(gè)函數(shù)而不是一個(gè)對象,這個(gè)函數(shù)用上一個(gè) state 作為第一個(gè)參數(shù),將此次更新被應(yīng)用時(shí)的 props 做為第二個(gè)參數(shù):
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
事件處理
React 事件的命名采用小駝峰式(camelCase),而不是純小寫。
使用 JSX 語法時(shí)你需要傳入一個(gè)函數(shù)作為事件處理函數(shù),而不是一個(gè)字符串。
在 React 中一個(gè)不同點(diǎn)是你不能通過返回 false 的方式阻止默認(rèn)行為。你必須顯式的使用 preventDefault 。例如,傳統(tǒng)的 HTML 中阻止鏈接默認(rèn)打開一個(gè)新頁面,你可以這樣寫:
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
</a>
在 React 中,可能是這樣的:
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
class函數(shù)中綁定this
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 此語法確保 handleClick 內(nèi)的 this 已被綁定。
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}
在循環(huán)中,通常我們會為事件處理函數(shù)傳遞額外的參數(shù)
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
1
2
列表和key
function ListItem(props) {
return <li>{props.value}</li>;
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<ListItem key={number.toString()} value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
語法
在 JSX 中所有的屬性都要更換成駝峰式命名,比如 onclick 要改成 onClick,唯一比較特殊的就是 class,因?yàn)樵?JS 中 class 是保留字,我們要把 class 改成 className 。
這是一個(gè)最基本的左側(cè)菜單欄,實(shí)現(xiàn)的過程很簡單,官方的說明文檔就有,但是我在導(dǎo)入layer.js之后,直接復(fù)制這段官方代碼到我的編輯器上時(shí),發(fā)現(xiàn)頁面是這樣的:
發(fā)現(xiàn),綁定屬性的菜單并沒有下拉選項(xiàng),這個(gè)問題在我導(dǎo)入layer.all.js之后解決了,而且發(fā)現(xiàn)如果是在頁面的最上方導(dǎo)入的話也沒有下拉選項(xiàng),只有在html代碼下面導(dǎo)入,才可以顯示 ,不知道是什么原因。
頁面截圖:
tab項(xiàng)右鍵菜單:
這里右鍵菜單的樣式并沒有做太多的美化。
html代碼:(頁面中關(guān)于引入js和css文件的部分被我省略了,還有要注意jQuery的引入順序)
<div class="layui-tab layui-tab-card site-demo-button" style="position: relative;">
<ul class="layui-nav layui-nav-tree layui-nav-side">
<li class="layui-nav-item layui-nav-itemed">
<a href="javascript:;">默認(rèn)展開</a>
<dl class="layui-nav-child">
<dd>
<a data-url="a" data-id="11" data-title="選項(xiàng)a" href="#" class="site-demo-active" data-type="tabAdd">選項(xiàng)a</a>
</dd>
<dd>
<a href="#" data-url="b" data-title="選項(xiàng)b" data-id="22" class="site-demo-active" data-type="tabAdd">選項(xiàng)b</a>
</dd>
<dd>
<a href="">跳轉(zhuǎn)</a>
</dd>
</dl>
</li>
<li class="layui-nav-item">
<a href="javascript:;">解決方案</a>
<dl class="layui-nav-child">
<dd>
<a href="">移動(dòng)模塊</a>
</dd>
<dd>
<a href="">后臺模版</a>
</dd>
<dd>
<a href="">電商平臺</a>
</dd>
</dl>
</li>
<li class="layui-nav-item">
<a href="#" data-url="c" data-title="選項(xiàng)c" data-id="33" class="site-demo-active" data-type="tabAdd">產(chǎn)品c</a>
</li>
<li class="layui-nav-item">
<a href="">大數(shù)據(jù)</a>
</li>
</ul>
<div class="layui-tab" lay-filter="demo" lay-allowclose="true" style="margin-left: 200px;">
<ul class="layui-tab-title">
</ul>
<ul class="rightmenu" style="display: none;position: absolute;">
<li data-type="closethis">關(guān)閉當(dāng)前</li>
<li data-type="closeall">關(guān)閉所有</li>
</ul>
<div class="layui-tab-content">
</div>
</div>
</div>
js代碼:
layui.use('element', function() {
var $ = layui.jquery;
var element = layui.element; //Tab的切換功能,切換事件監(jiān)聽等,需要依賴element模塊
//觸發(fā)事件
var active = {
//在這里給active綁定幾項(xiàng)事件,后面可通過active調(diào)用這些事件
tabAdd: function(url,id,name) {
//新增一個(gè)Tab項(xiàng) 傳入三個(gè)參數(shù),分別對應(yīng)其標(biāo)題,tab頁面的地址,還有一個(gè)規(guī)定的id,是標(biāo)簽中data-id的屬性值
//關(guān)于tabAdd的方法所傳入的參數(shù)可看layui的開發(fā)文檔中基礎(chǔ)方法部分
element.tabAdd('demo', {
title: name,
content: '<iframe data-frameid="'+id+'" scrolling="auto" frameborder="0" src="'+url+'.html" style="width:100%;height:99%;"></iframe>',
id: id //規(guī)定好的id
})
CustomRightClick(id); //給tab綁定右擊事件
FrameWH(); //計(jì)算ifram層的大小
},
tabChange: function(id) {
//切換到指定Tab項(xiàng)
element.tabChange('demo', id); //根據(jù)傳入的id傳入到指定的tab項(xiàng)
},
tabDelete: function (id) {
element.tabDelete("demo", id);//刪除
}
, tabDeleteAll: function (ids) {//刪除所有
$.each(ids, function (i,item) {
element.tabDelete("demo", item); //ids是一個(gè)數(shù)組,里面存放了多個(gè)id,調(diào)用tabDelete方法分別刪除
})
}
};
//當(dāng)點(diǎn)擊有site-demo-active屬性的標(biāo)簽時(shí),即左側(cè)菜單欄中內(nèi)容 ,觸發(fā)點(diǎn)擊事件
$('.site-demo-active').on('click', function() {
var dataid = $(this);
//這時(shí)會判斷右側(cè).layui-tab-title屬性下的有l(wèi)ay-id屬性的li的數(shù)目,即已經(jīng)打開的tab項(xiàng)數(shù)目
if ($(".layui-tab-title li[lay-id]").length <= 0) {
//如果比零小,則直接打開新的tab項(xiàng)
active.tabAdd(dataid.attr("data-url"), dataid.attr("data-id"),dataid.attr("data-title"));
} else {
//否則判斷該tab項(xiàng)是否以及存在
var isData = false; //初始化一個(gè)標(biāo)志,為false說明未打開該tab項(xiàng) 為true則說明已有
$.each($(".layui-tab-title li[lay-id]"), function () {
//如果點(diǎn)擊左側(cè)菜單欄所傳入的id 在右側(cè)tab項(xiàng)中的lay-id屬性可以找到,則說明該tab項(xiàng)已經(jīng)打開
if ($(this).attr("lay-id") == dataid.attr("data-id")) {
isData = true;
}
})
if (isData == false) {
//標(biāo)志為false 新增一個(gè)tab項(xiàng)
active.tabAdd(dataid.attr("data-url"), dataid.attr("data-id"),dataid.attr("data-title"));
}
}
//最后不管是否新增tab,最后都轉(zhuǎn)到要打開的選項(xiàng)頁面上
active.tabChange(dataid.attr("data-id"));
});
function CustomRightClick(id) {
//取消右鍵 rightmenu屬性開始是隱藏的 ,當(dāng)右擊的時(shí)候顯示,左擊的時(shí)候隱藏
$('.layui-tab-title li').on('contextmenu', function () { return false; })
$('.layui-tab-title,.layui-tab-title li').click(function () {
$('.rightmenu').hide();
});
//桌面點(diǎn)擊右擊
$('.layui-tab-title li').on('contextmenu', function (e) {
var popupmenu = $(".rightmenu");
popupmenu.find("li").attr("data-id",id); //在右鍵菜單中的標(biāo)簽綁定id屬性
//判斷右側(cè)菜單的位置
l = ($(document).width() - e.clientX) < popupmenu.width() ? (e.clientX - popupmenu.width()) : e.clientX;
t = ($(document).height() - e.clientY) < popupmenu.height() ? (e.clientY - popupmenu.height()) : e.clientY;
popupmenu.css({ left: l, top: t }).show(); //進(jìn)行絕對定位
//alert("右鍵菜單")
return false;
});
}
$(".rightmenu li").click(function () {
//右鍵菜單中的選項(xiàng)被點(diǎn)擊之后,判斷type的類型,決定關(guān)閉所有還是關(guān)閉當(dāng)前。
if ($(this).attr("data-type") == "closethis") {
//如果關(guān)閉當(dāng)前,即根據(jù)顯示右鍵菜單時(shí)所綁定的id,執(zhí)行tabDelete
active.tabDelete($(this).attr("data-id"))
} else if ($(this).attr("data-type") == "closeall") {
var tabtitle = $(".layui-tab-title li");
var ids = new Array();
$.each(tabtitle, function (i) {
ids[i] = $(this).attr("lay-id");
})
//如果關(guān)閉所有 ,即將所有的lay-id放進(jìn)數(shù)組,執(zhí)行tabDeleteAll
active.tabDeleteAll(ids);
}
$('.rightmenu').hide(); //最后再隱藏右鍵菜單
})
function FrameWH() {
var h = $(window).height() -41- 10 - 60 -10-44 -10;
$("iframe").css("height",h+"px");
}
$(window).resize(function () {
FrameWH();
})
});
tab項(xiàng)是放在<div class="layui-tab" lay-filter="demo" lay-allowclose="true" style="margin-left: 200px;"> 這個(gè)div中的,其中有一個(gè)重要的屬性lay-filter,在js中調(diào)用的tabAdd,tabDelete等多種方法都攜帶了這個(gè)參數(shù),我對此的理解是相當(dāng)于一個(gè)判斷攔截功能,將tab項(xiàng)放在lay-filter=‘demo’的div中??梢越柚搮?shù),完成指定元素的局部更新。
其中還有關(guān)于element的操作,var element = layui.element
element模塊的實(shí)例
返回的element變量為該實(shí)例的對象,攜帶一些用于元素操作的基礎(chǔ)方法,我們就是用這些方法進(jìn)行tab項(xiàng)的新增和刪除還有切換。
這是element 中的tabAdd方法,其中的content可以是一個(gè)iframe頁面,在此例中,我就是傳遞了一個(gè)簡單的頁面,這就實(shí)現(xiàn)了不同頁面間的一些切換。
element.tabAdd('demo', {
title: '選項(xiàng)卡的標(biāo)題'
,content: '選項(xiàng)卡的內(nèi)容' //支持傳入html
,id: '選項(xiàng)卡標(biāo)題的lay-id屬性值'
});
————————————————
版權(quán)聲明:本文為CSDN博主「nb7474」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/nb7474/article/details/79413460/
要實(shí)現(xiàn)JavaScript的拖拽效果,首先我們需要知道事件對象幾個(gè)有關(guān)于實(shí)現(xiàn)拖拽效果的坐標(biāo)
獲取事件對象 var e = e || window.event;
根據(jù)需求需要用到的拖拽效果的坐標(biāo)
clientX:鼠標(biāo)點(diǎn)擊位置相對于瀏覽器可視區(qū)域的水平偏移量(不會計(jì)算水平滾動(dòng)的距離)
clientY:鼠標(biāo)點(diǎn)擊位置相對于瀏覽器可視區(qū)域的垂直偏移量(不會計(jì)算垂直滾動(dòng)條的距離)
offsetX:鼠標(biāo)點(diǎn)擊位置相對于觸發(fā)事件對象的水平距離
offsetY:鼠標(biāo)點(diǎn)擊位置相對于觸發(fā)事件對象的垂直距離
pageX:鼠標(biāo)點(diǎn)擊位置相對于網(wǎng)頁左上角的水平偏移量,也就是clientX加 上水平滾動(dòng)條的距離
pageY:鼠標(biāo)點(diǎn)擊位置相對于網(wǎng)頁左上角的垂直平偏移量,也就是clientY加上垂直滾動(dòng)條的距離
offsetLeft:如果父元素中有定位的元素,那么就返回距離當(dāng)前元素最近的定位元素邊緣的距離
offsetTop:如果父元素中沒有定位元素,那么就返回相對于body左邊緣距離
獲取元素自身大?。簅ffsetWidth和offsetHeight / clientWidth和clientHeight
offsetWidth和clientWidth的區(qū)別:就是offsetWidth包含邊框,clientWidth不包含邊框
實(shí)現(xiàn)拖拽需要用到:clientWidth、clientHeight、clientX、clientY、offsetLeft、offsetTop
首先搭建好html結(jié)構(gòu)和css樣式
<div class="wrap">
<div class="cover">
</div>
</div>
* {
margin: 0;
padding: 0;
}
.wrap {
width: 500px;
height: 500px;
border: 1px solid deeppink;
position: relative;
margin: 50px auto;
}
.cover {
width: 150px;
height: 150px;
background: rgba(200, 7, 99, 0.5);
display: none;
position: absolute;
left: 0;
top: 0;
cursor: move;
}
注意:需要給大盒子和小盒子進(jìn)行定位:子絕父相
<script>
var wrap = document.querySelector(".wrap");
var cover = document.querySelector(".cover");
wrap.onmouseover = function() {
cover.style.display = "block";
wrap.onmousemove = function(e) {
var e = e || window.event;
var x1 = e.clientX;
var y1 = e.clientY;
//這里獲取到的e.clientX和e.clientY,可以看情況和需求改為e.pageX和e.pageY
var halfWidth = cover.clientWidth / 2;
var halfHeight = cover.clientHeight / 2;
var wrapLeft = wrap.offsetLeft;
var wrapTop = wrap.offsetTop;
var l = x1 - wrapLeft - halfWidth;
var t = y1 - wrapTop - halfHeight;
if (l <= 0) {
l = 0
}
if (l >= wrap.clientWidth - cover.clientWidth) {
l = wrap.clientWidth - cover.clientWidth
}
if (t <= 0) {
t = 0
}
if (t >= wrap.clientHeight - cover.clientHeight) {
t = wrap.clientHeight - cover.clientHeight
}
cover.style.left = l + "px";
cover.style.top = t + "px"
}
}
wrap.onmouseout = function() {
cover.style.display = "none";
}
</script>
var halfWidth = cover.clientWidth / 2;
var halfHeight = cover.clientHeight / 2;
var wrapLeft = wrap.offsetLeft;
var wrapTop = wrap.offsetTop;
var l = x1 - wrapLeft - halfWidth;
var t = y1 - wrapTop - halfHeight;
//限制范圍
if (l <= 0) {
l = 0
}
if (l >= wrap.clientWidth - cover.clientWidth) {
l = wrap.clientWidth - cover.clientWidth
}
if (t <= 0) {
t = 0
}
if (t >= wrap.clientHeight - cover.clientHeight) {
t = wrap.clientHeight - cover.clientHeight
}
注意:這里要限制小盒子在大盒子之間移動(dòng)的范圍,左上角的限制,當(dāng)小盒子超出范圍時(shí),將0賦值給l和t。右下角小盒子移動(dòng)的范圍在大盒子寬度減去小盒子的寬度。
css面試題@響應(yīng)式布局如何實(shí)現(xiàn)
1為什么要使用響應(yīng)式布局
響應(yīng)式布局可以讓網(wǎng)站同時(shí)適配不同分辨率和不同的手機(jī)端,讓客戶有更好
的體驗(yàn)。
2如何實(shí)現(xiàn)
方案一:百分比布局
利用對屬性設(shè)置百分比來適配不同屏幕,注意這里的百分比是相對于父元素; 能夠設(shè)置的屬性有width,、height、padding、margin,其他屬性比如border、 font-size不能用百分比來設(shè)置的
由于沒辦法對font-size進(jìn)行百分比設(shè)置,所以用的最多就是對圖片和大塊布局進(jìn)行百分比設(shè)置。
方案二:使用媒體查詢 (CSS3@media 查詢)
利用媒體查詢設(shè)置不同分辨率下的css樣式,來適配不同屏幕。
媒體查詢相對于百分比布局,可以對布局進(jìn)行更細(xì)致的調(diào)整,但需要在每個(gè)分辨率下面都寫一套css樣式。
該布局的話適用于簡單的網(wǎng)頁,可以使移動(dòng)端和pc端使用一套網(wǎng)址。從而節(jié)約成本。也方便后期的維護(hù),bootcss就是用了CSS3的media來實(shí)現(xiàn)響應(yīng)的 但是相對于復(fù)雜的網(wǎng)頁就不適合了(如:淘寶,京東)等等
方案三.rem 響應(yīng)式布局
rem布局的原理
rem:相對于根元素(即html元素)font-size計(jì)算值的倍數(shù)。
如 html的font-size為100px;那么2rem就為200px。
通俗的來講的話rem就是通過JavaScript來獲取頁面的寬度,從而動(dòng)態(tài)的計(jì)算rem。這樣就會使不同分辨率下展現(xiàn)出相同的效果。
//代碼展示
css面試題@響應(yīng)式布局如何實(shí)現(xiàn) 1為什么要使用響應(yīng)式布局 響應(yīng)式布局可以讓網(wǎng)站同時(shí)適配不同分辨率和不同的手機(jī)端,讓客戶有更好 的體驗(yàn)。 2如何實(shí)現(xiàn) 方案一:百分比布局 利用對屬性設(shè)置百分比來適配不同屏幕,注意這里的百分比是相對于父元素; 能夠設(shè)置的屬性有width,、height、padding、margin,其他屬性比如border、 font-size不能用百分比來設(shè)置的 由于沒辦法對font-size進(jìn)行百分比設(shè)置,所以用的最多就是對圖片和大塊布局進(jìn)行百分比設(shè)置。 方案二:使用媒體查詢 (CSS3@media 查詢) 利用媒體查詢設(shè)置不同分辨率下的css樣式,來適配不同屏幕。 媒體查詢相對于百分比布局,可以對布局進(jìn)行更細(xì)致的調(diào)整,但需要在每個(gè)分辨率下面都寫一套css樣式。 該布局的話適用于簡單的網(wǎng)頁,可以使移動(dòng)端和pc端使用一套網(wǎng)址。從而節(jié)約成本。也方便后期的維護(hù),bootcss就是用了CSS3的media來實(shí)現(xiàn)響應(yīng)的 但是相對于復(fù)雜的網(wǎng)頁就不適合了(如:淘寶,京東)等等 方案三.rem 響應(yīng)式布局 rem布局的原理 rem:相對于根元素(即html元素)font-size計(jì)算值的倍數(shù)。 如 html的font-size為100px;那么2rem就為200px。 通俗的來講的話rem就是通過JavaScript來獲取頁面的寬度,從而動(dòng)態(tài)的計(jì)算rem。這樣就會使不同分辨率下展現(xiàn)出相同的效果。 //代碼展示上述代碼中 7.5為動(dòng)態(tài)的值,根據(jù)設(shè)計(jì)圖的寬度進(jìn)行動(dòng)態(tài)的改變。window.onresize的作用是:當(dāng)頁面的寬度或高度發(fā)生改變時(shí),再次進(jìn)行調(diào)用rem函數(shù)。
如何在網(wǎng)頁前端里可視化你的知識圖譜
最近費(fèi)盡千辛萬苦構(gòu)造了一份可以用(大概)的知識圖譜,并且把要利用知識圖譜做的領(lǐng)域命名實(shí)體識別和一些推薦的功能做成Web版的demo,順帶想實(shí)現(xiàn)一些可視化知識圖譜的功能。
(憑啥知識圖譜就只能在Neo4j里自嗨,不能來前端show一下,歧視嗎(¬_¬))
找了做前端圖表展示的開源庫,D3.js和Echarts都能做,我拿Echarts實(shí)現(xiàn)了一下功能,先看一下在現(xiàn)在項(xiàng)目里一個(gè)基于知識圖譜查詢的實(shí)際效果:

接下里看看如何的實(shí)現(xiàn):
<script src="/static/js/echarts.common.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts@4.5.0/dist/echarts.min.js"></script>
給要展示的圖準(zhǔn)備一個(gè)Dom:
<!-- 為ECharts準(zhǔn)備一個(gè)具備大小的Dom -->
<div class = "col-md-12">
<div class="panel panel-default ">
<header class="panel-heading">
關(guān)系圖 :
</header>
<div class = "panel-body ">
<div id="graph" style="width: 100%;height:600px;"></div>
</div>
</div>
</div>
data = [
{name:'蘋果',category:1,id:0},
{name:'梨子',catagory:1,id:1},
{name:'水果',category:2,id:2}
]
links = [
{source:0,target:2,category:0,value:'屬于',symbolSize:10},
{source:1,target:2,category:0,value:'屬于',symbolSize:10}
]
var myChart = echarts.init(document.getElementById('graph'));
option = {
title: {
text: ''
},
tooltip: {},
animationDurationUpdate: 1500,
animationEasingUpdate: 'quinticInOut',
label: {
normal: {
show: true,
textStyle: {
fontSize: 12
},
}
},
legend: {
x: "center",
show: false
},
series: [
{
type: 'graph',
layout: 'force',
symbolSize: 45,
focusNodeAdjacency: true,
roam: true,
edgeSymbol: ['none', 'arrow'],
categories: [{
name: '查詢實(shí)體',
itemStyle: {
normal: {
color: "#009800",
}
}
}, {
name: 'instance',
itemStyle: {
normal: {
color: "#4592FF",
}
}
}, {
name: 'class',
itemStyle: {
normal: {
color: "#C71585",
}
}
}],
label: {
normal: {
show: true,
textStyle: {
fontSize: 12,
},
}
},
force: {
repulsion: 1000
},
edgeSymbolSize: [4, 50],
edgeLabel: {
normal: {
show: true,
textStyle: {
fontSize: 10
},
formatter: "{c}"
}
},
data: data,
links: links,
lineStyle: {
normal: {
opacity: 0.9,
width: 1.3,
curveness: 0,
color:"#262626",
}
}
}
]
};
// 使用剛指定的配置項(xiàng)和數(shù)據(jù)顯示圖表。
myChart.setOption(option);
這樣就成功實(shí)現(xiàn)了一個(gè)簡單的圖譜可視化:
————————————————
版權(quán)聲明:本文為CSDN博主「游離態(tài)GLZ不可能是金融技術(shù)宅」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_37477357/article/details/104857495
1.實(shí)現(xiàn)注冊與登錄功能:
要求用到驗(yàn)證碼,登錄后該出不再顯示登錄與注冊,而是顯示用戶名。
2.實(shí)現(xiàn)預(yù)約功能:
實(shí)現(xiàn)“運(yùn)動(dòng)”與“學(xué)習(xí)”兩方面的邀約功能,并將邀約數(shù)據(jù)保存到數(shù)據(jù)庫中,數(shù)據(jù)庫使用Mysql。
運(yùn)動(dòng)可以邀約:籃球、足球、乒乓球等
學(xué)習(xí)可以邀約:自習(xí)、輔導(dǎo)等
在正式開始編碼之前,需要先導(dǎo)入相關(guān)jar包并配置好相關(guān)的配置文件,同時(shí)也需要導(dǎo)入前端給的頁面代碼。接著是建立好相應(yīng)的數(shù)據(jù)庫結(jié)構(gòu),并初步構(gòu)建好三層架構(gòu)的想法思路。

web層
service層
dao層
然后在這里寫一下對于驗(yàn)證碼處理和點(diǎn)擊圖片更換驗(yàn)證碼功能的一些細(xì)節(jié)。
如下圖所示,為了保證servlet層能夠正確接收到界面所展示的驗(yàn)證碼信息,同時(shí)因?yàn)閟ession對象是項(xiàng)目自生成的,所以我直接獲取session對象并以類似于鍵值對的形式將頁面驗(yàn)證碼信息存入session中。
接下來是jsp頁面對于驗(yàn)證碼展示的一些處理
在這里,因?yàn)辄c(diǎn)擊驗(yàn)證碼更換操作需要用到j(luò)s,所以我百度得到了上圖這樣一串代碼。其中時(shí)間戳的作用是通過改變每次請求的時(shí)間參數(shù)來獲得刷新效果,即改變url中的響應(yīng)頭信息。
2.注冊功能
事實(shí)上,有了登錄功能的實(shí)現(xiàn),注冊功能的代碼與其都是大同小異的。最大的不同應(yīng)該就是Dao層執(zhí)行的操作不同

預(yù)約功能的實(shí)現(xiàn)更是與注冊功能的實(shí)現(xiàn)基本一致。所不同的應(yīng)該是jsp頁面對單選框輸入的設(shè)置。
首先在寫代碼之前我們需要理清如何穿插圖片呢?
可以讓所有圖片都float:left,用一個(gè)大盒子裝進(jìn)所有圖片,在用一個(gè)小盒子顯示圖片,溢出圖片就hidden,之后以每張圖片的寬度來scrollLeft.
可以給每張圖片一個(gè)name/id,用循環(huán)遍歷所有圖片
可以用float:left,但是除了我要顯示的圖片外,其他圖片都hidden,之后每當(dāng)我需要某張圖片時(shí),我就把它制定到某位置
…
在這里,我將用第二種方法,因?yàn)樗苤庇^明了,我要哪張圖片我就調(diào)哪張圖片。
HTML部分:在div里面我裝了一張圖片,name:0, 這是為了在剛打開的時(shí)候,我們的頁面是有東西的而不是一片空白。其他部分都好理解,不理解的可在下方評論。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>輪播圖</title>
<link rel="stylesheet" href="輪播圖.css" />
<script src="輪播圖.js">
</script>
</head>
<body>
<header>
<div id="oImg">
<!-- 輪流播放圖片 -->
<img id="insert" src="img/輪1.jpg" name="0"/>
</div>
<!-- 左右切換圖片 -->
<p id="left" οnclick="goBack()"></p>
<p id="right" οnclick="goForward()"></p>
<ul id="nav">
<!-- 指定某張圖片 -->
<li id="1" οnclick="move(this)">1</li>
<li id="2" οnclick="move(this)">2</li>
<li id="3" οnclick="move(this)">3</li>
<li id="4" οnclick="move(this)">4</li>
<li id="5" οnclick="move(this)">5</li>
</ul>
</header>
</body>
</html>
CSS:
* { margin: 0 auto; padding: 0 auto; } header { width: 100%; height: 680px; position: relative; } img { width: 100%; height: 680px; } #nav { position: absolute; bottom: 5px; left: 30%; } #nav li { width: 30px; height: 30px; line-height: 30px; text-align: center; background: #ccc; font-size: 24px; border-radius: 9px; color: darkslategrey; font-family: 'Times New Roman', Times, serif; margin: 0 25px; float: left; cursor: pointer; list-style: none; } #nav li:hover { background: peru; } #left { width: 25px; height: 24px; left: 0; top: 50%; cursor: pointer; position: absolute; background: url(img/fx1.png); } #right { width: 25px; height: 24px; right: 0; top: 50%; cursor: pointer; position: absolute; background: url(img/fx2.png); }之后我們來看重中之重JS部分
JavaScript:
// 五張圖片的url var oImg1 = "img/輪1.jpg"; var oImg2 = "img/輪2.jpg"; var oImg3 = "img/輪3.jpg"; var oImg4 = "img/輪4.jpg"; var oImg5 = "img/輪5.jpg"; // 把5張圖片存入一個(gè)數(shù)組 var arr = [oImg1, oImg2, oImg3, oImg4, oImg5]; window.onload = function() { //剛加載時(shí)第一張圖片1號背景顏色 document.getElementById("1").style.background = "peru"; run() } //輪播 function run() { timer = setInterval(function() { //隨機(jī)點(diǎn)數(shù)字時(shí)能接著變化 var pic = document.getElementById("insert").name; var shade = document.getElementById("insert"); //如果為最后一張圖片則重新循環(huán) if (pic == 4) { pic = -1; } //點(diǎn)一個(gè)數(shù)字該數(shù)字背景顏色變化其余的不變 var aLi = document.getElementsByTagName("li"); for (var j = 0; j < aLi.length; j++) { aLi[j].style.backgroundColor = "#CCCCCC"; } var i = parseInt(pic); document.getElementById("insert").src = arr[i + 1]; document.getElementById("insert").name = i + 1; //數(shù)字隨圖片變化 switch (i) { case 0: var temp = '2'; break; case 1: var temp = '3'; break; case 2: var temp = '4'; break; case 3: var temp = '5'; break; case -1: var temp = '1'; break; } document.getElementById(temp).style.background = "peru" }, 5000) } //右箭頭 function goForward() { var temp = document.getElementById("insert").name; var oBox = document.getElementById("insert"); var aLi = document.getElementsByTagName("li"); // 數(shù)字跟著圖片一起變 for (var i = 0; i < aLi.length; i++) { aLi[i].style.backgroundColor = "#CCCCCC"; } switch (temp) { case "0": var n = '2'; break; case "1": var n = '3'; break; case "2": var n = '4'; break; case "3": var n = '5'; break; case "4": var n = '1'; break; } document.getElementById(n).style.background = "peru" // 向右移動(dòng)圖片 for (var j = 0; j < arr.length; j++) { if (j < 4) { if (temp == j) { oBox.src = arr[j + 1]; } } else { if (temp == 4) { oBox.src = arr[0]; } } } // 輪到最后一張圖片時(shí)返回第一張 if (temp < 4) { oBox.name = parseInt(temp) + 1; } else { oBox.name = 0; } } //左箭頭 function goBack() { var temp = document.getElementById("insert").name; var oBox = document.getElementById("insert") var aLi = document.getElementsByTagName("li"); // 圖片移動(dòng)時(shí)數(shù)字也跟著變 for (var i = 0; i < aLi.length; i++) { aLi[i].style.backgroundColor = "#CCCCCC"; } switch (temp) { case "0": var n = '5'; break; case "1": var n = '1'; break; case "2": var n = '2'; break; case "3": var n = '3'; break; case "4": var n = '4'; break; } document.getElementById(n).style.background = "peru" // 向左移動(dòng)圖片 for (var j = 0; j < arr.length; j++) { if (j > 0) { if (temp == j) { oBox.src = arr[j - 1]; } } else { if (temp == 0) { oBox.src = arr[4]; } } } // 輪到第一張圖片時(shí)返回最后一張 if (temp > 0) { oBox.name = parseInt(temp) - 1; } else { oBox.name = 4; } } //指定圖片 function move(num) { var oBox = document.getElementById("insert"); var temp = document.getElementById("insert").name; var aLi = document.getElementsByTagName("li"); for (var i = 0; i < aLi.length; i++) { aLi[i].style.backgroundColor = "#CCCCCC"; } document.getElementById(num.innerHTML).style.background = "peru" switch (num.innerHTML) { case "1": oBox.src = arr[0]; oBox.name = 0; break; case "2": oBox.src = arr[1]; oBox.name = 1; break; case "3": oBox.src = arr[2]; oBox.name = 2; break; case "4": oBox.src = arr[3]; oBox.name = 3; break; case "5": oBox.src = arr[4]; oBox.name = 4; break; } }JavaScript部分我寫的很詳細(xì),仔細(xì)看的話是可以看懂的,主要分3個(gè)重要部分:
用src來調(diào)用每張圖片并給每張圖片一個(gè)name,這樣方便后面的重復(fù)使用
為下方的數(shù)字按鈕匹配圖片,點(diǎn)擊1跳到第1張圖片,點(diǎn)擊2跳到第2張圖片…因?yàn)槲野阉械膱D片都存在了一個(gè)數(shù)組里,所以在匹配的時(shí)候要注意數(shù)組0位置才是數(shù)字1指定的圖片
可以來回翻頁,當(dāng)?shù)竭_(dá)最后一張圖片時(shí),我再點(diǎn)擊下一張圖片又能返回到第一張圖片了,亦或者當(dāng)我點(diǎn)擊到第一張圖片時(shí),再上一張圖片又回到第五張圖片了
效果如下:
大家有問題可以在下方評論哦,看到了會及時(shí)回復(fù)噠!
————————————————
版權(quán)聲明:本文為CSDN博主「weixin_43964414」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_43964414/article/details/104844041
藍(lán)藍(lán)設(shè)計(jì)的小編 http://m.wnxcall.com