VUE之指令,组件

一:指令集

(1)v-once

(1)作用:

  (1)使得标签内部的属性一旦被赋值便不可以被更改

  (2)如果是input框 可以主动输入数据进行更改

(2)使用方式

<div id="app">
    <!--    其不加 v-once input框内数据可以更改-->
    <p><input type="text" v-model="num"></p>
    <!--    其加了v-once input框内数据不能随着别的数据变动而变动 但是可以主动变动-->
    <p><input type="text" v-model="num" v-once></p>
<!--    无论标签内部数据是否变动 其都不会变动-->
    <p v-once>{{num}}</p>
</div>
</body>
<script>
    let app = new Vue({
        el: '#app',
        data: {
            num: 0
        },
    })
</script>
v-once使用方式

(2)v-cloak

(1)作用:防止页面闪烁

<style>
    [v-cloak] {
        display: none;
    }
</style>
<!-- 不处理的情况下,每次新价值该页面,都会先渲染{{}},当vue环境加载成功,{{}}有会被解析消失 -->
<!-- 处理后,vue环境没加载好时,#app是被隐藏的,vue环境加载成功,会依次#app的v-cloak属性,就不会出现{{}}渲染闪烁问题 -->
<div id="app" v-cloak>
    {{ }}
    {{ }}
    {{ }}
</div>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el: '#app',
    })
</script>
v-cloak使用方式

(3)v-if与v-show

(1)作用:

  (1)可以控制标签的显隐

  (2)绑定的都是布尔值

  (3)v-if不会渲染标签 

  (5)v-show会以{display:none}的形式隐藏标签

<div id="app">
    <!--    其下方布尔值对应为false不会再页面渲染出来 且检测内部html标签也不会被渲染-->
    <p v-if="is_show">if标签渲染</p>
    <!--    其下方布尔值对应为false不会再页面渲染出来 检测内部html标签会以display:none的形式渲染-->
    <p v-show="is_show">show标签渲染</p>
</div>
</body>
<script>
    let app = new Vue({
        el: '#app',
        data: {
            is_show: false
        }
    })
</script>
v-if与v-show对比展示

(4)v-if条件判断

(1)作用:

  (1)类似于条件语句进行逻辑判断

(2)使用方式:

v-if = '布尔值'
v-else-if = '布尔值'
v-else 
PS:v-else没有条件 上述条件都不成立 走else条件
<div id="app">
<!--    情况一 v-if布尔值为真 只有其才会进行页面渲染-->
    <p v-if="0">if条件语句运行</p>
<!--    情况二 v-else-if布尔值为真 其余都为假 只有其才会进行页面渲染-->
    <p v-else-if="0">else-if条件语句运行</p>
<!--    情况三 上述if条件都为假 else会进行渲染 且只要if条件对应的布尔值为假 无论else对应的布尔值如何 都会进行渲染-->
    <p v-else>else条件语句运行</p>
</div>
</body>
<script>
    let app = new Vue({
        el: '#app',
    })
</script>
v-if基本使用方式
    <style>
        .box {
            width: 400px;
            height: 300px;
        }

        .r {
            background-color: red;
        }

        .y {
            background-color: yellow
        }

        .b {
            background-color: blue;
        }

    </style>
</head>
<body>
<div id="app">
    <div class="em">
        <p>
            <!--            点击事件 此时点击红 页面显示红色框 以此类推-->
            <button @click="chang_box('rbox')"></button>
            <button @click="chang_box('ybox')"></button>
            <button @click="chang_box('bbox')"></button>
        </p>
        <!--    页面渲染三个框   根据showname对应的值不同进行不同的页面渲染 -->
        <div class="box r" v-if="showname=='rbox'"></div>
        <div class="box y" v-else-if="showname=='ybox'"></div>
        <div class="box b" v-else="showname=='bbox'"></div>

    </div>
</div>
</body>
<script>
    let app = new Vue({
        el: '#app',
        data: {
            // 默认渲染红色
            showname: 'rbox'
        },
        methods: {
            // 上述点击事件会进行传参 当传参的参数赋值给函数 函数将传值赋值给showname
            chang_box(name) {
                this.showname = name
            }
        }
    })
</script>
边框渲染LowB版本
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cn.vuejs.org/js/vue.min.js"></script>
    <style>
        .box {
            width: 400px;
            height: 300px;
        }

        .r {
            background-color: red;
        }

        .y {
            background-color: yellow
        }

        .b {
            background-color: blue;
        }

        .active {
            color: blueviolet;
        }
    </style>
