> 文章列表 > 手写vue-router---hash模式

手写vue-router---hash模式

手写vue-router---hash模式

手写vue-router---hash模式

    • 手写前提准备---- 什么是hash
    • 手写前提准备---- Render函数中createElement()函数的参数
    • 手写vue-router

手写前提准备---- 什么是hash

原理就是网页的锚点

关于锚点的使用:

一 :锚点的几种写法:

  1. <a href = "#num-1">锚点1</a> + <div id = 'num-1'></div><a href> + <div id> (常用)
  2. <a href = "#num-1">锚点1</a> + <a name = 'num-1'></a><a href> + <a name> (不常用,后者只能写<a>,限制了一些情况)
  3. <div onclick="testFn()">锚点1</div> + <div id = 'num-1'></div> 这种方式最常用,没有限制。
		// 二:锚点写法三 的 testfn 写法// 1. window.location.hash这个属性可读可写。function testFn(){// 写这个以后,就不用写上面那些了。location.hash = 'num-5'// 滚动到指定的位置document.getElementById("num-5").scrollIntoView();}
        // 三: 关于锚点需要知道的函数// 2. 当#值发生变化时,就会触发这个事件window.addEventListener('hashchange',function(e){console.log(e);;})
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>test-1</title>
</head>
<body><p><a href="#num-4">锚点4</a></p><p><div onclick="testFn()">锚点5</div></p><div id = 'num-1'><div> 锚点1content </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content <br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br></div></div><div id = 'num-2'><div> 锚点2content </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content <br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br></div></div><div id = 'num-3'><div> 锚点3content </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content <br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br></div></div><div id = 'num-4'><div> 锚点4content </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content <br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br></div></div><div id = 'num-5'><div> 锚点5content </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br> </div><div> 锚点content <br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br>锚点content<br></div></div><script>// 当#值发生变化时,就会触发这个事件window.addEventListener('hashchange',function(e){console.log(e);;})// 2. window.location.hash这个属性可读可写。function testFn(){// 写这个以后,就不用写上面那些了。console.log('1111111111111')location.hash = 'num-5'document.getElementById("num-5").scrollIntoView();}</script>
</body>
</html>

我们发散一下思维:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>App.vue</title>
</head>
<body><router-link :to='num-5'></router-link>可以看成=======><p><div onclick="testFn()">锚点5</div></p>  或者<p><a href="#num-5">锚点4</a></p><div id = 'num-1'><router-view/>可以看成=======><div> 页面一 </div></div><div id = 'num-2'><router-view/>可以看成=======><div> 页面二 </div></div><div id = 'num-3'><router-view/>可以看成=======><div> 页面三 </div></div><div id = 'num-4'><router-view/>可以看成=======><div> 页面四 </div></div><div id = 'num-5'><router-view/>可以看成=======><div> 页面五 </div></div><script>// 当#值发生变化时,就会触发这个事件window.addEventListener('hashchange',function(e){console.log(e);;})// 2. window.location.hash这个属性可读可写。function testFn(){// 写这个以后,就不用写上面那些了。console.log('1111111111111')location.hash = 'num-5'document.getElementById("num-5").scrollIntoView();}</script>
</body>
</html>

手写前提准备---- Render函数中createElement()函数的参数

 第一个参数:必填
​ 
可选类型:1、string:html标签
​ 2、object:一个含有数据选项的对象
​ 3function:返回一个含有数据选项的对象Vue.component('child', {render: function (createElement) {//string:html标签return createElement('h1')//object:一个含有数据选项的对象return createElement({template: '<div>谈笑风生</div>'})//function:返回一个含有数据选项的对象var domFun = function () {return {template: `<div>谈笑风生</div>`}}return createElement(domFun())}})第二个参数是数据对象。只能是object
class
style
attrs
domProps
props
on
nativeOn
directives
scopedSlots
slot
key
refVue.component('child', {props: ['level'],render: function (createElement) {return createElement('div', {class: {foo: true,baz: false},style: {height: '34px',background: 'orange',fontSize: '16px'},//正常的html特性(除了class和style)attrs: {id: 'foo',title: 'baz'},//用来写原生的DOM属性domProps: {innerHTML: '<span style="color:blue;font-size:24px">江心比心</span>'}})}})第三个参数-代表子节点
类型:String|ArrayVue.component('child', {props: ['level'],render: function (createElement) {return createElement('div', [createElement('h1', '我是大标题'),createElement('h2', '我是二标题'),createElement('h3', '我是三标题')])}})

手写vue-router

let Vueclass myRouter {constructor(options = {}) {// 定义响应式数据Vue.util.defineReactive(this, 'current', '/')this.routers = options.routers //传入的路由表this.mode = 'hash' //路由模式this.init()//初始化函数}init() {if (this.mode === 'hash') {//监听网页初始化,网页加载完成以后,加载第一个页面window.addEventListener('load', () => {location.hash = '/'this.current = location.hash.slice(1)})//因为拿到的哈希时带#号的,而用户传入的路由表是不带#号的,所以要去掉#号window.addEventListener('hashchange', () => {this.current = location.hash.slice(1)})}}
}const install = function (vue) {/**需要mixin的原因是每个组件都能用   this.$router。使用混入后,各个页面都可以用了*/Vue.mixin({beforeCreate() {// 判断是不是根组件//这里为挂载到构造函数的原型对象上if (this.$options && this.$options.router) {Vue.prototype.$router = this.$options.router}},})//注册全局组件 router-link  router-view//Vue.component函数创建一个组件,第一个参数为组件名称,第二个参数为组件的配置项。Vue.component('router-link', {data() {return {name: 'router-link'}},props: {to: {type: String,require: true//表示必传}},methods:{pushUrl(e){if (this.$router.mode == 'hash') {location.hash = this.to}e.preventDefault()}},render(createElement) {/*** createElement函数也就是h函数,用于创建dom。第一个参数为创建的dom名称,即标签名* 第二个参数为一个配置项*/return createElement('a', {attrs: {href:this.to,},on:{click:this.pushUrl}}, this.$slots.default[0].text)}})Vue.component('router-view', {render(createElement) {// current必须是响应式的才会在发生变化的时候触发render函数let current = this.$router.current //获取当前路由let routers = this.$router.routers// 筛选,筛选完成以后进行渲染let component = routers.find(d => d.path === current)return createElement(component.component)}})
}export default {myRouter,install
}