本文目錄一覽:
Web前端主流框架—Vue的優缺點分析
Vue:
Vue是尤雨溪編寫的一個構建數據驅動的Web界面的庫,準確來說不是一個框架,它聚焦在V(view)視圖層。它有以下的特性:1.輕量級的框架;2.雙向數據綁定;3.指令;4.插件化。
優點:
1.簡單:官方文檔很清晰,比Angular簡單易學。
2.快速:異步批處理方式更新DOM。
3.組合:用解耦的、可復用的組件組合你的應用程序。
4.緊湊:~18kbmin+gzip,且無依賴。
5.強大:表達式無需聲明依賴的可推導屬性(computedproperties)。
6.對模塊友好:可以通過NPM、Bower或Duo安裝,不強迫你所有的代碼都遵循Angular的各種規定,使用場景更加靈活。
缺點:
1.新生兒:Vue.js是一個新的項目,沒有angular那麼成熟。
2.影響度不是很大:google了一下,有關於Vue.js多樣性或者說豐富性少於其他一些有名的庫
3.不支持IE8。
以上就是青藤小編關於Web前端主流框架:Vue的優缺點分析的相關分享,希望對大家有所幫助,想要了解更多相關內容,歡迎大家及時關注哦!
號稱目前最火的前端框架Vue,它有什麼顯著特點呢?
1、Vue是什麼
Vue.js 是目前最火的一個前端框架,除了可以開發網站,還可以開發手機App。
Vue.js 是前端的主流框架之一,和Angular.js、React.js 一起,並成為前端三大主流框架。
Vue.js 是一套構建用戶界面的框架,只關注視圖層,它不僅易於上手,還便於與第三方庫或既有項目整合。
Vue.js 是一套用於構建用戶界面的漸進式框架。
2、Vue的特點
遵循 MVVM 模式
編碼簡潔,體積小,運行效率高,適合移動/PC 端開發
它本身只關注 UI, 可以輕鬆引入 vue 插件或其它第三庫開發項目
3、Vue與其他前端框架的關係
借鑒 angular 的模板和數據綁定技術
借鑒 react 的組件化和虛擬 DOM 技術
4、Vue的現有插件
vue-cli: vue 腳手架,用於搭建項目的骨架
vue-resource(axios): ajax 請求
vue-router: 路由
vuex: 狀態管理
vue-lazyload: 圖片懶加載
vue-scroller: 頁面滑動相關
mint-ui: 基於 vue 的 UI 組件庫(移動端)
element-ui: 基於 vue 的 UI 組件庫(PC 端)
5、學習Vue的思想改變
Vue的中心思想是數據驅動,像遠古時代的老前輩jQuery是結構驅動。
大家回憶下以前我們使用jQuery寫代碼的時候,經常是這樣寫的:
$(“#myDiv”).html(“HelloWorld”);
這些寫法首先要獲取Dom節點,也就是Dom結構,然後再修改數據更新結構的內容,使用jQuery的一個很大的目的就是為了去簡化Dom的操作,而使用Vue就大不一樣了,Vue的做法就是直接this.msg=HelloWorld,然後msg就會自動的同步到結構上,我們所要關心的是數據內容的改變,而不再去關心如何操作Dom結構了。
總結一句話:不要在想着怎麼操作DOM,而是想着如何操作數據!!
vue實現路由跳轉的原理是什麼,是調用js底層什麼方法
前端路由是直接找到與地址匹配的一個組件或對象並將其渲染出來。改變瀏覽器地址而不向服務器發出請求有兩種方式:
1. 在地址中加入#以欺騙瀏覽器,地址的改變是由於正在進行頁內導航
2. 使用H5的window.history功能,使用URL的Hash來模擬一個完整的URL。
當打包構建應用時,Javascript 包會變得非常大,影響頁面加載。如果我們能把不同路由對應的組件分割成不同的代碼塊,然後當路由被訪問的時候才加載對應組件,這樣就更加高效了。
目錄結構
先來看看整體的目錄結構
和流程相關的主要需要關注點的就是 components、history 目錄以及 create-matcher.js、create-route-map.js、index.js、install.js。下面就從 basic 應用入口開始來分析 vue-router 的整個流程。
import Vue from ‘vue’
import VueRouter from ‘vue-router’
// 1. 插件
// 安裝 router-view and router-link 組件
// 且給當前應用下所有的組件都注入 $router and $route 對象
Vue.use(VueRouter)
// 2. 定義各個路由下使用的組件,簡稱路由組件
const Home = { template: ‘divhome/div’ }
const Foo = { template: ‘divfoo/div’ }
const Bar = { template: ‘divbar/div’ }
// 3. 創建 VueRouter 實例 router
const router = new VueRouter({
mode: ‘history’,
base: __dirname,
routes: [
{ path: ‘/’, component: Home },
{ path: ‘/foo’, component: Foo },
{ path: ‘/bar’, component: Bar }
]
})
// 4. 創建 啟動應用
// 一定要確認注入了 router
// 在 router-view 中將會渲染路由組件
new Vue({
router,
template: ` div id=”app”
h1Basic/h1
ul
lirouter-link to=”/”//router-link/li
lirouter-link to=”/foo”/foo/router-link/li
lirouter-link to=”/bar”/bar/router-link/li
router-link tag=”li” to=”/bar”/bar/router-link
/ul
router-view class=”view”/router-view
/div
`
}).$mount(‘#app’)123456789101112131415161718192021222324252627282930313233343536373839404142
作為插件
上邊代碼中關鍵的第 1 步,利用 Vue.js 提供的插件機制 .use(plugin) 來安裝 VueRouter,而這個插件機制則會調用該 plugin 對象的 install 方法(當然如果該 plugin 沒有該方法的話會把 plugin 自身作為函數來調用);下邊來看下 vue-router 這個插件具體的實現部分。
VueRouter 對象是在 src/index.js 中暴露出來的,這個對象有一個靜態的 install 方法:
/* @flow */
// 導入 install 模塊
import { install } from ‘./install’// …import { inBrowser, supportsHistory } from ‘./util/dom’// …export default class VueRouter {
// …}
// 賦值 install
VueRouter.install = install
// 自動使用插件if (inBrowser window.Vue) {
window.Vue.use(VueRouter)
}123456789101112131415161718
可以看到這是一個 Vue.js 插件的經典寫法,給插件對象增加 install 方法用來安裝插件具體邏輯,同時在最後判斷下如果是在瀏覽器環境且存在 window.Vue 的話就會自動使用插件。
install 在這裡是一個單獨的模塊,繼續來看同級下的 src/install.js 的主要邏輯:
// router-view router-link 組件import View from ‘./components/view’import Link from ‘./components/link’// export 一個 Vue 引用export let _Vue// 安裝函數export function install (Vue) {
if (install.installed) return
install.installed = true
// 賦值私有 Vue 引用
_Vue = Vue // 注入 $router $route
Object.defineProperty(Vue.prototype, ‘$router’, {
get () { return this.$root._router }
}) Object.defineProperty(Vue.prototype, ‘$route’, {
get () { return this.$root._route }
}) // beforeCreate mixin
Vue.mixin({
beforeCreate () { // 判斷是否有 router
if (this.$options.router) { // 賦值 _router
this._router = this.$options.router // 初始化 init
this._router.init(this) // 定義響應式的 _route 對象
Vue.util.defineReactive(this, ‘_route’, this._router.history.current)
}
}
}) // 註冊組件
Vue.component(‘router-view’, View)
Vue.component(‘router-link’, Link)// …}12345678910111213141516171819202122232425262728293031323334353637383940414243
這裡就會有一些疑問了?
· 為啥要 export 一個 Vue 引用?
插件在打包的時候是肯定不希望把 vue 作為一個依賴包打進去的,但是呢又希望使用 Vue 對象本身的一些方法,此時就可以採用上邊類似的做法,在 install 的時候把這個變量賦值 Vue ,這樣就可以在其他地方使用 Vue 的一些方法而不必引入 vue 依賴包(前提是保證 install 後才會使用)。
· 通過給 Vue.prototype 定義 $router、$route 屬性就可以把他們注入到所有組件中嗎?
在 Vue.js 中所有的組件都是被擴展的 Vue 實例,也就意味着所有的組件都可以訪問到這個實例原型上定義的屬性。
beforeCreate mixin 這個在後邊創建 Vue 實例的時候再細說。
實例化 VueRouter
在入口文件中,首先要實例化一個 VueRouter ,然後將其傳入 Vue 實例的 options 中。現在繼續來看在 src/index.js 中暴露出來的 VueRouter 類:
// …import { createMatcher } from ‘./create-matcher’// …export default class VueRouter {
// …
constructor (options: RouterOptions = {}) {
this.app = null
this.options = options
this.beforeHooks = []
this.afterHooks = []
// 創建 match 匹配函數
this.match = createMatcher(options.routes || [])
// 根據 mode 實例化具體的 History
let mode = options.mode || ‘hash’
this.fallback = mode === ‘history’ !supportsHistory if (this.fallback) {
mode = ‘hash’
} if (!inBrowser) {
mode = ‘abstract’
}
this.mode = mode switch (mode) {
case ‘history’:
this.history = new HTML5History(this, options.base) break
case ‘hash’:
this.history = new HashHistory(this, options.base, this.fallback) break
case ‘abstract’:
this.history = new AbstractHistory(this) break
default:
assert(false, `invalid mode: ${mode}`)
}
}
// …}123456789101112131415161718192021222324252627282930313233343536373839
裡邊包含了重要的一步:創建 match 匹配函數。
match 匹配函數
匹配函數是由 src/create-matcher.js 中的 createMatcher 創建的:
/* @flow */
import Regexp from ‘path-to-regexp’// …import { createRouteMap } from ‘./create-route-map’// …export function createMatcher (routes: ArrayRouteConfig): Matcher {
// 創建路由 map
const { pathMap, nameMap } = createRouteMap(routes)
// 匹配函數 function match (
raw: RawLocation,
currentRoute?: Route,
redirectedFrom?: Location
): Route {
// …
} function redirect (
record: RouteRecord,
location: Location
): Route {
// …
} function alias (
record: RouteRecord,
location: Location,
matchAs: string
): Route {
// …
} function _createRoute (
record: ?RouteRecord,
location: Location,
redirectedFrom?: Location
): Route { if (record record.redirect) { return redirect(record, redirectedFrom || location)
} if (record record.matchAs) { return alias(record, location, record.matchAs)
} return createRoute(record, location, redirectedFrom)
}
// 返回 return match
}
// …123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
具體邏輯後續再具體分析,現在只需要理解為根據傳入的 routes 配置生成對應的路由 map,然後直接返回了 match 匹配函數。
繼續來看 src/create-route-map.js 中的 createRouteMap 函數:
/* @flow */import { assert, warn } from ‘./util/warn’import { cleanPath } from ‘./util/path’// 創建路由 mapexport function createRouteMap (routes: ArrayRouteConfig): {
pathMap: DictionaryRouteRecord,
nameMap: DictionaryRouteRecord
} { // path 路由 map
const pathMap: DictionaryRouteRecord = Object.create(null) // name 路由 map
const nameMap: DictionaryRouteRecord = Object.create(null) // 遍歷路由配置對象 增加 路由記錄
routes.forEach(route = {
addRouteRecord(pathMap, nameMap, route)
}) return {
pathMap,
nameMap
}
}// 增加 路由記錄 函數function addRouteRecord (
pathMap: DictionaryRouteRecord,
nameMap: DictionaryRouteRecord,
route: RouteConfig,
parent?: RouteRecord,
matchAs?: string
) {
// 獲取 path 、name
const { path, name } = route
assert(path != null, `”path” is required in a route configuration.`) // 路由記錄 對象
const record: RouteRecord = {
path: normalizePath(path, parent),
components: route.components || { default: route.component },
instances: {},
name, parent,
matchAs,
redirect: route.redirect,
beforeEnter: route.beforeEnter,
meta: route.meta || {}
} // 嵌套子路由 則遞歸增加 記錄
if (route.children) {// …
route.children.forEach(child = {
addRouteRecord(pathMap, nameMap, child, record)
})
} // 處理別名 alias 邏輯 增加對應的 記錄
if (route.alias !== undefined) { if (Array.isArray(route.alias)) {
route.alias.forEach(alias = {
addRouteRecord(pathMap, nameMap, { path: alias }, parent, record.path)
})
} else {
addRouteRecord(pathMap, nameMap, { path: route.alias }, parent, record.path)
}
} // 更新 path map
pathMap[record.path] = record // 更新 name map
if (name) { if (!nameMap[name]) {
nameMap[name] = record
} else {
warn(false, `Duplicate named routes definition: { name: “${name}”, path: “${record.path}” }`)
}
}
}function normalizePath (path: string, parent?: RouteRecord): string {
path = path.replace(/\/$/, ”) if (path[0] === ‘/’) return path if (parent == null) return path return cleanPath(`${parent.path}/${path}`)
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
可以看出主要做的事情就是根據用戶路由配置對象生成普通的根據 path 來對應的路由記錄以及根據 name 來對應的路由記錄的 map,方便後續匹配對應。
實例化 History
這也是很重要的一步,所有的 History 類都是在 src/history/ 目錄下,現在呢不需要關心具體的每種 History 的具體實現上差異,只需要知道他們都是繼承自 src/history/base.js 中的 History 類的:
/* @flow */// …import { inBrowser } from ‘../util/dom’import { runQueue } from ‘../util/async’import { START, isSameRoute } from ‘../util/route’// 這裡從之前分析過的 install.js 中 export _Vueimport { _Vue } from ‘../install’export class History {// …
constructor (router: VueRouter, base: ?string) { this.router = router this.base = normalizeBase(base) // start with a route object that stands for “nowhere”
this.current = START this.pending = null
}// …}// 得到 base 值function normalizeBase (base: ?string): string { if (!base) { if (inBrowser) { // respect base tag
const baseEl = document.querySelector(‘base’) base = baseEl ? baseEl.getAttribute(‘href’) : ‘/’
} else { base = ‘/’
}
} // make sure there’s the starting slash
if (base.charAt(0) !== ‘/’) { base = ‘/’ + base
vuejs在前端開發起到什麼作用
jQuery的諸多局限性導致前端工程師的發展受到了很多的限制,只能做一些表面性的工作,並不能實現前後端分離開發。
而近期出現的Vue,它給前端帶來了無限的可能和改變。
改變一:真正意義上的前端工程師
之前開發都是前端做靜態頁面,把頁面給到後台程序員改成jsp、php、asp等等…一頓亂改,一頓塞變量,做完以後頁面樣式亂七八糟,最後你再調整css。說白了你會html,css就行了,基本沒什麼門檻,可以這麼說。
有了Vue和Node的前端工程化以後,前端工程師能做的事情越來越多,後台人員只需要拋過來一個Api,剩下的就可以都交給前端了。
改變二:服務端渲染VS客戶端渲染
傳統的jsp、php或是模板渲染也好,都是服務端渲染,就是客戶端一個請求,服務器直接把整個頁面返回給你,簡單粗暴。(Spring Boot是通過模板引擎,由服務端完成的渲染工作)
但是vue開發是前後端分離開發,通過api進行交互,客戶端請求服務器返回json數據,由客戶端進行渲染。
不僅減輕了服務器的壓力速度更快而且渲染更加優雅,代碼更容易維護。
改變三:渲染優雅,代碼易維護
jQuery是通過DOM來控制數據,不僅笨重而且渲染數據特別麻煩,而 Vue是通過數據來控制狀態,通過控制數據來控制渲染,變量可以直接寫在標籤中,渲染更加優雅。
因為前端代碼和後台代碼都是分開的,所以項目更容易維護,開發效率更高。
改變四:項目工程化,結合npm直接安裝第三方庫
Vue讓前端項目更加工程化,同時也規範了前端工程師的代碼,而node和npm的加入才是vue能蓬勃發展的重要原因。
Node為Vue提供了本地server和模塊化開發的思路,npm更能安裝Vue項目需要的模塊,配合Vue使用,比如Moment.js Element ui vuex等等,這些第三方庫讓Vue有了無限的可能。
敲黑板(補充下):傳統開發jQuery是命令式編程,現代框架開發是函數式編程。現代框架開發,可以使用Webpack(當然使用jQuery也可以使用Webpack),可以使用人家提供的現成的腳手架,比方說create-react-app,vue-cli。極大提高了開發的效率,並且可以使用最新的ES6、ES7語法進行開發,在編碼體驗上,就提高了一個檔次。
總結
知其然,知其所以然,沒有最好的框架,只有最合適的框架!
原創文章,作者:JR6UY,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/129060.html