首頁

JavaScript版數(shù)據(jù)結(jié)構(gòu)與算法——基礎篇(一)

前端達人

數(shù)組

數(shù)組——最簡單的內(nèi)存數(shù)據(jù)結(jié)構(gòu)

數(shù)組存儲一系列同一種數(shù)據(jù)類型的值。( Javascript 中不存在這種限制)

對數(shù)據(jù)的隨機訪問,數(shù)組是更好的選擇,否則幾乎可以完全用 「鏈表」 來代替

在很多編程語言中,數(shù)組的長度是固定的,當數(shù)組被填滿時,再要加入新元素就很困難。Javascript 中數(shù)組不存在這個問題。

但是 Javascript 中的數(shù)組被實現(xiàn)成了對象,與其他語言相比,效率低下。

數(shù)組的一些核心方法

方法 描述
push 方法將一個或多個元素添加到數(shù)組的末尾,并返回該數(shù)組的新長度。(改變原數(shù)組)
pop 方法從數(shù)組中刪除最后一個元素,并返回該元素的值。(改變原數(shù)組)
shift 方法從數(shù)組中刪除第一個元素,并返回該元素的值,如果數(shù)組為空則返回 undefined 。(改變原數(shù)組)
unshift 將一個或多個元素添加到數(shù)組的開頭,并返回該數(shù)組的新長度(改變原數(shù)組)
concat 連接兩個或多個數(shù)組,并返回結(jié)果(返回一個新數(shù)組,不影響原有的數(shù)組。)
every 對數(shù)組中的每個元素運行給定函數(shù),如果該函數(shù)對每個元素都返回 true,則返回 true。若為一個空數(shù)組,,始終返回 true。 (不會改變原數(shù)組,[].every(callback)始終返回 true)
some 對數(shù)組中的每個元素運行給定函數(shù),如果任一元素返回 true,則返回 true。若為一個空數(shù)組,,始終返回 false。(不會改變原數(shù)組,)
forEach 對數(shù)組中的每個元素運行給定函數(shù)。這個方法沒有返回值,沒有辦法中止或者跳出 forEach() 循環(huán),除了拋出一個異常(foreach不直接改變原數(shù)組,但原數(shù)組可能會被 callback 函數(shù)該改變。)
map 對數(shù)組中的每個元素運行給定函數(shù),返回每次函數(shù)調(diào)用的結(jié)果組成的數(shù)組(map不直接改變原數(shù)組,但原數(shù)組可能會被 callback 函數(shù)該改變。)
sort 按照Unicode位點對數(shù)組排序,支持傳入指定排序方法的函數(shù)作為參數(shù)(改變原數(shù)組)
reverse 方法將數(shù)組中元素的位置顛倒,并返回該數(shù)組(改變原數(shù)組)
join 將所有的數(shù)組元素連接成一個字符串
indexOf 返回第一個與給定參數(shù)相等的數(shù)組元素的索引,沒有找到則返回 -1
lastIndexOf 返回在數(shù)組中搜索到的與給定參數(shù)相等的元素的索引里最大的值,沒有找到則返回 -1
slice 傳入索引值,將數(shù)組里對應索引范圍內(nèi)的元素(淺復制原數(shù)組中的元素)作為新數(shù)組返回(原始數(shù)組不會被改變)
splice 刪除或替換現(xiàn)有元素或者原地添加新的元素來修改數(shù)組,并以數(shù)組形式返回被修改的內(nèi)容(改變原數(shù)組)
toString 將數(shù)組作為字符串返回
valueOf 和 toString 類似,將數(shù)組作為字符串返回

是一種遵循后進先出(LIFO)原則的有序集合,新添加或待刪除的元素都保存在棧的同一端,稱作棧頂,另一端就叫棧底。在棧里,新元素都靠近棧頂,舊元素都接近棧底。

通俗來講,就是你向一個桶里放書本或者盤子,你要想取出最下面的書或者盤子,你必須要先把上面的都先取出來。

棧也被用在編程語言的編譯器和內(nèi)存中保存變量、方法調(diào)用等,也被用于瀏覽器歷史記錄 (瀏覽器的返回按鈕)。

代碼實現(xiàn)

// 封裝棧
    function Stack() {
        // 棧的屬性
        this.items = []

        // 棧的操作
        // 1.將元素壓入棧
        Stack.prototype.push = function (element) {
            this.items.push(element)
        }
        // 2.從棧中取出元素
        Stack.prototype.pop = function () {
            return this.items.pop()
        }
        // 3.查看棧頂元素
        Stack.prototype.peek = function () {
            return this.items[this.items.length - 1]
        }
        // 4.判斷是否為空
        Stack.prototype.isEmpty = function () {
            return this.items.length === 0
        }
        // 5.獲取棧中元素的個數(shù)
        Stack.prototype.size = function () {
            return this.items.length
        }
        // 6.toString()方法
        Stack.prototype.toString = function () {
            let str = ''
            for (let i = 0; i< this.items.length; i++) {
                str += this.items[i] + ' '
            }
            return str
        }

    }

    // 棧的使用
    let s = new Stack()

隊列

隊列是遵循先進先出(FIFO,也稱為先來先服務)原則的一組有序的項。隊列在尾部添加新
元素,并從頂部移除元素。添加的元素必須排在隊列的末尾。

生活中常見的就是排隊

代碼實現(xiàn)

function Queue() {
        this.items = []
        // 1.將元素加入隊列
        Queue.prototype.enqueue = function (element) {
            this.items.push(element)
        }
        // 2.從隊列前端刪除元素
        Queue.prototype.dequeue = function () {
            return this.items.shift()
        }
        // 3.查看隊列前端元素
        Queue.prototype.front = function () {
            return this.items[0]
        }
        // 4.判斷是否為空
        Queue.prototype.isEmpty = function () {
            return this.items.length === 0
        }
        // 5.獲取隊列中元素的個數(shù)
        Queue.prototype.size = function () {
            return this.items.length
        }
        // 6.toString()方法
        Queue.prototype.toString = function () {
            let str = ''
            for (let i = 0; i< this.items.length; i++) {
                str += this.items[i] + ' '
            }
            return str
        }
    }
    
    // 隊列使用
    let Q = new Queue()

優(yōu)先級隊列:

代碼實現(xiàn)


function PriorityQueue() {
        function QueueElement(element, priority) {
            this.element = element
            this.priority = priority
        }
        this.items = []

        PriorityQueue.prototype.enqueue = function (element, priority) {
            let queueElement = new QueueElement(element,priority)

            // 判斷隊列是否為空
            if (this.isEmpty()) {
                this.items.push(queueElement)
            } else {
                let added = false // 如果在隊列已有的元素中找到滿足條件的,則設為true,否則為false,直接插入隊列尾部
                for (let i = 0; i< this.items.length; i++) {
                    // 假設priority值越小,優(yōu)先級越高,排序越靠前
                    if (queueElement.priority < this.items[i].priority) {
                        this.items.splice(i, 0, queueElement)
                        added = true
                        break
                    }
                }
                if (!added) {
                    this.items.push(queueElement)
                }
            }

        }
        
    }
    

鏈表

鏈表——存儲有序的元素集合,但在內(nèi)存中不是連續(xù)放置的。


鏈表(單向鏈表)中的元素由存放元素本身「data」 的節(jié)點和一個指向下一個「next」 元素的指針組成。牢記這個特點

相比數(shù)組,鏈表添加或者移除元素不需要移動其他元素,但是需要使用指針。訪問元素每次都需要從表頭開始查找。

代碼實現(xiàn):
單向鏈表