</head>
<body>
<div id="app">
    <div class="em">
        <p>
            <!--            根据布尔值判断这个按钮字体显示-->
            <button @click="changeBox('rbox')" :class="{active:showname=='rbox'}"></button>
            <button @click="changeBox('ybox')" :class="{active:showname=='ybox'}"></button>
            <button @click="changeBox('bbox')" :class="{active:showname=='bbox'}"></button>

        </p>
        <p>
            <!--            三元表达式 如果条件成立则给字体进行渲染 如果不成立则将页面置位空-->
            <button @click="changeBox('rbox')" :class="showname == 'rbox' ? 'active' : ''"></button>
            <button @click="changeBox('ybox')" :class="showname == 'ybox' ? 'active' : ''"></button>
            <button @click="changeBox('bbox')" :class="showname == 'bbox' ? 'active' : ''"></button>
        </p>

        <div class="box r" v-if="showname == 'rbox'"></div>
        <div class="box y" v-else-if="showname == 'ybox'"></div>
        <div class="box b" v-else></div>
    </div>
</div>
</body>
<script>
    let app = new Vue({
        el: '#app',
        data: {
            // 默认渲染红色
            showname: 'rbox'
        },
        methods: {
            // 上述点击事件会进行传参 当传参的参数赋值给函数 函数将传值赋值给showname
            changeBox(name) {
                this.showname = name
            }
        }
    })
</script>
</html>
边框盒子渲染进阶版

(5)v-pre

(1)作用:让标签在受VUE控制区域内的标签 不受VUE控制

<div id="app">
    <p>{{ msg }}</p>
    <!-- v-pre 指令可以在vue控制范围内,形成局部vue不控制区域
    {{ }} 和 v-if 都会原样输出,不会被解析
    -->
    <p v-pre>
        {{ }}
        <span v-if="hehe"></span>
    </p>
</div>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            msg: 'message'
        }
    })
</script>
Vv-pre

(6)v-for

(1)作用:对语句进行for循环

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cn.vuejs.org/js/vue.min.js"></script>
</head>
<body>
<div id="app">
    <div>
        <!--        基础使用方式-->
        <span v-for="ch in str">{{ ch }}</span>
    </div>
    <div>
        <!--针对循环遍历的标签 ch循环的一个个原素 index索引,通过会提供key属性来优化渲染速度,但key的值必须唯一(key可以不用提供) -->
        <span v-for="(ch, index) in str" :key="ch + index">{{ index }}{{ ch }}</span>
    </div>
    <div>
        <!--          便利字典对应的value-->
        <p v-for="ele in dic">{{ ele }}</p>
    </div>
    <div>
        <!--          便利 key,value-->
        <p v-for="(ele, k) in dic">{{ k }}:{{ ele }}</p>
    </div>
    <div>
        <!--            便利key value index-->
        <p v-for="(ele, k, i) in dic">{{ i }}{{ k }}:{{ ele }}</p>
    </div>
</div>
</body>
<script>
    new Vue({
        el: '#app',
        data: {
            str: '鸡你太美啊!',
            arr: [3, 4, 1, 2, 5],
            dic: {
                name: 'SR',
                age: 18,
                gender: '男神',
            }
        }
    })
</script>
</html>
v-for使用方式
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cn.vuejs.org/js/vue.min.js"></script>
    <style>
        li:hover {
            color: red;
            cursor: pointer;

        }
        li{
              list-style: none;
        }
    </style>
</head>
<body>
<div id="app">
    <p>
        <input type="text" v-model="userMsg">
        <button @click="sendMsg" type="button">留言</button>
    <ul>
        <li v-for="(msg, index) in msgs" @click="deleteMsg(index)">{{index}}:{{msg}}</li>
    </ul>
    </p>
</div>
</body>
<script>
    let app = new Vue({
        el: '#app',
        data: {
            // 三元表达式 判断存储数据库中是否有数据 如果有则渲染出来
            msgs: localStorage.msgs ? JSON.parse(localStorage.msgs) : [],  // 存储用户留言
            userMsg: ''  // 用户留言
        },
        methods: {
            sendMsg() {
                // 尾增
                // this.msgs.push(this.userMsg);
                // 首增
                // this.msgs.unshift(this.userMsg);

                let userMsg = this.userMsg;  // 获取用户输入的值
                if (userMsg) {
                    this.msgs.unshift(userMsg);  // 列表首增用户输入数据
                    localStorage.msgs = JSON.stringify(this.msgs);  // 将数据已字符串格式存入前段数据库
                    this.userMsg = '' // 清空用户的留言框
                }
            },
            deleteMsg(index){
                // 从索引位置开始操作 操作1位 没有操作结果
                this.msgs.splice(index,1)  // 开始索引  操作长度  操作的结果们
            }

        }
    })
