vue 源码实现(v-if-show)

案例

html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .cover {
            display: flex;
        }

        .box {
            height: 100px;
            width: 100px;
            border: 1px solid #333;
            margin-right: 30px;
            line-height: 100px;
            text-align: center;
            color: #fff;
        }

        .box1 {
            background-color: aqua;
        }

        .box2 {
            background-color: #789;
        }

        .box3 {
            background-color: rgb(53, 26, 102);
        }

        .box4 {
            background-color: rgb(139, 37, 59);
        }

        .btn_cover {
            margin-top: 30px;
            display: flex;
        }

        button {
            margin-right: 20px;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="cover">
            <div class="box box1" v-if="isshow1">
                box1
            </div>
            <div class="box box2" v-if="isshow2">
                box2
            </div>
            <div class="box box3" v-show="isshow3">
                box3
            </div>
            <div class="box box4" v-show="isshow4"> 
                box4
            </div>
        </div>

        <div class="btn_cover">
            <button @click="changeShow1">btn1</button>
            <button @click="changeShow2">btn2</button> 
            <button @click="changeShow3">btn3</button> 
            <button @click="changeShow4">btn4</button>
        </div>
    </div>
</body>
<script src="./index.js"></script>
<script>
    new myProxy({
        el: "#app",
        data: {
            isshow1: false,
            isshow2: false,
            isshow3: false,
            isshow4: false
        },
        methods: {
            changeShow1() {
                this.data.isshow1 = !this.data.isshow1
            },
            changeShow2() {
                this.data.isshow2 = !this.data.isshow2
            },
            changeShow3() {
                this.data.isshow3 = !this.data.isshow3
            },
            changeShow4() {
                this.data.isshow4 = !this.data.isshow4
            },
        }
    })
</script>

</html>

js


class myProxy {
    constructor(options) {
        let { el, data, methods } = options

        this.el = document.querySelector(el)
        this.data = data
        this.methods = methods

        this.eventPool = new Map()
        this.dataPool = new Map()

        this.init()
    }

    init() {
        this.initData()     //data中的数据添加响应式
        this.initDom(this.el)       // 收集数据,methods pool
        this.initView(this.dataPool)       // 将收集到的数据 初始化到具体的节点,控制节点的初始化显示和隐藏
        this.initEvent(this.eventPool)      // 给收集到的eventPool 绑定事件到具体的节点
    }

    initData() {    
        let that = this
        this.data = new Proxy(this.data, {
            get(target, key) {      // 还有一个没有完成的功能,this=>this.data
                // console.log("get--", target[key]);
                return Reflect.get(target, key)
            },
            set(target, key, value) {
                // console.log("set--", value);
                that.changeView(key, that.dataPool)
                return Reflect.set(target, key, value)
            }
        })
    }

    initDom(el) {
        let childNodes = el.childNodes

        if (childNodes.length === 0) {      // 文本节点
            return
        }

        childNodes.forEach(item => {
            if (item.nodeType === 1) {     // 元素节点
                const vIf = item.getAttribute("v-if")
                const vShow = item.getAttribute("v-show")
                const vEvent = item.getAttribute("@click")
                if (vIf) {
                     // 收集数据
                    this.dataPool.set(item, {
                        type: "if",
                        show: this.data[vIf],
                        data: vIf
                    })
                }

                if (vShow) {
                    this.dataPool.set(item, {
                        type: "show",
                        show: this.data[vShow],
                        data: vShow
                    })
                }

                if (vEvent) {
                    this.eventPool.set(item, this.methods[vEvent])
                }
            }
            this.initDom(item)
        })
    }

    initView(dataPool) {
        // 切换视图
        this.changeView(null, dataPool)
    }

    changeView(data = null, dataPool) {
        if (!data) {   // 初始化
            for (let [k, v] of dataPool) {
                switch (v.type) {
                    case "if":
                        v.comment = document.createComment('V-IF')  // 创建一个文本节点来替换
                        !v.show && k.parentNode.replaceChild(v.comment, k)
                        break;
                    case "show":
                        !v.show && (k.style.display = "none")
                        break;
                    default:
                        break;
                }
            }
            return
        }

        // 数据修改时执行
        for (let [k, v] of dataPool) {
            if (v.data === data) {
                switch (v.type) {
                    case "if":
                        v.show ? k.parentNode.replaceChild(v.comment, k)
                            : v.comment.parentNode.replaceChild(k, v.comment)
                        v.show = !v.show

                        break;
                    case "show":
                        v.show ? (k.style.display = "none") :
                            (k.style.display = "block")
                        v.show = !v.show
                        break;
                    default:
                        break;
                }
            }

        }
    }

    initEvent(eventPool) {
        for (let [k, v] of eventPool) {
            k.addEventListener("click", v.bind(this), false)
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue.js 是一个流行的前端框架,用于构建交互式的用户界面。要实现一个考试题目功能,我们可以使用 Vue.js 来实现。下面是一个简单的示例代码,展示了如何使用 Vue.js 来实现考试题目功能: ```html <!DOCTYPE html> <html> <head> <title>考试题目功能</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> </head> <body> <div id="app"> <h1>考试题目功能</h1> <div v-for="question in questions" :key="question.id"> <h2>{{ question.title }}</h2> <ul> <li v-for="option in question.options" :key="option.id"> <label> <input type="checkbox" v-model="selectedOptions[question.id]" :value="option.id"> {{ option.text }} </label> </li> </ul> </div> <button @click="submit">提交答案</button> <div v-if="showResults"> <h2>答案结果</h2> <ul> <li v-for="(result, questionId) in results" :key="questionId"> {{ questions.find(q => q.id === questionId).title }}: {{ result }} </li> </ul> </div> </div> <script> new Vue({ el: '#app', data: { questions: [ { id: 1, title: '问题1', options: [ { id: 1, text: '选项1' }, { id: 2, text: '选项2' }, { id: 3, text: '选项3' } ] }, { id: 2, title: '问题2', options: [ { id: 4, text: '选项1' }, { id: 5, text: '选项2' }, { id: 6, text: '选项3' } ] } ], selectedOptions: {}, results: {}, showResults: false }, methods: { submit() { // 计算结果 const results = {}; for (const questionId in this.selectedOptions) { const selected = this.selectedOptions[questionId] || []; results[questionId] = this.questions.find(q => q.id == questionId).options .filter(option => selected.includes(option.id)) .map(option => option.text); } this.results = results; this.showResults = true; } } }); </script> </body> </html> ``` 以上代码演示了一个简单的考试题目功能,包括显示题目、选择答案、提交答案和展示答案结果。这个功能可以通过 Vue.js 来实现,使用户能够方便地进行答题并获取结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值