function LinkedList() {
        function Node(data) {
            this.data = data
            this.next = null

        }
        this.head = null // 表頭
        this.length = 0
        // 插入鏈表
        LinkedList.prototype.append = function (data) {
            // 判斷是否是添加的第一個節(jié)點
            let newNode = new Node(data)
            if (this.length == 0) {
                this.head = newNode
            } else {
                let current = this.head
                while (current.next) { 
                // 如果next存在,
                // 則當前節(jié)點不是鏈表最后一個
                // 所以繼續(xù)向后查找
                    current = current.next
                }
                // 如果next不存在
                 // 則當前節(jié)點是鏈表最后一個
                // 所以讓next指向新節(jié)點即可
                current.next = newNode
            }
            this.length++
        }
        // toString方法
        LinkedList.prototype.toString = function () {
            let current = this.head
            let listString = ''
            while (current) {
                listString += current.data + ' '
                current = current.next
            }
            return listString
        }
         // insert 方法
        LinkedList.prototype.insert = function (position, data) {
            if (position < 0 || position > this.length) return false
            let newNode = new Node(data)
            if (position == 0) {
                newNode.next = this.head
                this.head = newNode
            } else {
                let index = 0
                let current = this.head
                let prev = null
                while (index++ < position) {
                    prev = current
                    current = current.next
                }
                newNode.next = current
                prev.next = newNode
            }
            this.length++
            return true
        }
        // get方法
        LinkedList.prototype.get = function (position) {
            if (position < 0 || position >= this.length) return null
            let index = 0
            let current = this.head
            while (index++ < position){
                current = current.next
            }
            return current.data
        }
        LinkedList.prototype.indexOf = function (data) {
            let index = 0
            let current = this.head
            while (current) {
                if (current.data == data) {
                    return index
                } else {
                    current = current.next
                    index++
                }
            }

            return  -1
        }
        LinkedList.prototype.update = function (position, data) {
            if (position < 0 || position >= this.length) return false
            let index = 0
            let current = this.head
            while (index++ < position) {
                current = current.next
            }
            current.data = data
            return  true
        }
        LinkedList.prototype.removeAt = function (position) {
            if (position < 0 || position >= this.length) return null
            if (position == 0) {
                this.head = this.head.next
            } else {
                let index = 0
                let current = this.head
                let prev = null
                while (index++ < position) {
                    prev = current
                    current = current.next
                }
                prev.next = current.next
            }
            this.length--
            return  true


        }
        LinkedList.prototype.remove = function (data) {
            let postions = this.indexOf(data)

            return this.removeAt(postions)
        }
        
    }

    let list = new LinkedList()
雙向鏈表:包含表頭、表尾 和 存儲數(shù)據(jù)的 節(jié)點,其中節(jié)點包含三部分:一個鏈向下一個元素的next, 另一個鏈向前一個元素的prev 和存儲數(shù)據(jù)的 data牢記這個特點

function doublyLinkedList() {
        this.head = null // 表頭:始終指向第一個節(jié)點,默認為 null
        this.tail = null // 表尾:始終指向最后一個節(jié)點,默認為 null
        this.length = 0 // 鏈表長度

        function Node(data) {
            this.data = data
            this.prev = null
            this.next = null
        }

        doublyLinkedList.prototype.append = function (data) {
            let newNode = new Node(data)

            if (this.length === 0) {
            // 當插入的節(jié)點為鏈表的第一個節(jié)點時
            // 表頭和表尾都指向這個節(jié)點
                this.head = newNode
                this.tail = newNode
            } else {
            // 當鏈表中已經(jīng)有節(jié)點存在時
            // 注意tail指向的始終是最后一個節(jié)點
            // 注意head指向的始終是第一個節(jié)點
            // 因為是雙向鏈表,可以從頭部插入新節(jié)點,也可以從尾部插入
            // 這里以從尾部插入為例,將新節(jié)點插入到鏈表最后
            // 首先將新節(jié)點的 prev 指向上一個節(jié)點,即之前tail指向的位置
                newNode.prev = this.tail
            // 然后前一個節(jié)點的next(及之前tail指向的節(jié)點)指向新的節(jié)點
            // 此時新的節(jié)點變成了鏈表的最后一個節(jié)點
                this.tail.next = newNode
            // 因為 tail 始終指向的是最后一個節(jié)點,所以最后修改tail的指向
                this.tail = newNode
            }
            this.length++
        }
        doublyLinkedList.prototype.toString = function () {
            return this.backwardString()
        }
        doublyLinkedList.prototype.forwardString = function () {
            let current = this.tail
            let str = ''

            while (current) {
                str += current.data + ''
                current = current.prev
            }

            return str
        }
        doublyLinkedList.prototype.backwardString = function () {
            let current = this.head
            let str = ''

            while (current) {
                str += current.data + ''
                current = current.next
            }

            return str
        }

        doublyLinkedList.prototype.insert = function (position, data) {
            if (position < 0 || position > this.length) return false
            let newNode = new Node(data)
            if (this.length === 0) {
                this.head = newNode
                this.tail = newNode
            } else {
                if (position == 0) {
                    this.head.prev = newNode
                    newNode.next = this.head
                    this.head = newNode
                } else if (position == this.length) {
                    newNode.prev = this.tail
                    this.tail.next = newNode
                    this.tail = newNode
                } else {
                    let current = this.head
                    let index = 0
                    while( index++ < position){
                        current = current.next
                    }
                    newNode.next = current
                    newNode.prev = current.prev
                    current.prev.next = newNode
                    current.prev = newNode

                }

            }

            this.length++
            return true
        }
        doublyLinkedList.prototype.get = function (position) {
            if (position < 0 || position >= this.length) return null
            let current = this.head
            let index = 0
            while (index++) {
                current = current.next
            }

            return current.data
        }
        doublyLinkedList.prototype.indexOf = function (data) {
            let current = this.head
            let index = 0
            while (current) {
                if (current.data === data) {
                    return index
                }
                current = current.next
                index++
            }
            return  -1
        }
        doublyLinkedList.prototype.update = function (position, newData) {
            if (position < 0 || position >= this.length) return false
            let current = this.head
            let index = 0
            while(index++ < position){
                current = current.next
            }
            current.data = newData
            return true
        }
        doublyLinkedList.prototype.removeAt = function (position) {
            if (position < 0 || position >= this.length) return null
            let current = this.head
            if (this.length === 1) {
                this.head = null
                this.tail = null
            } else {
                if (position === 0) { // 刪除第一個節(jié)點
                    this.head.next.prev = null
                    this.head = this.head.next
                } else if (position === this.length - 1) { // 刪除最后一個節(jié)點
                    this.tail.prev.next = null
                    this.tail = this.tail.prev
                } else {
                    let index = 0
                    while (index++ < position) {
                        current = current.next
                    }
                    current.prev.next = current.next
                    current.next.prev = current.prev
                }
            }
            this.length--
            return current.data
        }
        doublyLinkedList.prototype.remove = function (data) {
            let index = this.indexOf(data)
            return this.removeAt(index)
        }
    }


感謝你的閱讀~
————————————————
版權(quán)聲明:本文為CSDN博主「重慶崽兒Brand」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/brand2014/java/article/details/106134844



大數(shù)據(jù)可視化設計賞析(三)

前端達人

     如今大數(shù)據(jù)產(chǎn)業(yè)正在超出我們的想象悄然發(fā)展,而隨著大數(shù)據(jù)時代的到來,越來越多的公司開始意識到數(shù)據(jù)資源的管理和運用。今天就給大家介紹一些可視化大屏的UI設計。


點擊查看原圖

    --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

c24b7efe812270eb555c5ab24b8a5fa2626973621ab956-4LUO4k_fw658.gif

 --大屏UI設計--

eebdcf2ab80ccf28a832b463b5efb8d390baa8401fbcda-58EU2O_fw658.jpg


eee7b0bd72a92d26ef0ea8b65921a2fcacf49ae934f18-ScQnAI_fw658.png

f0ab44b8e812af72209891521cbff1fe6ff656b863d09-JxGZiR_fw658.jpg



f5c7bedb9779f20ca239e235a98ef8eae839a5f980e8a-gkXvyM_fw658.png

 --大屏UI設計--


點擊查看原圖

 --大屏UI設計--