</script>
</html>
todolist

二:属性

(1)计算属性

(1)特点

  (1)computed用来声明方法属性的

  (2)声明的方法属性 不能与data中定义的重复

  (3)方法属性必须在页面中渲染 才会对内部的出现的变量进行监听

  (4)计算属性的值 来源于监听方法的返回值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cn.vuejs.org/js/vue.min.js"></script>
</head>
<body>
<div id="app">
    姓:<input type="text" v-model="fName">
    名:<input type="text" v-model="lName">
    姓名:<b>{{ flName }}</b>
</div>
</body>
<script>
    let app = new Vue({
        el:'#app',
        data:{
            fName:'',
            lName:'',
        },
        computed:{
            flName(){
                 // fName 与 lName 值发生改变 该方法就会触发
                // 计算属性的值 来源于该函数的返回值  flName
                return this.fName + this.lName
            }
        }
    })
</script>
</html>
computed方法属性

(2)监听属性

  (1)watch为data中已存在的属性设置监听事件

  (2)监听属性值发生改变 就会触发该方法

  (3)监听事件方法的返回值 无任何意义

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cn.vuejs.org/js/vue.min.js"></script>
</head>
<body>
<div id="app">
    姓名:<input type="text" v-model="fullName">
    姓:<b>{{ firstName }}</b>
    名:<b>{{ lastName }}</b>
</div>
</body>
<script>
    let app = new Vue({
        el: '#app',
        data: {
            fullName: '',
            firstName: '',
            lastName: '',
        },
        watch:{  // 监听事件的开启方式
            fullName(){
                nameArr = this.fullName.split('');  // 字符串切换列表
                this.firstName = nameArr[0];
                this.lastName = nameArr[1];
            }
        }

    })
</script>
</html>
监听事件

三:组件

(1)基本概念

(1)定义:一个包含html + css + js的集合体属于一个组件

(2)分类

  (1)根组件:属于new Vue()产生的组件 在项目开发中一个项目 只有一个组件

  (2)全局组件:不用注册就可以成为任何一个组件的子组件

  (3)局部组件:需要注册才能成为局部组件的一个子组件

(3)特点

  (1)每一个组件都包含自己的 html + css + js逻辑

  (2)每一个组件都有自己template模板 用来标识自己html结构

  (3)每一个template只有一个根标签

  (4)根组件一般不提供template模板 就是由真实的挂载点提供

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cn.vuejs.org/js/vue.min.js"></script>
</head>
<body>
<div id="app">
    {{msg}}
</div>
</body>
<script>
    let app = new Vue({
        el: '#app',
        data: {
            msg: '组件'
        },
        template: `

        <div> </div>>  // 此时不会被渲染 在加载顺序的时候 其会有限加载虚拟模板 而不是dom内部数据 导致上述内部数据消失

    <div>{{msg}}</div>  // 其会被加载
    <div>{{msg}}</div>  // 其不会被加载 一个模板下只有一个根标签
        `
    })
</script>
</html>
组件特点展示

(2)局部组件

(1)创建局部组件

(2)注册局部组件

(3)调用局部组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cn.vuejs.org/js/vue.min.js"></script>
    <style>
        .box {
            box-shadow: 0 3px 5px 0 #666;
            width: 240px;
            height: 300px;
            text-align: center;
            padding: 20px 0;
            float: left;
            margin: 5px;
        }

        .box img {
            width: 200px;
        }
    </style>
</head>
<body>
<div id="app">
    <!--    调用局部组件 因为含有大写字母 此时标签不能识别大写字母 因此需要使用--->
    <local-tag></local-tag>
    <local-tag></local-tag>
</div>
</body>
<script>
    // 定义局部组件 给局部组件命名
    let localTag = {
        template: `
        <div class="box">
        <img src="img/001.png" alt="">
        <h3>猫星人</h3>
         <p>猫星人❤猫星人</p>
        </div>
        `
    };
    let app = new Vue({
        el: '#app',
        // 注册局部组件
        components: {
            localTag  // 等价于 localTag:localTag
        }
    })
</script>
</html>
局部组件

(3)全局组件

(1)创建全局组件

(2)父组件之间调用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cn.vuejs.org/js/vue.min.js"></script>
    <style>
        .box {
            box-shadow: 0 3px 5px 0 #666;
            width: 240px;
            height: 300px;
            text-align: center;
            padding: 20px 0;
            float: left;
            margin: 5px;
        }

        .box img {
            width: 200px;
        }

    </style>
