手写vue-router---hash模式

手写前提准备---- 什么是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
ref

    Vue.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|Array

    Vue.component('child', {
        props: ['level'],
        render: function (createElement) {
            return createElement('div', [
                createElement('h1', '我是大标题'),
                createElement('h2', '我是二标题'),
                createElement('h3', '我是三标题')
            ])
        }
    })


手写vue-router

let Vue

class 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
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值