• Vue组件


    习题详解

    用table表格标签渲染以上数据,表格第一列是学生总分

    '''
    ...
        ...
            <tr>
                ...  # 表头字段
            </tr>
            
            <tr v-for="(score, i) in scores">  
                <td>{{i + 1}}</td>  # 1 
                <td v-for="(v, k, i) in score">{{v}}</td>  # Bob	97	89	67	253
            </tr>
        ...
    ...
    
    
    ...
        // 模拟页面加载成功, 从后台获取数据
        `let scores = null;
        $.ajax({
            url: '',
            success(response) {
                scores = response.data
            }
        });`;
    
        let scores = [
            ...
        ];
    
        // // for in遍历的是取值索引或者key|for of 遍历的是值(字典除外)
        // for (v in scores) {
        //     console.log(v)  // 0 1 2 3 4
        // }
        for (score of scores) {
            score.total = score.math + score.chinese + score.english
        }
        for (let i = 0; i < scores.length - 1; i++) {  
            for (let j = 0; j < scores.length - 1 - i; j++) {
                if (scores[j].total < scores[j + 1].total) {  // 总分排序
                	
                	// 调整整个数据对象顺序
                    let temp = scores[j];  
                    scores[j] = scores[j + 1];
                    scores[j + 1] = temp
                }
            }
        }
        
        new Vue({
            ...
            data: {
                // scores:scores
                scores  // 属性名与变量名相同可省略只写一个
            },
            ...
        })
    ...
    '''
    

    只渲染所有科目都及格了的学生

    '''
            <tr v-for="(score, i) in scores" v-if="score.math >= 60 && score.chinese >= 60 && score.english >= 60">
                ...
            </tr>
    '''
    

    i)有三个按钮:语文、数学、外语,点击谁谁高亮,且当前筛选规则采用哪门学科
    ii)两个输入框,[]~[],前面填最小分数,后面填最大分数,全部设置完毕后,表格的数据会被更新: 只渲染满足所有条件的结果

    '''
        <style>
            .click {
                background-color: pink;
            }
        </style>
        
        
    <div id="app">
        <button type="button" @click="subject = 'chinese'" :class="{click: subject === 'chinese'}">语文</button>
        ...
        <p>
            请输入分数段:
            <input type="number" min="0" max="100" v-model="min">
            ~
            <input type="number" min="0" max="100" v-model="max">
        </p>
        <table border="1" style="margin: auto">  # margin: auto, 居中
            <tr>
                <th>排名</th>  # 添加排名字段
                
                # 单独的v-if, 条件满足则渲染该标签, 不满足则不渲染该标签
                <th v-for="(v, k, i) in scores[0]" v-if="k === 'name' || k === subject || !subject">{{k}}</th>  
            </tr>
            <tr v-for="(score, i) in scores" v-if="(score[subject] >= +min && score[subject] <= +max) || (!max || !min)">
                <td>{{i + 1}}</td>
                <td v-for="(v, k, i) in score" v-if="k=== 'name' || k === subject || !subject">{{v}}</td>  # 循环嵌套及v-if嵌套
            </tr>
        </table>
    </div>
    
    
    ...
            data: {
                ...
                subject: '',
                min: '',
                max: '',
            },
    ...
    '''
    

    组件介绍

    组件: HTML + CSS + JS 封装的集合体, 组件具有复用性

    组件分类

    • 根组件: new Vue() 生成的组件
    • 局部组件: 组件名 = {}, {} 内部采用的是vue语法
    • 全局组件: Vue.component('组件名', {}), {}内部采用的是vue语法

    组件都有管理其HTML页面结果的template实例成员

    '''
    <div id="app">
        {{info}}
    </div>
    
    
        new Vue({
            el: '#app',  // 挂载点本质是被组件中的template成员指定的虚拟DOM替换的占位符
            data: {
                info: '根组件信息',
            },
            ...
            template: '<div>{{info}}</div>'
        })
        // 根组件可以不明确template, 此时template默认采用挂载点的HTML页面结构
        // 如果设置了template, 挂载点的HTML页面结构失效
        // 挂载点不能为body标签和html标签
    '''
    

    子组件

    • 根组件都是作为最顶层的父组件, 局部与全局组件作为根组件的子组件, 组件间的父子关系是相对的
    • 子组件间的数据是隔离的, 每一个子组件拥有自己独立的数据空间
    • 局部组件必须注册后才能使用, 而全局组件不需要注册(提前加载到了内存中, 占用内存), 推荐使用局部组件(使用时才占用内存)
    • 变量在哪个组件中出现就由该组件提供变量值并管理该变量
    '''
    	# 样式复习
        <style>
            body {
                margin: 0; /*取出浏览器页边留白*/
            }
    
            .box {
                 250px; /*调整图片宽度, 长度自动等比缩放*/
                border-radius: 20px; /*图片四周设置20px圆角弧度*/
                overflow: hidden; /*图片超出部分隐藏*/
                background-color: aqua; /*设置图片及文字背景颜色*/
                float: left;
                margin: 10px;
            }
    
            .box img {
                 100%; /*设置图片宽度占比为父标签的100%*/
            }
    
            .box h2 {
                margin: 0; /*取出标题标签与父标签留白*/
                text-align: center; /*标题居中*/
            }
    
            .wrap {
                 1100px;
                margin: 0 auto; /*标签居中*/
                border: 3px solid red;  /*标签边框样式*/
            }
    
            .wrap:after { /*清除浮动影响*/
                content: '';
                display: block;
                clear: both;
            }
        </style>
    '''
    
    '''
    <div id="app">
        <div class="wrap">
            <local-tag></local-tag>  <!--能渲染-->
            <local-Tag></local-Tag>  <!--能渲染-->
            <global-tag></global-tag>
        </div>
    </div>
    
    
        let localTag = {  // 定义局部组件, 需要在使用它的父组件中注册才能正常渲染
            template: `
            <div class="box" @click="fn">
                <img src="img/444.jpg" alt="">
                <h2>美女</h2>
            </div>
            `,
            methods: {
                fn() {
                    alert(123)
                },
            }
        };
    
        Vue.component('globalTag', {  // 定义全局组件, 不需要注册就可以正常渲染
            template: `
            <div class="box">
                <img src="img/555.jpg" alt="">
                <h2>旺仔牛奶</h2>
            </div>
            `
        });
    
        new Vue({
            ...
            components: {
                // localTag: localTag,  // css语法不识别大小写, js中的驼峰体对应css中的-
                localTag  // // 注册局部组件, 属性名与变量名相同时可省略只写一个
            }
    
        })
        // 局部, 全局, 和根组件都是一个vue实例, 一个实例对应一套html, css, js结构
    '''
    

    组件数据局部化

    类比

    类比:
    class A:
        name = 'Owen'
        def __init__(self, name):  # 实例化一次自动执行一次__init__函数产生一个局部作用域
            self.name = name
    
    
    a1 = A('jason')
    a2 = A('tank')
    a1.name
    a2.name
    
    '''
        let localTag = {  // 定义局部组件, 需要在使用它的父组件中注册才能正常渲染
            template: `
            <div class="box" @click="fn">
                <img src="img/444.jpg" alt="">
                <h2>锤了美女{{count}}下</h2>
            </div>
            `,
            methods: {
                fn() {
                    this.count++
                },
            },
            // data: function () {
            //     return {count: 0,}  // 返回对象类型数据
            // },
    
            data() {  // 简写形式, 局部或全局组件可能会被复用多次, 每次被渲染的组件都有自己独立的变量名称空间
                return {count: 0};  // 执行方法会产生局部作用域, 所以方法的返回值作为局部化数据
            },
        };
    '''
    

    组件传参

    父传子

    • 子组件以字符串形式在props中自定义组件属性, 该字符串可以通过反射机制在子组件中以变量形式使用
    • 子组件在父组件中渲染时, 会将父组件的对应变量绑定给子组件的自定义属性, 实现父组件向子组件传参
    '''
    <div id="app">
        <div class="wrap">
            <local-tag v-for="girl in girls" :xxx="girl"></local-tag>
        </div>
    </div>
    
    
    <script>
        let girls = [
            {
                name: '美女四号',
                img_path: 'img/444.jpg',
            },
            ...
        ];
        let localTag = {
            props: ['xxx',],
            template: `
            <div class="box">
                <img :src="xxx.img_path" alt="">
                <h2>{{xxx.name}}</h2>
            </div>
            `,
        };
    '''
    

    子传父

    • 子组件中的template中最多只能写一个根标签, 因为挂载点只能挂载一个标签
    • 子组件中定义的事件, 事件是属于子组件的, 但事件绑定的方法由父组件实现
    • 在子组件中通过 this.emit('自定义事件名', 参数) 控制自定义事件在子组件中触发的位置
    '''
    <div id="app">
        <h1>{{h1}}</h1>
        <h2>{{h2}}</h2>
        <tag @action1="action1Fn" @action2="action2Fn"></tag>  <!--方法action1Fn属于根组件, 由根组件实现, 事件action1属于子组件-->
    </div>
    
    
        let tag = {
            template: `
            <div>
            主标题内容: <input type="text" v-model="input_h1" @input="h1Change">
            子标题内容: <input type="text" v-model="input_h2">
            </div>
            `,
            data() {
                return {
                    input_h1: '',
                    input_h2: '',
                };
            },
            methods: {
                h1Change() {
                    this.$emit('action1', this.input_h1);
                },
            },
            watch: {
                input_h2() {
                    this.$emit('action2', this.input_h2);
                },
            },
        };
        
        new Vue({
            el: '#app',
            methods: {
                action1Fn(a) {
                    if (!a) {
                        this.h1 = '主标题';
                    }
                    else {
                        this.h1 = a;
                    }
                },
                ...,
            },
            components: {
                tag
            },
            data: {
                girls,
                h1: '主标题',
                h2: '子标题',
            }
        });
    '''
    
  • 相关阅读:
    gulp4.0 存在的错误信息 The following tasks did not complete: default,Did you forget to signal async completion?
    高性能前端 art-template 模板
    cookie 详解
    Cross origin requests are only supported for protocol schemes: http, data, chrome,chrome-extension的问题
    jQuery EasyUI 详解
    我的游戏学习日志1——恐龙快打
    我的游戏学习日志2——雪人兄弟
    关于网页导航栏制作的几种方法与常见问题解决(新人向)
    JavaScript基础
    利用CSS3制作网页动画
  • 原文地址:https://www.cnblogs.com/-406454833/p/12117987.html
Copyright © 2020-2023  润新知