TB2XULnmC0mpuFjSZPiXXbssVXa-680650857的副本.jpg

 --大屏UI設計--點擊查看原圖

 --大屏UI設計--點擊查看原圖

 --大屏UI設計--點擊查看原圖

 --大屏UI設計--點擊查看原圖

 --大屏UI設計--點擊查看原圖

 --大屏UI設計--點擊查看原圖

 --大屏UI設計--點擊查看原圖

 --大屏UI設計--WechatIMG166.jpeg

 --大屏UI設計--點擊查看原圖

 --大屏UI設計--點擊查看原圖

 --大屏UI設計--點擊查看原圖

 --大屏UI設計--點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

WechatIMG174.jpeg

 --大屏UI設計--

WechatIMG175.jpeg

 --大屏UI設計--

WechatIMG164.jpeg

 --大屏UI設計--

WechatIMG176.jpeg

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

點擊查看原圖

 --大屏UI設計--

(以上圖片均來自于網(wǎng)絡)


其實可視化大屏的UI設計并不只是一個簡單的設計,其核心就是要以展示數(shù)據(jù)為核心,不管在多么炫目的情況下都不會影響數(shù)據(jù)的展示。


  藍藍設計m.sillybuy.com )是一家專注而深入的界面設計公司,為期望卓越的國內(nèi)外企業(yè)提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網(wǎng)站建設 、平面設計服





    更多精彩文章:

       

 大數(shù)據(jù)可視化設計賞析(一)

  大數(shù)據(jù)可視化設計賞析(二)

  大數(shù)據(jù)可視化設計賞析(三)

  大數(shù)據(jù)可視化設計賞析(四)

  大數(shù)據(jù)可視化設計賞析(五)

  大數(shù)據(jù)可視化設計賞析(六)

  大數(shù)據(jù)可視化設計賞析(七)




以動物為靈感的 LOGO 設計欣賞

前端達人

    對于許多公司和品牌而言,使用帶有含義的動物logo,能非常準確的傳遞品牌信息!比如說豹子的敏捷,獅子的勇猛,長頸鹿的優(yōu)雅,獨角獸的神秘等等!這種品牌意識在其徽標中使用動物象征來策劃。根據(jù)所選動物的類型,品牌是強大,快速,奢華,關懷,神秘和許多其他情感。

1.jpg2.jpg3.jpg4.jpg5.jpg6.jpg7.jpg8.jpg9.jpg10.jpg11.jpg12.jpg13.jpg14.jpg15.jpg16.jpg17.jpg18.jpg19.jpg20.jpg21.jpg22.jpg23.jpg24.jpg25.jpg26.jpg27.jpg28.jpg29.jpg30.jpg31.jpg32.jpg33.jpg34.jpg35.jpg36.jpg37.jpg38.jpg39.jpg40.jpg41.jpg42.jpg43.jpg


大數(shù)據(jù)可視化設計賞析(二)

前端達人


    隨著大數(shù)據(jù)產(chǎn)業(yè)的發(fā)展,越來越多的公司開始實現(xiàn)數(shù)據(jù)資源的管理和應用,尤其是一些在日常生活中經(jīng)常使用大屏幕的大中型企業(yè)。此時,用戶界面設計者需要呈現(xiàn)相應的視覺效果。接下來為大家介紹大屏可視化的UI設計。


點擊查看原圖

 --大屏UI設計--


3.jpg

 --大屏UI設計--


4.jpg

 --大屏UI設計--


5.jpg


 --大屏UI設計--





7.jpg


 --大屏UI設計--



8.jpg


 --大屏UI設計--



9.jpg


 --大屏UI設計--



點擊查看原圖

 --大屏UI設計--


點擊查看原圖


 --大屏UI設計--




點擊查看原圖


 --大屏UI設計--

(圖片均來源于網(wǎng)絡)

  藍藍設計m.sillybuy.com )是一家專注而深入的界面設計公司,為期望卓越的國內(nèi)外企業(yè)提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網(wǎng)站建設 平面設計服


    更多精彩文章:

       

 大數(shù)據(jù)可視化設計賞析(一)

  大數(shù)據(jù)可視化設計賞析(二)

  大數(shù)據(jù)可視化設計賞析(三)

  大數(shù)據(jù)可視化設計賞析(四)

  大數(shù)據(jù)可視化設計賞析(五)

  大數(shù)據(jù)可視化設計賞析(六)

  大數(shù)據(jù)可視化設計賞析(七)


小程序入門到精通:了解小程序開發(fā)4個重要文件

前端達人

點擊查看原圖


1. 小程序沒有DOM對象,一切基于組件化

2. 小程序的四個重要的文件

  • *.js —> view邏輯 —> javascript
  • *.wxml —> view結(jié)構(gòu) ----> html
  • *.wxss —> view樣式 -----> css
  • *. json ----> view 數(shù)據(jù) -----> json文件

注意:為了方便開發(fā)者減少配置項,描述頁面的四個文件必須具有相同的路徑與文件名。

2.1 WXML

WXML(WeiXin Markup Language)是框架設計的一套標簽語言,結(jié)合基礎組件、事件系統(tǒng),可以構(gòu)建出頁面的結(jié)構(gòu)。WXML 充當?shù)木褪穷愃?nbsp;HTML 的角色
要完整了解 WXML 語法,請參考WXML 語法參考

2.2 WXSS

WXSS (WeiXin Style Sheets)是一套樣式語言,用于描述 WXML 的組件樣式。

WXSS 用來決定 WXML 的組件應該怎么顯示。

為了適應廣大的前端開發(fā)者,WXSS 具有 CSS 大部分特性。同時為了更適合開發(fā)微信小程序,WXSS 對 CSS 進行了擴充以及修改。

與 CSS 相比,WXSS 擴展的特性有:



尺寸單位

樣式導入

2.3 json

JSON 是一種數(shù)據(jù)格式,并不是編程語言,在小程序中,JSON扮演的靜態(tài)配置的角色。



全局配置

小程序根目錄下的 app.json 文件用來對微信小程序進行全局配置,決定頁面文件的路徑、窗口表現(xiàn)、設置網(wǎng)絡超時時間、設置多 tab 等。



頁面配置

每一個小程序頁面也可以使用同名 .json 文件來對本頁面的窗口表現(xiàn)進行配置,頁面中配置項會覆蓋 app.json 的 window 中相同的配置項。



工具配置 project.config.json

通常大家在使用一個工具的時候,都會針對各自喜好做一些個性化配置,例如界面顏色、編譯配置等等,當你換了另外一臺電腦重新安裝工具的時候,你還要重新配置。

考慮到這點,小程序開發(fā)者工具在每個項目的根目錄都會生成一個 project.config.json,你在工具上做的任何配置都會寫入到這個文件,當你重新安裝工具或者換電腦工作時,你只要載入同一個項目的代碼包,開發(fā)者工具就自動

注意:

JSON文件都是被包裹在一個大括號中 {},通過key-value的方式來表達數(shù)據(jù)。JSON的Key必須包裹在一個雙引號中,在實踐中,編寫 JSON 的時候,忘了給 Key 值加雙引號或者是把雙引號寫成單引號是常見錯誤。

JSON的值只能是以下幾種數(shù)據(jù)格式,其他任何格式都會觸發(fā)報錯,例如 JavaScript 中的 undefined。



數(shù)字,包含浮點數(shù)和整數(shù)

字符串,需要包裹在雙引號中

Bool值,true 或者 false

數(shù)組,需要包裹在方括號中 []

對象,需要包裹在大括號中 {}

Null

還需要注意的是 JSON 文件中無法使用注釋,試圖添加注釋將會引發(fā)報錯。


2.4 js

一個服務僅僅只有界面展示是不夠的,還需要和用戶做交互:響應用戶的點擊、獲取用戶的位置等等。在小程序里邊,我們就通過編寫 JS 腳本文件來處理用戶的操作。


注冊頁面

對于小程序中的每個頁面,都需要在頁面對應的 js 文件中進行注冊,指定頁面的初始數(shù)據(jù)、生命周期回調(diào)、事件處理函數(shù)等



使用 Page 構(gòu)造器注冊頁面

簡單的頁面可以使用 Page() 進行構(gòu)造。



使用 Component 構(gòu)造器構(gòu)造頁面

