删除多余文件;修复hash路由默认值;优化router-link样式

master
yutent 2023-08-16 10:57:17 +08:00
parent 8519bfd4ef
commit 285e64bbed
5 changed files with 16 additions and 222 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "wkitd", "name": "wkitd",
"version": "1.1.0", "version": "1.1.1",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",
"files": [ "files": [

View File

@ -16,6 +16,7 @@ class App extends Component {}
export function createApp({ export function createApp({
data = {}, data = {},
styles = [],
methods = {}, methods = {},
mounted = noop, mounted = noop,
render render
@ -24,6 +25,7 @@ export function createApp({
return new (function () { return new (function () {
App.props = data App.props = data
App.styles = styles
Object.assign(App.prototype, methods, { mounted }) Object.assign(App.prototype, methods, { mounted })
this.use = function (plugin = noop, ...args) { this.use = function (plugin = noop, ...args) {

View File

@ -1,219 +0,0 @@
/**
*
* @authors yutent (yutent@doui.cc)
* @date 2017-04-14 21:04:50
*
*/
import { bind, fire } from 'wkit'
import {
noop,
targetIsThisWindow,
query2object,
object2query
} from '../utils.js'
//hash前缀正则
const PREFIX_REGEXP = /^(#!|#)[\/]+?/
const RULE_REGEXP = /(\/[^/]*)(:[A-Za-z0-9_]+)(\?)?/g
class Router {
type = 'history'
#tables = new Map()
#views = new Set()
#targets = new Map()
#ready = false
#route = Object.create(null)
#beforeEach
constructor() {
// bind(window, 'popstate', this.#hashchange.bind(this))
}
// 事件监听
__listen__() {
let { mode } = this.options
bind(window, 'load, popstate', ev => {
if (ev.type === 'load') {
if (this.ready) {
return
}
this.ready = true
}
let path = mode === 'hash' ? location.hash : location.pathname
path = path.replace(PREFIX_REGEXP, '').trim()
path = path.replace(TRIM_REGEXP, '')
if (ev.type === 'load') {
this.go(path)
// hash模式要手动触发一下路由检测
if (mode === 'hash') {
this.__check__(path)
}
} else {
// 因为pushState不会触发popstate事件,
// 所以这里只在hash模式或有ev.state的情况下才会主动触发路由检测
if (mode === 'hash' || ev.state) {
this.__check__(path)
}
}
})
//劫持页面上所有点击事件,如果事件源来自链接或其内部,
//并且它不会跳出本页,并且以"#/"或"#!/"开头那么触发go方法
bind(document, 'click', ev => {
let prevented =
'defaultPrevented' in ev
? ev.defaultPrevented
: ev.returnValue === false
if (prevented || ev.ctrlKey || ev.metaKey || ev.which === 2) {
return
}
let target = ev.target
while (target.nodeName !== 'A') {
target = target.parentNode
if (!target || target.tagName === 'BODY') {
return
}
}
if (mode === 'history') {
if (targetIsThisWindow(target.target)) {
let href =
target.getAttribute('href') || target.getAttribute('xlink:href')
if (
!href ||
/^(http[s]?:|ftp:)?\/\//.test(href) ||
/^javascript:/.test(href)
) {
return
}
// hash地址,只管修正前缀即可, 会触发popstate事件,所以这里只处理非hash的情况
if (!PREFIX_REGEXP.test(href)) {
// 非hash地址,则需要阻止默认事件
// 并主动触发跳转, 同时强制清除hash
ev.preventDefault()
this.go(href, true)
}
}
}
})
}
__parseRule__(rule, opts) {
let re = rule.replace(RULE_REGEXP, function (m, p1, p2, p3, p4) {
let w = '([\\w.-]'
if (p1 || p2) {
return w + '+)'
} else {
if (!/^\{[\d\,]+\}$/.test(p4)) {
w = '('
}
return w + p4 + ')'
}
})
re = re
.replace(/(([^\\])([\/]+))/g, '$2\\/')
.replace(/(([^\\])([\.]+))/g, '$2\\.')
.replace(/(([^\\])([\-]+))/g, '$2\\-')
.replace(/(\(.*)(\\[\-]+)(.*\))/g, '$1-$3')
re = '^' + re + '$'
opts.regexp = new RegExp(re)
return opts
}
__add__(rule, callback) {
// 特殊值"!", 则自动作非匹配回调处理
if (rule === '!') {
this.noMatch = callback
return
}
if (rule.charAt(0) !== '/') {
console.error('路由规则必须以"/"开头')
return
}
rule = rule.replace(/^[\/]+|[\/]+$|\s+/g, '')
let opts = { rule, callback }
Anot.Array.ensure(this.table, this.__parseRule__(rule, opts))
}
// 路由检测
__check__(path) {
let { allowReload } = this.options
if (!allowReload && path === this.last) {
return
}
this.last = this.path
this.path = path
this.pathArr = path.split('/')
LINKS.forEach(vm => {
if (vm.rule.test(this.path)) {
vm.active = true
} else {
vm.active = false
}
})
for (let i = 0, route; (route = this.table[i++]); ) {
let args = path.match(route.regexp)
if (args) {
args.shift()
return route.callback.apply(route, args)
}
}
this.noMatch && this.noMatch(this.path)
}
// 跳转到路由
go2(path, forceCleanHash = false) {
path = path.trim().replace(TRIM_REGEXP, '')
let { mode } = this.options
if (mode === 'hash') {
// 页面刷新时, 不主动添加空hash, 避免执行2次noMatch回调
if (!path && path === location.hash) {
return
}
location.hash = '!/' + path
} else {
let hash = forceCleanHash ? '' : location.hash
let search = forceCleanHash ? '' : location.search
if (forceCleanHash) {
window.history.pushState({ path }, null, `/${path + search + hash}`)
} else {
window.history.replaceState({ path }, null, `/${path + search + hash}`)
}
// pushState不会触发popstate事件,所以要手动触发路由检测
this.__check__(path)
}
}
// 绑定路由事件
addRoute(routes) {
// if (Array.isArray(routes)) {
// routes.forEach(it => {
// this.#add(it)
// })
// } else {
// this.#add(routes)
// }
// // 初始化后再添加路由, 手动执行一次回调
// if (this.#ready) {
// this.#hashchange()
// }
}
}
export default function () {
return () => new Router()
}

View File

@ -24,6 +24,12 @@ class RouterView extends Component {
} }
} }
static styles = css`
:host {
display: block;
}
`
#views = [] #views = []
created() { created() {
@ -80,10 +86,15 @@ class RouterLink extends Component {
static styles = css` static styles = css`
:host { :host {
display: inline-flex; display: inline-flex;
align-items: center;
-webkit-user-select: none; -webkit-user-select: none;
user-select: none; user-select: none;
} }
a { a {
display: flex;
align-items: center;
width: 100%;
height: 100%;
color: inherit; color: inherit;
text-decoration: inherit; text-decoration: inherit;
cursor: pointer; cursor: pointer;

View File

@ -97,9 +97,9 @@ class Router {
#check() { #check() {
let isHash = this.type === MODE_HASH let isHash = this.type === MODE_HASH
let $view = window.wkitd.get(__ROUTER_VIEW__) let $view = window.wkitd.get(__ROUTER_VIEW__)
let hash = location.hash let hash = location.hash || '#/'
let path = isHash let path = isHash
? location.hash ? hash
: location.href.replace(location.origin, '').replace(hash, '') : location.href.replace(location.origin, '').replace(hash, '')
let query let query