</head>
<body>
<div id="app">
    <!--    调用局部组件 因为含有大写字母 此时标签不能识别大写字母 因此需要使用--->
    <global-tag></global-tag>
    <global-tag></global-tag>
    <global-tag></global-tag>
    <global-tag></global-tag>

</div>
</body>
<script>
    // 定义全局组件 给局部组件命名
    Vue.component('global-tag', {
        template: `
        <div class="box" @click="action">
        <img src="img/001.png" alt="">
        <p>猫星人</p>
         <p >猫星人❤{{num}}</p>
        </div>>
        `,
        data() {
            // 给上述的爱心赋值 使用返回值的原因是因为 有多个图片每个对应自己独立的
            return {
                num: 0
            }
        },
        methods: {
            action() {
                this.num++
            }
        }
    });

    let app = new Vue({
        el: '#app',
        // 注册局部组件

    })
</script>
</html>
全局组件

 三:组件交互

 (1)父传子

(1)基本思路:数据交互 - 父传子 - 通过绑定属性的方式

  (1)父组件提供数据

  (2)父组件模板中 子组件设置自定义属性 绑定的值由父组件提供

  (3)通过props获得自定义的属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cn.vuejs.org/js/vue.min.js"></script>
    <style>
        .info {
            text-align: center;
            width: 200px;
            padding: 3px;
            box-shadow: 0 3px 5px 0 pink;
            float: left;
            margin: 5px;
        }

        .info img {
            width: 200px;
        }
    </style>
</head>
<body>
<div id="app">
        <!--  在父组件模板中,为子组件标签设置自定义属性,绑定的值由父组件提供 -->
    <!--    my_info属于自定义属性 其值是便利出来的-->
    <info v-for="info in infos" :key="info.image" :my_info="info"></info>
</div>
</body>
<script>
    // 给所有被渲染的图片打印信息
    let infos = [
        {
            image: 'img/001.png',  // 这些都是图片路径
            title: '猫星人'
        },
        {
            image: 'img/002.png',
            title: '蛋糕'
        },
        {
            image: 'img/003.png',
            title: '蓝糕'
        },
        {
            image: 'img/004.png',
            title: '二哈'  // 图片命名
        },
    ];

    let info = {
        template: `
        <div class="info">

        <img :src="my_info.image" alt="">
        <p>{{my_info.title}}</p>
</div>


        `,
        props: ['my_info']  // 通过反射获取上述变量info
    };
    let app = new Vue({
        el: '#app',
        components: {
            info  // 注册局部组件
        },
        data: {
            // 为上述组件 提供数据
            infos
        }
    })

</script>
</html>
父传子

(2)子传父

(1)基本思路

  (1)数据由子组件提供

  (2)子组件内部通过触发系统事件,发送一个自定义事件,将数据携带出来

  (3)父组件位子组件标签的自定义属性通过方法实现,就可以通过参数拿到子组件传递处理的参数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cn.vuejs.org/js/vue.min.js"></script>
    <style>
        .close:hover {
            cursor: pointer;
            color: red;
        }

        li {
            list-style: none;
        }
    </style>
</head>
<body>
<div id="app">
    <p>
        <input type="text" v-model="userMsg">
        <button @click="sendMsg">留言</button>
    </p>
    <ul>
<!--        子组件通过触发系统事件 发送一个自定义事件 将数据携带过来 自定义事件remove_msg-->
        <msg-li v-for="(msg,index) in msgs " :msg='msg' :index='index' @remove_msg="removeAction"></msg-li>

    </ul>
</div>
</body>
<script>
    let msgLi = {
        template: `
           <li>
            <span class="close" @click="deleteMsg(index)">x </span>
            <span>第{{ index + 1 }}条:</span>
            <span>{{ msg }}</span>
          </li>

        `,
        props: ['msg', 'index'],
        methods: {
                // 自定一个系统事件 传递参数
            deleteMsg(index) {
            // 数据由子组件提供  index
                this.$emit('remove_msg', index);
            }
        }
    };
    let app = new Vue({
        el: '#app',
        data: {
            msgs: [],
            userMsg: ''
        },
        components: {
            msgLi
        },
        methods: {
            sendMsg() {
                if (this.userMsg) {
                    this.msgs.unshift(this.userMsg);
                    this.userMsg = ''
                }
            },
            // 拿到上述自定义事件remove_msg传递过来的参数 index
            removeAction(index) {
                this.msgs.splice(index, 1)
            }
        }
    })
</script>
</html>
子传父
原文地址:https://www.cnblogs.com/SR-Program/p/11643952.html