好,下面我將結合一些實例,說一下我對組合模式以及觀察者模式的了解:
1、組合模式:
組合模式在對象間形成樹形結構;
組合模式中基本對象和組合對象被一致對待;
無須關心對象有多少層, 調用時只需在根部進行調用;
將多個對象的功能,組裝起來,實現批量執行;
想象我們現在手上有個萬能遙控器, 當我們回家, 按一下開關, 下列事情將被執行:
到家了,開門
開電腦
開音樂
// 先準備一些需要批量執行的功能 class GoHome{ init(){ console.log("到家了,開門"); } } class OpenComputer{ init(){ console.log("開電腦"); } } class OpenMusic{ init(){ console.log("開音樂"); } } // 組合器,用來組合功能 class Comb{ constructor(){ // 準備容器,用來防止將來組合起來的功能 this.skills = []; } // 用來組合的功能,接收要組合的對象 add(task){ // 向容器中填入,將來準備批量使用的對象 this.skills.push(task); } // 用來批量執行的功能 action(){ // 拿到容器中所有的對象,才能批量執行 this.skills.forEach( val => { val.init(); } ); } } // 創建一個組合器 var c = new Comb(); // 提前將,將來要批量操作的對象,組合起來 c.add( new GoHome() ); c.add( new OpenComputer() ); c.add( new OpenMusic() ); // 等待何時的時機,執行組合器的啟動功能 c.action(); // 在內部,會自動執行所有已經組合起來的對象的功能
由此,我們可以總結一下組合模式的特點
:
1.批量執行
2.啟動一個方法,會遍歷多個方法,同時執行,有點類似于遞歸的感覺
3.組合模式略微耗性能,但是執行方便
目前只是一個基礎組合。
高級組合:
1.組合成樹狀結構,每個對象下,還會有自己的子對象
2.如果執行了父對象的某個方法,所有的子對象會跟隨執行
3.組合模式一般建議使用在動態的html結構上,因為組合模式的結構和html的結構,出奇的一致
4.基本對象和組合對象被一致對待, 所以要保證基本對象(葉對象)和組合對象具有一致方法
2、觀察者模式:
觀察者模式也叫也叫Observer模式、訂閱/發布模式,也是由GoF提出的23種軟件設計模式的一種。
觀察者模式是行為模式之一,它的作用是當一個對象的狀態發生變化時,能夠自動通知其他關聯對象,自動刷新對象狀態,或者說執行對應對象的方法(主題數據改變,通知其他相關個體,做出相應的數據更新)。
這種設計模式可以大大降低程序模塊之間的耦合度,便于更加靈活的擴展和維護。
以觀察的角度,發現對應的狀況,處理問題。
觀察者模式包含兩種角色:
①觀察者(訂閱者):會隨時更新自身的信息或狀態(訂閱者可以隨時加入或離開);
②被觀察者(發布者):接收到發布者發布的信息,從而做出對應的改變或執行。
很方便的實現簡單的廣播通信,實現一對多的對應關系。
核心思想:觀察者只要訂閱了被觀察者的事件,那么當被觀察者的狀態改變時,被觀察者會主動去通知觀察者,而無需關心觀察者得到事件后要去做什么,實際程序中可能是執行訂閱者的回調函數。
Javascript中實現一個例子:
這是HTML學習總結系列的第二篇,第一篇在這里:
HTML 學習總結1入門 基本概念、格式 文字標簽 圖片標簽 鏈接標簽 表格標簽 注釋
這次的學習內容相較第一次分類少,但是比較雜。
框架集標簽
框架標簽是將網頁設置成網頁框架的一種雙標簽,被設計成框架的網頁被切分成若干區域,沒有實際的內容,只當做框架用于鑲嵌其它的網頁。
那么,這個標簽是:
<frameset></frameset>
框架集標簽的屬性
使用的時候需要將HTML文件中的body標簽部分替換為框架標簽,寫成這樣:
<html> <head></head> <frameset rows="500,*" border="3" noresize="noresize"> </frame> </html>看上面的代碼,用frameset替換掉body不難理解,畢竟我們約定做框架的網頁不具有實體內容 接著,這里提到了框架標簽的三個屬性,分別為: rows/cols 框架的分行或分列 border 分隔框的寬度 noresize 大小是否可調 現在來分別解釋一下 第一個,rows 或cols 屬性,代表了框架的分行或分列的情況,在引號內書寫該屬性的值的時候,不需要指明分成幾欄,只需要指明每一欄占據的寬度或高度(單位為像素)并使用逗號隔開。瀏覽器在解析的時候會計算到底分成了幾欄。另外,不指定寬度而使其占據剩余位置時,可以使用通配符 “ * ”。 第二個,border 屬性,代表了分隔框的寬度,這是屬性的數值單位是像素。所以如果你不想加入邊框,則可以將它設置為零。 第三個,noresize 屬性,表示我們的框架的大小是否可調,frameset標簽默認為大小可調,當用戶鼠標移動到邊框上時,他可以拖拽改變大小。所以如果不想讓用戶隨意改變框架大小,那么可以選擇使用這個屬性 (當然,也可以選擇把邊框的寬度設為零,讓他找不到)。 這個屬性的值同屬性名稱一樣。 最后還需要說明的是:框架集標簽是可以進行嵌套的,也就是說,在已經分出來的框架中,我們可以借著分欄。 在框架內鑲嵌網頁 剛剛我們使用 frameset 標簽將網頁變成框架并劃分成了若干區域,每一個區域都是一個單獨的可顯示頁面的子網頁(筆者起的名)?,F在,我們需要在這些區域內為它鑲嵌上一個網頁,這需要用到frame這個單標簽在框架下添加網頁,它的寫法如下: <frame src="...." name="...." /> 1 這里可以看到 frame 標簽的兩個屬性; src 和 name 。它們分別代表著添置連接(這是一個超鏈接,網頁,HTML文件,圖片等都是可以的。有關超鏈接的信息,可參照上一篇學習總結或者問問度娘 ),以及框架名稱。 框架的命名,很主要的一個原因在于可以重復利用一個框架,即在其他標簽使用時,可以在某個框架上顯示相應內容。還記得上一篇中,我們提到的鏈接標簽 target 屬性中的 “某框架名稱” 這個值嗎?在為框架命名后,就可以使用上述的 target 用法,將打開的網頁放在某個框架中了。 綜上,舉個例子: 先來創造一個帶有嵌套的框架<!--frame--> <html> <head></head> <frameset rows="200,*" border="5" noresize="noresize"> <frame src="title.html" name="title" /> <frameset cols="200,*"> <frame src="selection_bar.html" /> <frame name="output_page" /> </frameset> </frameset> </html><!--title--> <html> <head></head> <body> <font size="7" color="blue"> The test page </font> </body> </html>
<!--selection_bar--> <html> <head></head> <body> <font size="5" color="red"> Please select websites. </font> <br /><br /> <a target="output_page"/>百度一下<br /><br /> <a target="output_page"/>CSDN <br /><br /> </body> </html>
最后來看下結果:
復制到瀏覽器即可使用,注意別忘了引入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: '子組件本身的數據'
}
},
template: `<div>
<p>{{msg}}</p>
<p>{{title}}</p>
<p>{{content}}</p>
</div>`
});
var vm = new Vue({
el: '#app',
data: {
pmsg: '父組件中內容',
ptitle: '動態綁定屬性'
}
});
</script>
————————————————
版權聲明:本文為CSDN博主「溫柔的堅持」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_43745003/article/details/104908639
前言
在學習JS中的原型,原型鏈,繼承這些知識之前,我們先學習下基礎知識:函數和對象的關系。
我們一直都知道,函數也是對象的一種,因為通過instanceof就可以判斷出來。但是函數和對象的關系并不是簡單的包含和被包含的關系,這兩者之間的關系還是有點復雜的。接下來我們就來捋一捋。
首先,闡述一點,對象都是通過函數創建的
對于下面這種類型的代碼,一般叫做“語法糖”
var obj = {a:10,b:20}; var arr = [5, 'x', true];
但是,其實上面這段代碼的實質是下面這樣的:
//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 ());
即,Fn是一個函數,fn對象是從Fn函數new出來的,這樣fn對象就可以調用Fn.prototype中的屬性。
但是,因為每個對象都有一個隱藏的屬性——“proto”,這個屬性引用了創建這個對象的函數的prototype。即:fn.proto === Fn.prototype
那么,這里的_proto_到底是什么呢?
其實,這個__proto__是一個隱藏的屬性,javascript不希望開發者用到這個屬性值,有的低版本瀏覽器甚至不支持這個屬性值。
var obj = {}; console.log(obj.__proto__);
isPrototypeOf()函數,用于檢測兩個對象之間似乎否存在原型關系,使用方法如下:
// 查看 Fn 的 prototype 對象,是否是 f 原型 Fn.prototype.isPrototypeOf(f);
//// 查看 f 對象是否是構造函數 Fn 的實例 //console.log(f instanceof Fn); //// 查看 f 對象是否是構造函數 Fn 的實例 //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運算符右側為構造函數,并且js中所有原型都來自Object構造函數。
JS解析器訪問屬性順序
當訪問實例 f 的屬性或方法時,會先在當前實例對象 f 中查找,如果沒有,則沿著__proto__繼續向上尋找,如果找到最頂頭的Object還是找不到,則會拋出undefined。如果在實例中找到,或某層原型中找到,就會讀取并使用,同時停止向上找尋。
由此可見,解析器的解析順序遵循就近原則,如果在最近的位置發現屬性存在,便不會繼續向上找尋。
原型的應用
數組去重:
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()
觸發事件
newvue.$emit('自定義事件名', 參數)
監聽事件
newvue.on('自定義事件名', 觸發方法名)
銷毀事件
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"> /* 兄弟組件之間數據傳遞 */ // 提供事件中心 var hub = new Vue(); Vue.component('test-tom', { data: function(){ return { num: 0 } }, template: ` <div> <div>TOM:{{num}}</div> <div> <button @click='handle'>點擊</button> </div> </div> `, methods: { handle: function(){ hub.$emit('jerry-event', 2); } }, mounted: function() { // 監聽事件 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'>點擊</button> </div> </div> `, methods: { handle: function(){ // 觸發兄弟組件的事件 hub.$emit('tom-event', 1); } }, mounted: function() { // 監聽事件 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>————————————————
版權聲明:本文為CSDN博主「溫柔的堅持」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_43745003/article/details/104919633
這是一個最基本的左側菜單欄,實現的過程很簡單,官方的說明文檔就有,但是我在導入layer.js之后,直接復制這段官方代碼到我的編輯器上時,發現頁面是這樣的:
發現,綁定屬性的菜單并沒有下拉選項,這個問題在我導入layer.all.js之后解決了,而且發現如果是在頁面的最上方導入的話也沒有下拉選項,只有在html代碼下面導入,才可以顯示 ,不知道是什么原因。
頁面截圖:
tab項右鍵菜單:
這里右鍵菜單的樣式并沒有做太多的美化。
html代碼:(頁面中關于引入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:;">默認展開</a> <dl class="layui-nav-child"> <dd> <a data-url="a" data-id="11" data-title="選項a" href="#" class="site-demo-active" data-type="tabAdd">選項a</a> </dd> <dd> <a href="#" data-url="b" data-title="選項b" data-id="22" class="site-demo-active" data-type="tabAdd">選項b</a> </dd> <dd> <a href="">跳轉</a> </dd> </dl> </li> <li class="layui-nav-item"> <a href="javascript:;">解決方案</a> <dl class="layui-nav-child"> <dd> <a href="">移動模塊</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="選項c" data-id="33" class="site-demo-active" data-type="tabAdd">產品c</a> </li> <li class="layui-nav-item"> <a href="">大數據</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">關閉當前</li> <li data-type="closeall">關閉所有</li> </ul> <div class="layui-tab-content"> </div> </div> </div>js代碼:
layui.use('element', function() { var $ = layui.jquery; var element = layui.element; //Tab的切換功能,切換事件監聽等,需要依賴element模塊 //觸發事件 var active = { //在這里給active綁定幾項事件,后面可通過active調用這些事件 tabAdd: function(url,id,name) { //新增一個Tab項 傳入三個參數,分別對應其標題,tab頁面的地址,還有一個規定的id,是標簽中data-id的屬性值 //關于tabAdd的方法所傳入的參數可看layui的開發文檔中基礎方法部分 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 //規定好的id }) CustomRightClick(id); //給tab綁定右擊事件 FrameWH(); //計算ifram層的大小 }, tabChange: function(id) { //切換到指定Tab項 element.tabChange('demo', id); //根據傳入的id傳入到指定的tab項 }, tabDelete: function (id) { element.tabDelete("demo", id);//刪除 } , tabDeleteAll: function (ids) {//刪除所有 $.each(ids, function (i,item) { element.tabDelete("demo", item); //ids是一個數組,里面存放了多個id,調用tabDelete方法分別刪除 }) } }; //當點擊有site-demo-active屬性的標簽時,即左側菜單欄中內容 ,觸發點擊事件 $('.site-demo-active').on('click', function() { var dataid = $(this); //這時會判斷右側.layui-tab-title屬性下的有lay-id屬性的li的數目,即已經打開的tab項數目 if ($(".layui-tab-title li[lay-id]").length <= 0) { //如果比零小,則直接打開新的tab項 active.tabAdd(dataid.attr("data-url"), dataid.attr("data-id"),dataid.attr("data-title")); } else { //否則判斷該tab項是否以及存在 var isData = false; //初始化一個標志,為false說明未打開該tab項 為true則說明已有 $.each($(".layui-tab-title li[lay-id]"), function () { //如果點擊左側菜單欄所傳入的id 在右側tab項中的lay-id屬性可以找到,則說明該tab項已經打開 if ($(this).attr("lay-id") == dataid.attr("data-id")) { isData = true; } }) if (isData == false) { //標志為false 新增一個tab項 active.tabAdd(dataid.attr("data-url"), dataid.attr("data-id"),dataid.attr("data-title")); } } //最后不管是否新增tab,最后都轉到要打開的選項頁面上 active.tabChange(dataid.attr("data-id")); }); function CustomRightClick(id) { //取消右鍵 rightmenu屬性開始是隱藏的 ,當右擊的時候顯示,左擊的時候隱藏 $('.layui-tab-title li').on('contextmenu', function () { return false; }) $('.layui-tab-title,.layui-tab-title li').click(function () { $('.rightmenu').hide(); }); //桌面點擊右擊 $('.layui-tab-title li').on('contextmenu', function (e) { var popupmenu = $(".rightmenu"); popupmenu.find("li").attr("data-id",id); //在右鍵菜單中的標簽綁定id屬性 //判斷右側菜單的位置 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(); //進行絕對定位 //alert("右鍵菜單") return false; }); } $(".rightmenu li").click(function () { //右鍵菜單中的選項被點擊之后,判斷type的類型,決定關閉所有還是關閉當前。 if ($(this).attr("data-type") == "closethis") { //如果關閉當前,即根據顯示右鍵菜單時所綁定的id,執行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"); }) //如果關閉所有 ,即將所有的lay-id放進數組,執行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項是放在<div class="layui-tab" lay-filter="demo" lay-allowclose="true" style="margin-left: 200px;"> 這個div中的,其中有一個重要的屬性lay-filter,在js中調用的tabAdd,tabDelete等多種方法都攜帶了這個參數,我對此的理解是相當于一個判斷攔截功能,將tab項放在lay-filter=‘demo’的div中??梢越柚搮?,完成指定元素的局部更新。
其中還有關于element的操作,var element = layui.element
element模塊的實例
返回的element變量為該實例的對象,攜帶一些用于元素操作的基礎方法,我們就是用這些方法進行tab項的新增和刪除還有切換。
這是element 中的tabAdd方法,其中的content可以是一個iframe頁面,在此例中,我就是傳遞了一個簡單的頁面,這就實現了不同頁面間的一些切換。
element.tabAdd('demo', { title: '選項卡的標題' ,content: '選項卡的內容' //支持傳入html ,id: '選項卡標題的lay-id屬性值' });
————————————————
版權聲明:本文為CSDN博主「nb7474」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/nb7474/article/details/79413460/
要實現JavaScript的拖拽效果,首先我們需要知道事件對象幾個有關于實現拖拽效果的坐標
獲取事件對象 var e = e || window.event;
根據需求需要用到的拖拽效果的坐標
clientX:鼠標點擊位置相對于瀏覽器可視區域的水平偏移量(不會計算水平滾動的距離)
clientY:鼠標點擊位置相對于瀏覽器可視區域的垂直偏移量(不會計算垂直滾動條的距離)
offsetX:鼠標點擊位置相對于觸發事件對象的水平距離
offsetY:鼠標點擊位置相對于觸發事件對象的垂直距離
pageX:鼠標點擊位置相對于網頁左上角的水平偏移量,也就是clientX加 上水平滾動條的距離
pageY:鼠標點擊位置相對于網頁左上角的垂直平偏移量,也就是clientY加上垂直滾動條的距離
offsetLeft:如果父元素中有定位的元素,那么就返回距離當前元素最近的定位元素邊緣的距離
offsetTop:如果父元素中沒有定位元素,那么就返回相對于body左邊緣距離
獲取元素自身大?。簅ffsetWidth和offsetHeight / clientWidth和clientHeight
offsetWidth和clientWidth的區別:就是offsetWidth包含邊框,clientWidth不包含邊框
實現拖拽需要用到:clientWidth、clientHeight、clientX、clientY、offsetLeft、offsetTop
首先搭建好html結構和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; }注意:需要給大盒子和小盒子進行定位:子絕父相
<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 }注意:這里要限制小盒子在大盒子之間移動的范圍,左上角的限制,當小盒子超出范圍時,將0賦值給l和t。右下角小盒子移動的范圍在大盒子寬度減去小盒子的寬度。
css面試題@響應式布局如何實現
1為什么要使用響應式布局
響應式布局可以讓網站同時適配不同分辨率和不同的手機端,讓客戶有更好
的體驗。
2如何實現
方案一:百分比布局
利用對屬性設置百分比來適配不同屏幕,注意這里的百分比是相對于父元素; 能夠設置的屬性有width,、height、padding、margin,其他屬性比如border、 font-size不能用百分比來設置的
由于沒辦法對font-size進行百分比設置,所以用的最多就是對圖片和大塊布局進行百分比設置。
方案二:使用媒體查詢 (CSS3@media 查詢)
利用媒體查詢設置不同分辨率下的css樣式,來適配不同屏幕。
媒體查詢相對于百分比布局,可以對布局進行更細致的調整,但需要在每個分辨率下面都寫一套css樣式。
該布局的話適用于簡單的網頁,可以使移動端和pc端使用一套網址。從而節約成本。也方便后期的維護,bootcss就是用了CSS3的media來實現響應的 但是相對于復雜的網頁就不適合了(如:淘寶,京東)等等
方案三.rem 響應式布局
rem布局的原理
rem:相對于根元素(即html元素)font-size計算值的倍數。
如 html的font-size為100px;那么2rem就為200px。
通俗的來講的話rem就是通過JavaScript來獲取頁面的寬度,從而動態的計算rem。這樣就會使不同分辨率下展現出相同的效果。
//代碼展示
css面試題@響應式布局如何實現 1為什么要使用響應式布局 響應式布局可以讓網站同時適配不同分辨率和不同的手機端,讓客戶有更好 的體驗。 2如何實現 方案一:百分比布局 利用對屬性設置百分比來適配不同屏幕,注意這里的百分比是相對于父元素; 能夠設置的屬性有width,、height、padding、margin,其他屬性比如border、 font-size不能用百分比來設置的 由于沒辦法對font-size進行百分比設置,所以用的最多就是對圖片和大塊布局進行百分比設置。 方案二:使用媒體查詢 (CSS3@media 查詢) 利用媒體查詢設置不同分辨率下的css樣式,來適配不同屏幕。 媒體查詢相對于百分比布局,可以對布局進行更細致的調整,但需要在每個分辨率下面都寫一套css樣式。 該布局的話適用于簡單的網頁,可以使移動端和pc端使用一套網址。從而節約成本。也方便后期的維護,bootcss就是用了CSS3的media來實現響應的 但是相對于復雜的網頁就不適合了(如:淘寶,京東)等等 方案三.rem 響應式布局 rem布局的原理 rem:相對于根元素(即html元素)font-size計算值的倍數。 如 html的font-size為100px;那么2rem就為200px。 通俗的來講的話rem就是通過JavaScript來獲取頁面的寬度,從而動態的計算rem。這樣就會使不同分辨率下展現出相同的效果。 //代碼展示上述代碼中 7.5為動態的值,根據設計圖的寬度進行動態的改變。window.onresize的作用是:當頁面的寬度或高度發生改變時,再次進行調用rem函數。
如何在網頁前端里可視化你的知識圖譜
最近費盡千辛萬苦構造了一份可以用(大概)的知識圖譜,并且把要利用知識圖譜做的領域命名實體識別和一些推薦的功能做成Web版的demo,順帶想實現一些可視化知識圖譜的功能。
(憑啥知識圖譜就只能在Neo4j里自嗨,不能來前端show一下,歧視嗎(¬_¬))
找了做前端圖表展示的開源庫,D3.js和Echarts都能做,我拿Echarts實現了一下功能,先看一下在現在項目里一個基于知識圖譜查詢的實際效果:
接下里看看如何的實現:
<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>給要展示的圖準備一個Dom:
<!-- 為ECharts準備一個具備大小的Dom --> <div class = "col-md-12"> <div class="panel panel-default "> <header class="panel-heading"> 關系圖 : </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: '查詢實體', 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", } } } ] }; // 使用剛指定的配置項和數據顯示圖表。 myChart.setOption(option);這樣就成功實現了一個簡單的圖譜可視化:
————————————————
版權聲明:本文為CSDN博主「游離態GLZ不可能是金融技術宅」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_37477357/article/details/104857495
1.實現注冊與登錄功能:
要求用到驗證碼,登錄后該出不再顯示登錄與注冊,而是顯示用戶名。
2.實現預約功能:
實現“運動”與“學習”兩方面的邀約功能,并將邀約數據保存到數據庫中,數據庫使用Mysql。
運動可以邀約:籃球、足球、乒乓球等
學習可以邀約:自習、輔導等
在正式開始編碼之前,需要先導入相關jar包并配置好相關的配置文件,同時也需要導入前端給的頁面代碼。接著是建立好相應的數據庫結構,并初步構建好三層架構的想法思路。
web層
service層
dao層
然后在這里寫一下對于驗證碼處理和點擊圖片更換驗證碼功能的一些細節。
如下圖所示,為了保證servlet層能夠正確接收到界面所展示的驗證碼信息,同時因為session對象是項目自生成的,所以我直接獲取session對象并以類似于鍵值對的形式將頁面驗證碼信息存入session中。
接下來是jsp頁面對于驗證碼展示的一些處理
在這里,因為點擊驗證碼更換操作需要用到js,所以我百度得到了上圖這樣一串代碼。其中時間戳的作用是通過改變每次請求的時間參數來獲得刷新效果,即改變url中的響應頭信息。
2.注冊功能
事實上,有了登錄功能的實現,注冊功能的代碼與其都是大同小異的。最大的不同應該就是Dao層執行的操作不同
預約功能的實現更是與注冊功能的實現基本一致。所不同的應該是jsp頁面對單選框輸入的設置。
藍藍設計的小編 http://axecq.cn