Page 構(gòu)造器適用于簡單的頁面。但對于復雜的頁面, Page 構(gòu)造器可能并不好用。

此時,可以使用 Component 構(gòu)造器來構(gòu)造頁面。 Component 構(gòu)造器的主要區(qū)別是:方法需要放在 methods: { } 里面。

————————————————

版權(quán)聲明:本文為CSDN博主「前端嵐楓」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/yilanyoumeng3/java/article/details/106292742





2020年,令人驚嘆的Echarts!

前端達人

點擊查看原圖


1.可視化面板介紹

應對現(xiàn)在數(shù)據(jù)可視化的趨勢,越來越多企業(yè)需要在很多場景(營銷數(shù)據(jù),生產(chǎn)數(shù)據(jù),用戶數(shù)據(jù))下使用,可視化圖表來展示體現(xiàn)數(shù)據(jù),讓數(shù)據(jù)更加直觀,數(shù)據(jù)特點更加突出。

01-技術(shù)要點

  1. div + css 布局
  2. flex 布局
  3. Less
  4. 原生js + jquery 使用
  5. rem適配
  6. echarts基礎

02-案例適配方案

  1. 設計稿是1920px
  2. flexible.js 把屏幕分為 24 等份
  3. cssrem 插件的基準值是 80px
    插件-配置按鈕—配置擴展設置–Root Font Size 里面 設置。
    但是別忘記重啟vscode軟件保證生效


03-頁面主體布局

  1. header布局
  2. mainbox布局
  3. 公共面板模塊 panel
  4. 柱形圖 bar
因為我們今天的主題是echarts部分所以前面的這些,我就為大家寫好框架,里面的布局相信以大家的能力都是分分鐘解決的事情。


2.Echarts(重點)

echarts介紹

常見的數(shù)據(jù)可視化庫:

D3.js 目前 Web 端評價最高的 Javascript 可視化工具庫(入手難)
ECharts.js 百度出品的一個開源 Javascript 數(shù)據(jù)可視化庫
Highcharts.js 國外的前端數(shù)據(jù)可視化庫,非商用免費,被許多國外大公司所使用
AntV 螞蟻金服全新一代數(shù)據(jù)可視化解決方案 等等
Highcharts 和 Echarts 就像是 Office 和 WPS 的關系

ECharts,一個使用 JavaScript 實現(xiàn)的開源可視化庫,可以流暢的運行在 PC 和移動設備上,兼容當前絕大部分瀏覽器(IE8/9/10/11,Chrome,F(xiàn)irefox,Safari等),底層依賴矢量圖形庫 ZRender,提供直觀,交互豐富,可高度個性化定制的數(shù)據(jù)可視化圖表。

官網(wǎng)地址:https://www.echartsjs.com/zh/index.html

echarts體驗
下載echarts https://github.com/apache/incubator-echarts/tree/4.5.0

使用步驟(5大步驟):
1.引入echarts 插件文件到html頁面中
2.準備一個具備大小的DOM容器

<div id="main" style="width: 600px;height:400px;"></div>

3.初始化echarts實例對象

var myChart = echarts.init(document.getElementById('main'));

4.指定配置項和數(shù)據(jù)(option)

var option = {
    xAxis: {
        type: 'category',
        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    },
    yAxis: {
        type: 'value'
    },
    series: [{
        data: [820, 932, 901, 934, 1290, 1330, 1320],
        type: 'line'
    }]
};

5.將配置項設置給echarts實例對象


myChart.setOption(option);  


echarts基礎配置

這是要求同學們知道以下配置每個模塊的主要作用干什么的就可以了

series

系列列表。每個系列通過 type 決定自己的圖表類型

大白話:圖標數(shù)據(jù),指定什么類型的圖標,可以多個圖表重疊。

xAxis:直角坐標系 grid 中的 x 軸

boundaryGap: 坐標軸兩邊留白策略 true,這時候刻度只是作為分隔線,標簽和數(shù)據(jù)點都會在兩個刻度之間的帶(band)中間。

yAxis:直角坐標系 grid 中的 y 軸

grid:直角坐標系內(nèi)繪圖網(wǎng)格。

title:標題組件

tooltip:提示框組件

legend:圖例組件

color:調(diào)色盤顏色列表

數(shù)據(jù)堆疊,同個類目軸上系列配置相同的stack值后 后一個系列的值會在前一個系列的值上相加。



option = {

    // color設置我們線條的顏色 注意后面是個數(shù)組

    color: ['pink', 'red', 'green', 'skyblue'],

    // 設置圖表的標題

    title: {

        text: '折線圖堆疊123'

    },

    // 圖表的提示框組件 

    tooltip: {

        // 觸發(fā)方式

        trigger: 'axis'

    },

    // 圖例組件

    legend: {

       // series里面有了 name值則 legend里面的data可以刪掉

    },

    // 網(wǎng)格配置  grid可以控制線形圖 柱狀圖 圖表大小

    grid: {

        left: '3%',

        right: '4%',

        bottom: '3%',

        // 是否顯示刻度標簽 如果是true 就顯示 否則反之

        containLabel: true

    },

    // 工具箱組件  可以另存為圖片等功能

    toolbox: {

        feature: {

            saveAsImage: {}

        }

    },

    // 設置x軸的相關配置

    xAxis: {

        type: 'category',

        // 是否讓我們的線條和坐標軸有縫隙

        boundaryGap: false,

        data: ['星期一', '周二', '周三', '周四', '周五', '周六', '周日']

    },

     // 設置y軸的相關配置

    yAxis: {

        type: 'value'

    },

    // 系列圖表配置 它決定著顯示那種類型的圖表

    series: [

        {

            name: '郵件營銷',

            type: 'line',

           

            data: [120, 132, 101, 134, 90, 230, 210]

        },

        {

            name: '聯(lián)盟廣告',

            type: 'line',



            data: [220, 182, 191, 234, 290, 330, 310]

        },

        {

            name: '視頻廣告',

            type: 'line',

          

            data: [150, 232, 201, 154, 190, 330, 410]

        },

        {

            name: '直接訪問',

            type: 'line',

          

            data: [320, 332, 301, 334, 390, 330, 320]

        }

    ]

};



3.Echarts快速使用

1.官網(wǎng)實例

點擊查看原圖



官網(wǎng)默認為我們提供了大量的案例,我們需要使用那一種只需要直接點擊打開后復制他們的相關配置,然后按照我上面說的5大步驟進行使用即可。

2.社區(qū)Gallery

點擊查看原圖



官方自帶的圖例,可能在很多時候并不能滿足我們的需要,在社區(qū)這里可以找到一些基于echart的高度定制好的圖表,相當于基于jquery開發(fā)的插件,這里是基于echarts開發(fā)的第三方的圖表。

本案例中使用了地圖模擬飛行的案例就是從社區(qū)中進行引用的,
參考社區(qū)的例子:https://gallery.echartsjs.com/editor.html?c=x0-ExSkZDM (模擬飛機航線)
實現(xiàn)步驟:

第一需要下載china.js提供中國地圖的js文件
第二個因為里面代碼比較多,我們新建一個新的js文件 myMap.js 引入
使用社區(qū)提供的配置即可。
代碼已經(jīng)上傳至我的碼云如有需要的小伙伴可自行下載:
https://gitee.com/jiuyueqi/echarts

ps:最后呢,如果大家看完樓主的文章覺得對echarts的學習和了解有所幫助,麻煩大家路過點個贊點個關注唄!樓主后續(xù)還會繼續(xù)更新有關前端方面的面試題資料或者其他方面的知識。
————————————————
版權(quán)聲明:本文為CSDN博主「程序猿玖月柒」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_45257157/java/article/details/106300587

關于JavaScript獲取時間函數(shù)及實現(xiàn)倒計時

前端達人

JavaScript數(shù)組對象的迭代方法詳解

上一篇博客講到了數(shù)組的方法,當然里邊比較復雜的就是數(shù)組的迭代方法,因為涉及到了回調(diào)函數(shù),所以這篇博客我們來詳細講解一下js數(shù)組迭代方法的使用。


