VueRouter源码解析——深入理解fillParams、path、resolvePath等方法
2023-10-05 17:17:47
## 导读
在本文中,我们将深入分析VueRouter的源代码,详细了解fillParams、path、resolvePath、parsePath、cleanPath、query、parseQuery、resolveQuery、stringifyQuery和resolve方法的实现细节,以便更深入地理解VueRouter的工作原理。
## fillParams方法
fillParams方法用于将动态参数填充到路径模板中。例如,对于路径模板`/user/:id`,如果动态参数为`123`,那么fillParams方法将返回`/user/123`。
```js
const fillParams = (path, params, routeConfig) => {
for (const key in params) {
const value = params[key]
const segment = routeConfig.pathSegments.find(segment => segment.param === key)
if (segment) {
path = path.replace(segment.regex, value)
}
}
return path
}
path方法
path方法用于获取当前路由的路径。
const path = () => {
return currentRoute.fullPath || '/'
}
resolvePath方法
resolvePath方法用于解析路径。它会将路径中的动态参数替换为对应的值。例如,对于路径/user/:id
,如果动态参数为123
,那么resolvePath方法将返回/user/123
。
const resolvePath = (relative, current, append) => {
if (relative.charAt(0) === '/') {
return relative
}
if (relative.charAt(0) === '?' || relative.charAt(0) === '#') {
return current + relative
}
const stack = current.split('/')
// remove trailing slash
stack.pop()
// resolve relative path
const segments = relative.replace(/^\//, '').split('/')
for (let i = 0; i < segments.length; i++) {
const segment = segments[i]
if (segment === '.') {
continue
} else if (segment === '..') {
stack.pop()
} else {
stack.push(segment)
}
}
// ensure leading slash
if (stack[0] !== '') {
stack.unshift('')
}
return stack.join('/')
}
parsePath方法
parsePath方法用于解析路径。它会将路径分解为一个对象,其中包含路径的各个部分。例如,对于路径/user/123
,parsePath方法将返回一个对象:
{
path: '/user/123',
params: { id: '123' }
}
const parsePath = (path) => {
const hash = path.indexOf('#')
if (hash >= 0) {
path = path.slice(0, hash)
}
const query = path.indexOf('?')
if (query >= 0) {
path = path.slice(0, query)
}
return {
path,
query,
hash
}
}
cleanPath方法
cleanPath方法用于清除路径中的多余部分。例如,对于路径/user///123///
,cleanPath方法将返回/user/123
。
const cleanPath = (path) => {
return path.replace(/\/\//g, '/')
}
query方法
query方法用于获取当前路由的查询参数。
const query = () => {
return currentRoute.query || {}
}
parseQuery方法
parseQuery方法用于解析查询参数。它会将查询参数分解为一个对象。例如,对于查询参数id=123
,parseQuery方法将返回一个对象:
{
id: '123'
}
const parseQuery = (query) => {
const result = {}
query = query.trim().replace(/^(\?|#|&)/, '')
if (!query) {
return result
}
query.split('&').forEach(param => {
const parts = param.replace(/\+/g, ' ').split('=')
const key = decodeURIComponent(parts.shift())
const val = parts.length > 0 ? decodeURIComponent(parts.join('=')) : null
if (key in result) {
result[key] = [].concat(result[key], val)
} else {
result[key] = val
}
})
return result
}
resolveQuery方法
resolveQuery方法用于解析查询参数。它会将查询参数中的动态参数替换为对应的值。例如,对于查询参数id=:id
,如果动态参数为123
,那么resolveQuery方法将返回一个对象:
{
id: '123'
}
const resolveQuery = (query, current, routeConfig) => {
if (!query || !routeConfig) {
return query
}
const queryParams = parseQuery(query)
const dynamicParams = {}
for (const key in queryParams) {
const value = queryParams[key]
const segment = routeConfig.pathSegments.find(segment => segment.param === key)
if (segment) {
dynamicParams[key] = value
}
}
return stringifyQuery(dynamicParams, query)
}
stringifyQuery方法
stringifyQuery方法用于将查询参数转换为字符串。
const stringifyQuery = (obj) => {
const query = []
for (const key in obj) {
const value = obj[key]
if (value == null) {
continue
}
if (Array.isArray(value)) {
for (let i = 0; i < value.length; i++) {
query.push(encodeURIComponent(key) + '=' + encodeURIComponent(value[i]))
}
} else {
query.push(encodeURIComponent(key) + '=' + encodeURIComponent(value))
}
}
return query.join('&')
}
resolve方法
resolve方法用于解析路径和查询参数。它会将路径和查询参数中的动态参数替换为对应的值。例如,对于路径/user/:id
和查询参数id=:id
,如果动态参数为123
,那么resolve方法将返回一个对象:
{
path: '/user/123',
query: { id: '123' }
}
const resolve = (path, current, append) => {
let parsedPath
let parsedQuery
if (typeof path === 'string') {
parsedPath = parsePath(path)
} else {
parsedPath = path
}
parsedQuery = parseQuery(parsedPath.query)
const routeConfig = findRoute(parsedPath.path, current)
if (!routeConfig) {
return createRoute(null, parsedPath, parsedQuery)
}
const resolvedPath = resolvePath(parsedPath.path, current, append)
const resolvedQuery = resolveQuery(parsedQuery, current, routeConfig)
return createRoute(routeConfig, {
path: resolvedPath,
query: resolvedQuery
})
}
总结
在本文中,我们详细分析了VueRouter的源代码,深入了解了fillParams、path、resolvePath、parsePath、cleanPath、query、parseQuery、resolveQuery、stringifyQuery和resolve方法的实现细节。这些方法对于理解VueRouter的工作原理非常重要。