数据双向绑定的复杂方法

103 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

数据双向绑定的复杂方法

子组件

<template lang="">
    <div>
        
        <input @input="onInput" :value="message">
    </div>
</template>

<script>
export default {
    props:{
        message:{
            type:String
        }
    },
    methods:{
        onInput(e){
            this.$emit("valueChange",e.target.value)
        }
    }
}
</script>
<style lang="">
    
</style>
复制代码

父组件

<template lang="">
    <div>
        {{myMessage}}
        <info :value="myMessage" @valueChange="e => myMessage = e"></info>
    </div>
</template>
<script>
import Info from "./info.vue"
export default {
    components:{
        Info
    },
    data(){
        return{
            myMessage:""
        }
    }
}
</script>

<style lang="">
    
</style>
复制代码

子组件通过$emit 触发事件,父组件通过接受对应事件绑定实现接收参数

sync修饰符

上述代码可以通过.sync可以简化上面代码,只需要修两个地方:

  1. 组件内触发的事件名称以“update:myPropName”命名。
  2. 父组件v-bind:value 加上.sync修饰符,即 v-bind:value.sync 这样父组件就不用再手动绑定@update:value事件了。
// 子组件
...
methods: {
   onInput(e) {
       this.$emit("update:value", e.target.value)
   }
}
复制代码
// 父组件
<info :value.sync="myMessage"></info>
复制代码

多个属性一起绑定

可以通过对象形式实现v-bind.sync = "对象"

<info v-bind.sync="obj"></info> 
<script> 
  ..
  data() { obj: {a: '', b: '', c: '', d: ''} } 
  .. 
</script>
复制代码

注意:

带有.sync修饰符的v-bind不能与表达式一起使用(例如 v-bind:title.sync = "doc.title + '!'"是无效的)

编写浏览器历史相关代码

import HashHistory from './history/hash'
constructor(options){
    this.matcher = createMatcher(options.routes || []);
    // vue路由有三种模式 hash / h5api /abstract ,为了保证调用时方法一致。我们需要提供一个base类,在分别实现子类,不同模式下通过父类调用对应子类的方法
    this.history = new HashHistory(this);
}
复制代码

这里我们以hash路由为主,创建hash路由实例

import History from './base'
// hash路由
export default class HashHistory extends History{
    constructor(router){
        super(router);
    }
}
// 路由的基类
export default class History {
    constructor(router){
        this.router = router;
    }
}
复制代码

如果是hash路由,打开网站如果没有hash默认应该添加#/

import History from './base';
function ensureSlash(){ 
    if(window.location.hash){
        return 
    }
    window.location.hash = '/'
}
export default class HashHistory extends History{
    constructor(router){
        super(router);
        ensureSlash(); // 确保有hash
    }
}
复制代码

稍后我们在继续扩展路由相关代码,我们先把焦点转向初始化逻辑

init(app){
        const history = this.history;
        // 初始化时,应该先拿到当前路径,进行匹配逻辑

        // 让路由系统过度到某个路径
        const setupHashListener = ()=> {
            history.setupListener(); // 监听路径变化
        }
        history.transitionTo( // 父类提供方法负责跳转
            history.getCurrentLocation(), // 子类获取对应的路径
            // 跳转成功后注册路径监听,为视图更新做准备
            setupHashListener
        )
}