1.forEach(funcrion(value,index,arr){}):對數(shù)組的每一項運行給定函數(shù),這個方法不進行返回,所以一般用于讓數(shù)組循環(huán)執(zhí)行某方法。

  var arr=[1,2,3,4,5,6];

    arr.forEach(function(val,index,arr){

        console.log(val,index,arr);

    })

    // 其中:

    // value:每一個數(shù)組項的值 必填項

    // index:每一個數(shù)組項對應的索引

    // arr:當前的數(shù)組


注意:forEach()方法不返回值,所以回調(diào)函數(shù)中使用return會打印出來undefined。

2.map(funcrion(value,index,arr){}):對數(shù)組的每一項運行給定函數(shù),它將返回執(zhí)行函數(shù)后的結(jié)果組成的新數(shù)組。

 var aNum2 = [1.2, 1.8, 2.0, 4.3];

    console.log(aNum2.map(Math.floor()));// [1,1,2,4]

    

    var arr=[1,2,3];

    console.log(arr.map(function(val,index){

        return val*3

    }));// 3 6 9

    // 其中:

    // value:每一個數(shù)組項的值 必填項

    // index:每一個數(shù)組項對應的索引

    // arr:當前的數(shù)組

注意:map()方法有返回值,返回值為新的數(shù)組,所以可以直接再回調(diào)函數(shù)中return。

3.every(funcrion(value,index,arr){}):對數(shù)組的每一項都運行給定函數(shù),進項判斷,若對于每項執(zhí)行函數(shù)都返回了true,則其結(jié)果為true。

 var arr=[10,20,30];

    console.log(arr.every(function(val){

        return val>20;

    }));// false

    

    console.log(arr.every(function(val){

        return val>0;

    }));// true

    

    // 其中:

    // value:每一個數(shù)組項的值 必填項

    // index:每一個數(shù)組項對應的索引

    // arr:當前的數(shù)組



注意:every()方法所有的數(shù)組項都符合判斷時返回true,否則返回false。

4.some(funcrion(value,index,arr){}):對數(shù)組的每一項都運行給定函數(shù),進行判斷,若存在一項符合條件的數(shù)組項,則其結(jié)果為true。

    var arr=[10,20,30];

    console.log(arr.some(function(val){

        return val>20;

    }));// true

    

    console.log(arr.some(function(val){

        return val>0;

    }));// true

    

    console.log(arr.some(function(val){

        return val<0;

    }));// false

    

    arr.some(function(val){

        console.log(val<0);

    });//fasle false false

    // 其中:

    // value:每一個數(shù)組項的值 必填項

    // index:每一個數(shù)組項對應的索引

    // arr:當前的數(shù)組


注意:some()方法如果回調(diào)函數(shù)執(zhí)行完會根據(jù)結(jié)果返回true或false,但是回調(diào)函數(shù)中打印判斷是,只會作為判斷條件的返回值,則會打印多遍。

5.fliter(funcrion(value,index,arr){}):對數(shù)組的每一項都運行給定函數(shù),進行過濾,將符合條件的數(shù)組項添加到新的數(shù)組中,并返回新的數(shù)組。

   var aNum=[1,2,3,4];
    console.log(aNum.filter(function (num) {
        return num > 1;
    }));//[2,3,4,]
    aNum.filter(function (num) {
        console.log(num > 1);//true true true
    })

注意:filter()方法對數(shù)組項進行過濾,然后將符合條件的數(shù)組項添加到一個新的數(shù)組并返回,但是如果直接打印這個判斷條件,相當于打印的判斷條件的結(jié)果,只會返回true或者false。

6.ES6中新增的迭代方法

1.find():返回第一個符合傳入測試(函數(shù))條件的數(shù)組元素。


  var aNum=[10,20,30,40];

    console.log(aNum.find(function (num) {

        return num > 19;

    }));//1

    console.log(aNum.find(function (num) {

        return num < 0;

    }));//undefined



2.findIndex():返回符合傳入測試(函數(shù))條件的數(shù)組元素索引。


console.log(aNum.findIndex(function (num) { return num > 19; }));//3


3.includes():判斷一個數(shù)組是否包含一個指定的值。

總結(jié):

forEach()與map()是一對,用于數(shù)組遍歷執(zhí)行指定函數(shù),前者不返回數(shù)組,后者返回 處理過的新數(shù)組。
every()與some()是一對,分別適用于檢測數(shù)組是否全部滿足某條件或者存在滿足的數(shù)組項,返回true或false。
filter()則是相當于過濾器的存在,過濾掉數(shù)組中不符合條件的數(shù)據(jù),將符合條件的數(shù)組項添加到新數(shù)組,并返回。
————————————————
版權(quán)聲明:本文為CSDN博主「Mr_Han119」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_39155611/java/article/details/106294417


小白學VUE——快速入門

前端達人

文章目錄

小白學VUE——快速入門

前言:什么是VUE?

環(huán)境準備:

vue的js文件

vscode

Vue入門程序

抽取代碼片段

vue標準語法:

什么是vue指令?

v-bind指令

事件單向綁定

v-model:事件雙向綁定

v-on事件監(jiān)聽指令

v: on:submit.prevent指令

v-if 判斷指令

v-for 循環(huán)渲染指令

前言:什么是VUE?

Vue.js(讀音 /vju?/, 類似于 view) 是一套構(gòu)建用戶界面的漸進式框架。 Vue 只關注視圖層, 采用自底向上增量開發(fā)的設計。 Vue 的目標是通過盡可能簡單的 API 實現(xiàn)響應的數(shù)據(jù)綁定和組合的視圖組件。

點擊查看原圖

環(huán)境準備:
vue的js文件
使用CDN外部導入方法
以下推薦國外比較穩(wěn)定的兩個 CDN,把這些網(wǎng)址放進script標簽的src屬性下即可,國內(nèi)還沒發(fā)現(xiàn)哪一家比較好,目前還是建議下載到本地。

Staticfile CDN(國內(nèi)) : https://cdn.staticfile.org/vue/2.2.2/vue.min.js
unpkg:https://unpkg.com/vue/dist/vue.js, 會保持和 npm 發(fā)布的的版本一致。
cdnjs : https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js
2.VSCODE軟件
(2).使用內(nèi)部導入方法(自行下載js文件放進工作區(qū)js文件夾即可)

2.png

vscode

前往vscode官網(wǎng)下載對應版本的vscode

點擊查看原圖

Vue入門程序
首先了解一下什么是插值
插值:數(shù)據(jù)綁定最常見的形式就是使用 **{{…}}(雙大括號)**的文本插值:

單獨抽出這段來看一下:
Vue即是vue內(nèi)置的對象,el(element)指的是綁定的元素,可以用#id綁定元素,data指的是定義頁面中顯示的模型數(shù)據(jù),還有未展示的methods,指的是方法

var app = new Vue({
            el: "#app",//綁定VUE作用的范圍
            data: {//定義頁面中顯示的模型數(shù)據(jù)
                message: 'hello vue'
            }
 });

代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>


    <script src="js/vue.min.js"></script>

</head>
<body>
    

    <!-- 插值表達式 獲取data里面定義的值 {{message}} -->
    <div id="app">{{ message }}</div>

    <script>
        //創(chuàng)建一個VUE對象
        var app = new Vue({
            el: "#app",//綁定VUE作用的范圍
            data: {//定義頁面中顯示的模型數(shù)據(jù)
                message: 'hello vue'
            }
        });

    </script>

</body>
</html>

抽取代碼片段

步驟:文件-首選項-用戶片段
輸入片段名稱回車

復制以下片段覆蓋之前的注釋內(nèi)容

{
"vh": {
"prefix": "vh", // 觸發(fā)的關鍵字 輸入vh按下tab鍵
"body": [
"<!DOCTYPE html>",
"<html lang=\"en\">",
"",
"<head>",
"    <meta charset=\"UTF-8\">",
"    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">",
"    <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">",
"    <title>Document</title>",
"    <script src=\"js/vue.min.js\"></script>",
"</head>",
"",
"<body>",
"    <div id=\"app\"></div>",
"    <script>",
"        var vm=new Vue({",
"           el:'#app',",
"           data:{},",
"           methods:{}",
"        });",
"    </script>",
"</body>",
"",
"</html>",
],
"description": "vh components"
}
}

此時,新建一個html文件,輸入vh在按下tab鍵即可快速填充內(nèi)容

vue標準語法:
什么是vue指令?
在vue中提供了一些對于頁面 + 數(shù)據(jù)的更為方便的輸出,這些操作就叫做指令, 以v-xxx表示
類似于html頁面中的屬性 `

比如在angular中 以ng-xxx開頭的就叫做指令
在vue中 以v-xxx開頭的就叫做指令
指令中封裝了一些DOM行為, 結(jié)合屬性作為一個暗號, 暗號有對應的值,根據(jù)不同的值,框架會進行相關DOM操作的綁定

下面簡單介紹一下vue的幾個基礎指令: v-bind v-if v-for v-on等

v-bind指令
作用:

給元素的屬性賦值
可以給已經(jīng)存在的屬性賦值 input value
也可以給自定義屬性賦值 mydata
語法
在元素上 v-bind:屬性名="常量||變量名"
簡寫形式 :屬性名="變量名"
例:
<div v-bind:原屬性名="變量"></div> <div :屬性名="變量"></div>

事件單向綁定

事件單向綁定,可以用 v-bind:屬性名="常量||變量名,綁定事件,用插值表達式取出值

<body>
    <div id="app">
    
        <h1 v-bind:title="message">
            {{content}}
        </h1>

        <!-- 簡寫方式 -->
        <h2 :title="content">{{message}}</h2>


    </div>
    <script>
        var vm=new Vue({
           el:'#app',
           data:{
               content: '我是標題',
               message: '頁面加載于' + new Date().toDateString()
           }
           
        });
    </script>
</body>

效果:
20200511203222885.png


————————————————
版權(quán)聲明:本文為CSDN博主「熱愛旅行的小李同學」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/m0_46275020/java/article/details/106055312


最簡單理解web前端

前端達人

web前端

web中開發(fā)的三個基本技術(shù)(html5,css3,JavaScript)

html簡介:html語言是純文本類型的語言,是internet上用來編寫網(wǎng)頁的主要語言,使用HTML語言編寫的網(wǎng)頁文件也是標準的純文本文件(簡單說告訴瀏覽器顯示什么)
.
css簡介:css是一種網(wǎng)頁控制技術(shù),采用css技術(shù),可以有效地對頁面、字體、顏色、背景和其他效果實現(xiàn)更加精準的控制
(簡單的說告訴瀏覽器如何顯示)
.
JavaScript:JavaScript是web頁面中的一種腳本編程語言,也是一種通用的、跨平臺的、基于對象和事件驅(qū)動并具有安全性的腳本語言。它不需要進行編譯,而是直接嵌入HTML頁面中,把靜態(tài)頁面變成動態(tài)頁面。(簡單的來說告訴瀏覽器如何交互)

簡單HTML文件結(jié)構(gòu)

<html>/*文件開始*/ <head>/*文件頭*/ <title>標題</title>/*文件標題*/ </head> <body>內(nèi)容</body> </html>/*文件結(jié)束*/

HTML常用的標記

<br>換行 <p></p>段落 <s></s>刪除線 <b></b>字體粗體 <u></u>下劃線 <em></em>斜體內(nèi)容 <sub></sub> 下標 <sup></sup>上標 <hr></hr>水平線 <a></a>超鏈接 .....





bool查詢簡介

Elasticsearch(下面簡稱ES)中的bool查詢在業(yè)務中使用也是比較多的。在一些非實時的分頁查詢,導出的場景,我們經(jīng)常使用bool查詢組合各種查詢條件。



Bool查詢包括四種子句,



must

filter

should

must_not

我這里只介紹下must和filter兩種子句,因為是我們今天要講的重點。其它的可以自行查詢官方文檔。



must, 返回的文檔必須滿足must子句的條件,并且參與計算分值

filter, 返回的文檔必須滿足filter子句的條件。但是跟Must不一樣的是,不會計算分值, 并且可以使用緩存

從上面的描述來看,你應該已經(jīng)知道,如果只看查詢的結(jié)果,must和filter是一樣的。區(qū)別是場景不一樣。如果結(jié)果需要算分就使用must,否則可以考慮使用filter。



光說比較抽象,看個例子,下面兩個語句,查詢的結(jié)果是一樣的。



使用filter過濾時間范圍,

GET kibana_sample_data_ecommerce/_search
{
  "size": 1000, 
  "query": {
    "bool": {
      "must": [
        {"term": {
          "currency": "EUR"
        }}
      ],
      "filter": {
        "range": {
          "order_date": {
            "gte": "2020-01-25T23:45:36.000+00:00",
            "lte": "2020-02-01T23:45:36.000+00:00"
          }
        }
      }
    }
  }
}


filter比較的原理

上一節(jié)你已經(jīng)知道了must和filter的基本用法和區(qū)別。簡單來講,如果你的業(yè)務場景不需要算分,使用filter可以真的讓你的查詢效率飛起來。



為了說明filter查詢的原因,我們需要引入ES的一個概念 query context和 filter context。



query context



query context關注的是,文檔到底有多匹配查詢的條件,這個匹配的程度是由相關性分數(shù)決定的,分數(shù)越高自然就越匹配。所以這種查詢除了關注文檔是否滿足查詢條件,還需要額外的計算相關性分數(shù).



filter context



filter context關注的是,文檔是否匹配查詢條件,結(jié)果只有兩個,是和否。沒有其它額外的計算。它常用的一個場景就是過濾時間范圍。



并且filter context會自動被ES緩存結(jié)果,效率進一步提高。



對于bool查詢,must使用的就是query context,而filter使用的就是filter context。



我們可以通過一個示例驗證下。繼續(xù)使用第一節(jié)的例子,我們通過kibana自帶的search profiler來看看ES的查詢的詳細過程。



使用must查詢的執(zhí)行過程是這樣的:



可以明顯看到,此次查詢計算了相關性分數(shù),而且score的部分占據(jù)了查詢時間的10分之一左右。



filter的查詢我就不截圖了,區(qū)別就是score這部分是0,也就是不計算相關性分數(shù)。



除了是否計算相關性算分的差別,經(jīng)常使用的過濾器將被Elasticsearch自動緩存,以提高性能。



我自己曾經(jīng)在一個項目中,對一個業(yè)務查詢場景做了這種優(yōu)化,當時線上的索引文檔數(shù)量大概是3000萬左右,改成filter之后,查詢的速度幾乎快了一倍。


總結(jié)

我們應該根據(jù)自己的實際業(yè)務場景選擇合適的查詢語句,在某些不需要相關性算分的查詢場景,盡量使用filter context可以讓你的查詢更加。


你所不知道的XML

前端達人

一、XML:

XML(Extensible Markup Language 可擴展標記語言),XML是一個以文本來描述數(shù)據(jù)的文檔。

1. 示例:

<?xml version="1.0" encoding="UTF-8"?>
<people>
    <person personid="E01">
        <name>Tony</name>
        <address>10 Downing Street, London, UK</address>
        <tel>(061) 98765</tel>
        <fax>(061) 98765</fax>
        <email>tony@everywhere.com</email>
    </person>
    <person personid="E02">
        <name>Bill</name>
        <address>White House, USA</address>
        <tel>(001) 6400 98765</tel>
        <fax>(001) 6400 98765</fax>
        <email>bill@everywhere.com</email>
    </person>
</people>

2. 用途:

(1)充當顯示數(shù)據(jù)(以XML充當顯示層)

(2)存儲數(shù)據(jù)(存儲層)的功能

(3)以XML描述數(shù)據(jù),并在聯(lián)系服務器與系統(tǒng)的其余部分之間傳遞。(傳輸數(shù)據(jù)的一樣格式)

從某種角度講,XML是數(shù)據(jù)封裝和消息傳遞技術(shù)。

3.解析XML:
3.1 :使用SAX解析XML

3.1.1 什么是SAX:

SAX是Simple API for XML的縮寫
SAX 是讀取和操作 XML 數(shù)據(jù)更快速、更輕量的方法。SAX 允許您在讀取文檔時處理它,從而不必等待整個文檔被存儲之后才采取操作。它不涉及 DOM 所必需的開銷和概念跳躍。 SAX API是一個基于事件的API ,適用于處理數(shù)據(jù)流,即隨著數(shù)據(jù)的流動而依次處理數(shù)據(jù)。SAX API 在其解析您的文檔時發(fā)生一定事件的時候會通知您。在您對其響應時,您不作保存的數(shù)據(jù)將會被拋棄。

3.1.2 SAX解析XML方式:

SAX API中主要有四種處理事件的接口,它們分別是ContentHandler,DTDHandler, EntityResolver 和 ErrorHandler 。實際上只要繼承DefaultHandler 類就可以,DefaultHandler實現(xiàn)了這四個事件處理器接口,然后提供了每個抽象方法的默認實現(xiàn)。
// 創(chuàng)建SAX解析器工廠對象
SAXParserFactory spf = SAXParserFactory.newInstance();
// 使用解析器工廠創(chuàng)建解析器實例
SAXParser saxParser = spf.newSAXParser();
// 創(chuàng)建SAX解析器要使用的事件偵聽器對象
PersonHandler handler = 
                         new PersonHandler();
// 開始解析文件
saxParser.parse(
            new File(fileName), handler);


3.2. DOM解析XML:

DOM:Document Object Model(文檔對象模型)
DOM的特性:
定義一組 Java 接口,基于對象,與語言和平臺無關將 XML 文檔表示為樹,在內(nèi)存中解析和存儲 XML 文檔,允許隨機訪問文檔的不同部分。

DOM解析XML
DOM的優(yōu)點,由于樹在內(nèi)存中是持久的,因此可以修改后更新。它還可以在任何時候在樹中上下導航,API使用起來也較簡單。 

DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();
DocumentBuilder db = builder.newDocumentBuilder();
db.parse("person.xml");
NodeList node_person = doc.getElementsByTagName("person");

 3.3. JDOM解析XML:

JDOM是兩位著名的 Java 開發(fā)人員兼作者,Brett Mclaughlin 和 Jason Hunter 的創(chuàng)作成果, 2000 年初在類似于Apache協(xié)議的許可下,JDOM作為一個開放源代碼項目正式開始研發(fā)了。

JDOM 簡化了與 XML 的交互并且比使用 DOM 實現(xiàn)更快,JDOM 與 DOM 主要有兩方面不同。首先,JDOM 僅使用具體類而不使用接口。這在某些方面簡化了 API,但是也限制了靈活性。第二,API 大量使用了 Collections 類,簡化了那些已經(jīng)熟悉這些類的 Java 開發(fā)者的使用。
 

解析步驟:
(1)SAXBuilder sax = new SAXBuilder();
(2)Document doc = sax.build(….);
(3)Element el = doc.getRootElement();(4)List list = el.getChildren();
(5)遍歷內(nèi)容


3.4. DOM4J解析XML:

dom4j是一個非常非常優(yōu)秀的Java XML API,具有性能優(yōu)異、功能強大和極端易用使用的特點,同時它也是一個開放源代碼的軟件,可以在SourceForge上找到它。在對主流的Java XML API進行的性能、功能和易用性的評測,dom4j無論在那個方面都是非常出色的。如今你可以看到越來越多的Java軟件都在使用dom4j來讀寫XML,特別值得一提的是連Sun的JAXM也在用dom4j。這是必須使用的jar包, Hibernate用它來讀寫配置文件。
解析步驟:
(1)SAXReader sax = new SAXReader();
(2)Document doc = sax.read(Thread.currentThread().getContextClassLoader()
          .getResourceAsStream("person.xml"));
(3)Element root = doc.getRootElement();
(4)Iterator iterator = root.elementIterator();
(5)遍歷迭代器


4.各種解析方法比較:
JDOM 和 DOM 在性能測試時表現(xiàn)不佳,在測試 10M 文檔時內(nèi)存溢出。
SAX表現(xiàn)較好,這要依賴于它特定的解析方式。一個 SAX 檢測即將到來的XML流,但并沒有載入到內(nèi)存(當然當XML流被讀入時,會有部分文檔暫時隱藏在內(nèi)存中。DOM4J是這場測試的獲勝者,目前許多開源項目中大量采用 DOM4J,例如大名鼎鼎的 Hibernate 也用 DOM4J 來讀取 XML 配置文件。
xstream 實現(xiàn)XML的轉(zhuǎn)換


5.案例:

public class Person {
    private String personid;
    private String name;
    private String address;
    private String tel;
    private String fax;
    private String email;

    @Override
    public String toString() {
        return "Person{" +
                "personid='" + personid + '\'' +
                ", name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", tel='" + tel + '\'' +
                ", fax='" + fax + '\'' +
                ", email='" + email + '\'' +
                '}';
    }

    public String getPersonid() {
        return personid;
    }

    public void setPersonid(String personid) {
        this.personid = personid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public String getFax() {
        return fax;
    }

    public void setFax(String fax) {
        this.fax = fax;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}



<?xml version="1.0" encoding="UTF-8"?>
<people>
    <person personid="E01">
        <name>Tony Blair</name>
        <address>10 Downing Street, London, UK</address>
        <tel>(061) 98765</tel>
        <fax>(061) 98765</fax>
        <email>blair@everywhere.com</email>
    </person>
    <person personid="E02">
        <name>Bill Clinton</name>
        <address>White House, USA</address>
        <tel>(001) 6400 98765</tel>
        <fax>(001) 6400 98765</fax>
        <email>bill@everywhere.com</email>
    </person>
</people>


import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Hu Guanzhong
 * SAX解析的特點:
 * 1、基于事件驅(qū)動
 * 2、順序讀取,速度快
 * 3、不能任意讀取節(jié)點(靈活性差)
 * 4、解析時占用的內(nèi)存小
 * 5、SAX更適用于在性能要求更高的設備上使用(Android開發(fā)中)
 *
 */
public class PersonHandler extends DefaultHandler{
    private List<Person> persons = null;
    private Person p;//當前正在解析的person
    private String tag;//用于記錄當前正在解析的標簽名

    public List<Person> getPersons() {
        return persons;
    }

    //開始解析文檔時調(diào)用
    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
        persons = new ArrayList<>();
        System.out.println("開始解析文檔...");
    }

    //在XML文檔解析結(jié)束時調(diào)用
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
        System.out.println("解析文檔結(jié)束.");
    }

    /**
     * 解析開始元素時調(diào)用
     * @param uri 命名空間
     * @param localName 不帶前綴的標簽名
     * @param qName 帶前綴的標簽名
     * @param attributes 當前標簽的屬性集合
     * @throws SAXException
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        if ("person".equals(qName)){
            p = new Person();
            String personid = attributes.getValue("personid");
            p.setPersonid(personid);
        }
        tag = qName;
        System.out.println("startElement--"+qName);
    }

    //解析結(jié)束元素時調(diào)用
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        if ("person".equals(qName)) {
            persons.add(p);
        }
        tag = null;
        System.out.println("endElement--"+qName);
    }

    //解析文本內(nèi)容時調(diào)用
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        if (tag != null) {
            if ("name".equals(tag)) {
                p.setName(new String(ch,start,length));
            }else if("address".equals(tag)){
                p.setAddress(new String(ch,start,length));
            }else if("tel".equals(tag)){
                p.setTel(new String(ch,start,length));
            }else if("fax".equals(tag)){
                p.setFax(new String(ch,start,length));
            }else if("email".equals(tag)){
                p.setEmail(new String(ch,start,length));
            }
            System.out.println(ch);
        }
    }
}



public class XMLDemo {

    /**
     * 使用第三方xstream組件實現(xiàn)XML的解析與生成
     */
    @Test
    public void xStream(){
        Person p = new Person();
        p.setPersonid("1212");
        p.setAddress("北京");
        p.setEmail("vince@163.com");
        p.setFax("6768789798");
        p.setTel("13838389438");
        p.setName("38");

        XStream xStream = new XStream(new Xpp3Driver());
        xStream.alias("person",Person.class);
        xStream.useAttributeFor(Person.class,"personid");
        String xml = xStream.toXML(p);
        System.out.println(xml);

        //解析XML
        Person person = (Person)xStream.fromXML(xml);
        System.out.println(person);
    }

    /**
     * 從XML文件中讀取對象
     */
    @Test
    public void xmlDecoder() throws FileNotFoundException {
        BufferedInputStream in = new BufferedInputStream(new FileInputStream("test.xml"));
        XMLDecoder decoder = new XMLDecoder(in);
        Person p = (Person)decoder.readObject();
        System.out.println(p);
    }
    /**
     * 把對象轉(zhuǎn)成XML文件寫入
     */
    @Test
    public void xmlEncoder() throws FileNotFoundException {
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("test.xml"));
        XMLEncoder xmlEncoder = new XMLEncoder(bos);
        Person p = new Person();
        p.setPersonid("1212");
        p.setAddress("北京");
        p.setEmail("vince@163.com");
        p.setFax("6768789798");
        p.setTel("13838389438");
        p.setName("38");
        xmlEncoder.writeObject(p);
        xmlEncoder.close();
    }

    /**
     * DOM4J解析XML
     * 基于樹型結(jié)構(gòu),第三方組件
     * 解析速度快,效率更高,使用的JAVA中的迭代器實現(xiàn)數(shù)據(jù)讀取,在WEB框架中使用較多(Hibernate)
     *
     */
    @Test
    public void dom4jParseXML() throws DocumentException {
        //1 創(chuàng)建DOM4J的解析器對象
        SAXReader reader = new SAXReader();
        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/vince/xml/person.xml");
        org.dom4j.Document doc = reader.read(is);
        org.dom4j.Element rootElement = doc.getRootElement();
        Iterator<org.dom4j.Element> iterator = rootElement.elementIterator();
        ArrayList<Person> persons = new ArrayList<>();
        Person p = null;
        while(iterator.hasNext()){
            p = new Person();
            org.dom4j.Element e = iterator.next();
            p.setPersonid(e.attributeValue("personid"));
            Iterator<org.dom4j.Element> iterator1 = e.elementIterator();
            while(iterator1.hasNext()){
                org.dom4j.Element next = iterator1.next();
                String tag = next.getName();
                if("name".equals(tag)){
                    p.setName(next.getText());
                }else if("address".equals(tag)){
                    p.setAddress(next.getText());
                }else if("tel".equals(tag)){
                    p.setTel(next.getText());
                }else if("fax".equals(tag)){
                    p.setFax(next.getText());
                }else if("email".equals(tag)){
                    p.setEmail(next.getText());
                }
            }
            persons.add(p);
        }
        System.out.println("結(jié)果:");
        System.out.println(Arrays.toString(persons.toArray()));
    }

    /**
     * JDOM解析 XML
     * 1、與DOM類似基于樹型結(jié)構(gòu),
     * 2、與DOM的區(qū)別:
     * (1)第三方開源的組件
     * (2)實現(xiàn)使用JAVA的Collection接口
     * (3)效率比DOM更快
     */
    @Test
    public void jdomParseXML() throws JDOMException, IOException {
        //創(chuàng)建JDOM解析器
        SAXBuilder builder = new SAXBuilder();
        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/vince/xml/person.xml");
        org.jdom2.Document build = builder.build(is);
        Element rootElement = build.getRootElement();
        List<Person> list = new ArrayList<>();
        Person person = null;
        List<Element> children = rootElement.getChildren();
        for(Element element: children){
            person = new Person();
            String personid = element.getAttributeValue("personid");
            person.setPersonid(personid);
            List<Element> children1 = element.getChildren();
            for (Element e: children1){
                String tag = e.getName();
                if("name".equals(tag)){
                    person.setName(e.getText());
                }else if("address".equals(tag)){
                    person.setAddress(e.getText());
                }else if("tel".equals(tag)){
                    person.setTel(e.getText());
                }else if("fax".equals(tag)){
                    person.setFax(e.getText());
                }else if("email".equals(tag)){
                    person.setEmail(e.getText());
                }
            }
            list.add(person);
        }
        System.out.println("結(jié)果:");
        System.out.println(Arrays.toString(list.toArray()));
    }

    /**
     * DOM解析XML
     * 1、基于樹型結(jié)構(gòu),通過解析器一次性把文檔加載到內(nèi)存中,所以會比較占用內(nèi)存,可以隨機訪問
     * 更加靈活,更適合在WEB開發(fā)中使用
     */
    @Test
    public void domParseXML() throws ParserConfigurationException, IOException, SAXException {
        //1、創(chuàng)建一個DOM解析器工廠對象
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        //2、通過工廠對象創(chuàng)建解析器對象
        DocumentBuilder documentBuilder = factory.newDocumentBuilder();
        //3、解析文檔
        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/vince/xml/person.xml");
        //此代碼完成后,整個XML文檔已經(jīng)被加載到內(nèi)存中,以樹狀形式存儲
        Document doc = documentBuilder.parse(is);
        //4、從內(nèi)存中讀取數(shù)據(jù)

        //獲取節(jié)點名稱為person的所有節(jié)點,返回節(jié)點集合
        NodeList personNodeList = doc.getElementsByTagName("person");
        ArrayList<Person> persons = new ArrayList<>();
        Person p = null;
        //此循環(huán)會迭代兩次
        for (int i=0;i<personNodeList.getLength();i++){
            Node personNode = personNodeList.item(i);
            p = new Person();
            //獲取節(jié)點的屬性值
            String personid = personNode.getAttributes().getNamedItem("personid").getNodeValue();
            p.setPersonid(personid);
            //獲取當前節(jié)點的所有子節(jié)點
            NodeList childNodes = personNode.getChildNodes();
            for (int j = 0;j<childNodes.getLength();j++){
                Node item = childNodes.item(j);
                String nodeName = item.getNodeName();
                if ("name".equals(nodeName)) {
                    p.setName(item.getFirstChild().getNodeValue());
                }else if("address".equals(nodeName)){
                    p.setAddress(item.getFirstChild().getNodeValue());
                }else if("tel".equals(nodeName)){
                    p.setTel(item.getFirstChild().getNodeValue());
                }else if("fax".equals(nodeName)){
                    p.setFax(item.getFirstChild().getNodeValue());
                }else if("email".equals(nodeName)){
                    p.setEmail(item.getFirstChild().getNodeValue());
                }
            }
            persons.add(p);
        }
        System.out.println("結(jié)果:");
        System.out.println(Arrays.toString(persons.toArray()));
    }

    /**
     * SAX解析的特點:
     * 1、基于事件驅(qū)動
     * 2、順序讀取,速度快
     * 3、不能任意讀取節(jié)點(靈活性差)
     * 4、解析時占用的內(nèi)存小
     * 5、SAX更適用于在性能要求更高的設備上使用(Android開發(fā)中)
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    @Test
    public void saxParseXML() throws ParserConfigurationException, SAXException, IOException {
        //1、創(chuàng)建一個SAX解析器工廠對象
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        //2、通過工廠對象創(chuàng)建SAX解析器
        SAXParser saxParser = saxParserFactory.newSAXParser();
        //3、創(chuàng)建一個數(shù)據(jù)處理器(需要我們自己來編寫)
        PersonHandler personHandler = new PersonHandler();
        //4、開始解析
        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/vince/xml/person.xml");
        saxParser.parse(is,personHandler);
        List<Person> persons = personHandler.getPersons();
        for (Person p:persons){
            System.out.println(p);
        }
    }
}

日歷

鏈接

個人資料

藍藍設計的小編 http://m.sillybuy.com

存檔