Vue基础篇重点汇总

535 阅读5分钟

这次的 Vue基础篇 会从 4个方向 1个项目 来 汇总.

一. 基本语法

1. 数据的对象格式

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <div id="app">
        <p>{{student.name}}今年{{student.age}}岁,是{{student.sex}}的</p>
    </div>
</body>

</html>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            student : {
                name : '张三',
                age : 23,
                sex : '男'
            }
        }
    })
</script>

2. 双向绑定

要求: 输入框输入数据,会显示到h3元素上,分别通过jsvue实现

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <div id="app">
        <input type="text" v-model="msg">
        <h3>{{msg}}</h3>
    </div>
</body>

</html>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script>
    // v-model 指令
    new Vue({
        el: "#app",
        data: {
            msg : ""
        }
    })
</script>

效果图:

双向数据绑定.gif

3. 简易实现双向数据绑定(原生js实现vue双向绑定)

<!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></title>
</head>

<body>
    <input type="text" value="" id="ipt" oninput="iptChange(this.value)">
    <h3 id="title" ></h3>
</body>

</html>
<script>
    // 获取元素
    var ipt = document.getElementById('ipt')
    var title = document.getElementById('title')

    // 声明一个data对象 专门用来放数据
    var data = {};

    // 用来给对象添加属性 define(定义) Property(属性)
    // Object.defineProperty(对象的名称,属性的名称,配置项)
    Object.defineProperty(data, 'msg', {
        // get方法: 定义这个msg时要赋值的数据
        get: function () {
            return '你好世界'
        },
        // set方法: 代表当你拿到最新的值时,需要做的事
        set: function (newVal) {
            title.innerHTML = newVal
            ipt.value = newVal
            console.log(newVal);
        }
    })
    // console.log(data.msg);
    // 初始样式
    title.innerHTML = data.msg
    ipt.value = data.msg

    // input的value值发生改变
    function iptChange(val) {
        data.msg = val  // 修改数据源 会自动触发set方法
    }
</script>

效果图: 实现出来的效果和vue的效果为一样的 简易实现双向数据绑定.gif

4. Vue中的MVVM

GmKzOR8JfUFnHCg.png

1). View层:

视图层,在前端里就是我们常说的DOM层,主要作用是给用户展示各种信息;

2). Model层:

数据层(逻辑层),数据可能是我们自定义的数据,或者是从网络请求下来的数据;

3). ViewModel层:

视图模型层,是View层和Model层沟通的桥梁;一方面它实现了数据绑定(Data Binding),将Model的改变实时反应到View中;另一方面它实现了DOM监听,当DOM发生改变可以对应改变数据(Data)

5. v-pre

概念: 跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。

通俗易懂一点: 让胡子语法失效 显示出该有的{{}}内容

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <div id="app">
        <!-- v-pre: 让胡子语法失效 显示出该有的{{}}内容 -->
        <p>当你输入<span v-pre>{{msg}}</span>的时候,你就可以看到{{msg}}</p>
    </div>
</body>

</html>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            msg : "你好世界"
        }
    })
</script>

效果图:

v-pre.png

6. v-html 和 v-text

概念: 胡子语法与v-text是一样的,都无法解析html标签 , v-html比较强大 可以将html标签解析出来

v-html不仅可以渲染数据,而且可以解析标签

v-text和{{}}表达式渲染数据,不解析标签

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <!-- 
        胡子语法与v-text是一样的,都无法解析html标签
        v-html比较强大 可以将html标签解析出来
    -->
    <div id="app">
        <ul>
            <li>{{msg}}</li>
            <li v-html="msg"></li>
            <li v-text="msg"></li>
            <div>------------</div>
            <li>{{msg}}</li>
            <li v-html="content"></li>
            <li v-text="content"></li>
        </ul> 
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            msg:"你好世界",
            content:"<b>hello world</b>"
        }
    })
</script>

效果图:

v-html和v-text.png

7. v-cloak

概念: v-cloak指令用于在数据渲染出来之前 将标签隐藏掉 这样用户就看不到胡子语法

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
    <style>
        [v-cloak]{
            display: none;
        }
    </style>
</head>

<body>
    <!-- v-cloak指令用于在数据渲染出来之前 将标签隐藏掉 这样用户就看不到胡子语法 -->
    <div id="app">
        <ul>
            <li>{{msg1}}</li>
            <li v-cloak>{{msg2}}</li>
        </ul>
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            msg1:'你好世界1',
            msg2:'你好世界2'
        }
    })
</script>

8. v-show 与 v-if

v-show 和 v-if的区别:

1). 显示和隐藏:

v-show 的显示隐藏控制的是css的display属性
v-if 的显示隐藏时通过创建和销毁dom元素实现的

从性能上讲 v-show性能更好 而v-if会造成性能浪费

2). 使用场景:

当需要频繁切换一个元素的显示隐藏时,使用v-show
当一次性渲染元素并且再也不需要修改,那么两者都行
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
    <style>
        .box{width: 100px;height: 100px;background-color: red;}
    </style>
</head>

<body>
    <div id="app">
        <div class="box" v-show="flag"></div>
        <div class="box" v-if="flag2"></div>
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            flag : true,
            flag2 : false
        }
    })
</script>

我们通过控制台可以看到 v-if的元素被销毁了 v-show的元素只是加了style

v-show和v-if.png

9. v-on

为元素绑定事件可以直接在元素上 v-on:click="方法名称()" ,或者简写成 @click="方法名称()"

对应的方法要写在Vue对象中的 methods 中,在指令中想要访问data属性中的数据,可以通过this加上自己定义的属性名即可,this.自定义属性名称

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
    <style>
        .box{width: 100px;height: 100px;background-color: red;}
    </style>
</head>

<body>
    <div id="app">
        <div>
            <button @click='btnClick'>按钮</button>
            <div class="box" v-show='flag'></div>
        </div> 
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        // data是专门用来存放数据的地方
        data: {
            flag : true
        },
        // methods是专门用来存放方法的地方
        methods:{
            btnClick(){
                // 控制盒子的显示隐藏,本质上是控制盒子的true和false
                console.log(this);
                this.flag = !this.flag
            }
        }
    })
</script>

效果图:

v-on.gif

二. 常用指令

1. v-bind

v-bind 和 v-on 一样也有简写的方式,v-bind:src="" 可以简写成 :src=""

1.1 属性绑定

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <div id="app">
        <a :href="link" v-text="msg"></a>
        <button @click="gobili">切换到B站</button>
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            link : "http://baidu.com",
            msg:'百度一下'
        },
        methods:{
            gobili(){
                this.link = "http://bilibili.com"
                this.msg = '哔哩哔哩'
            }
        }
    })
</script>

效果图:

属性绑定.gif 1.2 类名绑定

绑定class有两种方式:对象语法,数组语法。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
    <style>
        .green{
            color: green;
        }
        .italic{
            font-style: italic;
        }
    </style>
</head>

<body>
    <div id="app">
        <p class="green">绿</p>
        <p v-bind:class="{'green':isgreen}">绿</p>
        <p :class="{'green':isgreen,'italic':isItalic}">绿</p>
        <h3 :class="greenplay ? 'green italic' : '' ">绿色 -- 重要</h3>
        <p :class="['green','italic']">绿</p>
        <p :class="setItalic()">绿</p> <!-- 括号代表立即执行 -->
        <button v-text='msg' @click="huan"></button>
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            greenplay:true,
            isgreen:true,
            isItalic:true,
            msg : '切换false',
            flag : true
        },
        methods:{
            setItalic(){
                return ['green','italic']
            },
            huan(){
                if(this.flag){
                    this.greenplay = false
                    this.msg = '切换为true'
                }else{
                    this.greenplay = true
                    this.msg = '切换为false'
                }
                this.flag = !this.flag
            }
        }
    })
</script>

效果图:

类名绑定.gif 1.3 style绑定

注意点:

  1. 我们可以使用驼峰式语法:比如font-size ---> fontSize
  2. 或短横线分隔 font-size
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <div id="app">
        <ul>
            <li style="background-color: pink; color:orange;">背景粉,文字橙</li>
            <li :style="{'background-color':bgColor,color:fontColor}">背景粉,文字橙</li>
            <li :style="colorObj">背景粉,文字橙</li>
            <li :style="[colorObj,fontStyle]">背景粉,文字橙</li>
            <li :style="getStyle()">背景粉,文字橙</li>
            <!-- 对象的key值是字符串  background-color   -会被浏览器默认成减号-->
            <!-- 
                解决方法:
                    加''变成字符串
                    驼峰式
            -->
        </ul>
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            bgColor:'pink',
            fontColor:'orange',
            colorObj:{background:'pink',color:'orange'},
            fontStyle:{fontSize:'20px'}
        },
        methods:{
            getStyle(){
                return [this.colorObj,this.fontStyle]
            }
        }
    })
</script>

效果图:

style绑定.png

2. 循环遍历v-for以及key的使用

v-for语法: v-for="(item,index) in 数组名"

item 对应的是数组中的每一条数据

index 索引(下标)

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <!-- 
        key作为唯一标识符,如果选用index,那么他就失去了唯一性
        index在数组发生变化时,它自己也会发生变化,所以当数组是会变化的时候,尽量不要选择index作为key

        总结:
        当数组不发生变化时(一次性渲染)key可以选用index或者id
        当数组会发生变化时,这时候会引起html的重排,此时不要选用index,最好选择id
    -->
    <div id="app">
        <ul>
            <li v-for="(item,index) in arr" :key="item.id">{{item.name}} <input type="checkbox"></li>
        </ul>
        <button @click="unshiftOne">追加元素</button>
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            arr: [
                { id:1,name: '张三' },
                { id:2,name: '李四' },
                { id:3,name: '王五' },
            ]
        },
        methods:{
            unshiftOne(){
                this.arr.unshift({ id: 4, name: '狗蛋' })
            }
        }
    })
</script>

效果图: 实现一个在前添加元素的效果

v-for.gif

3. 计算属性

computed中写需要计算的函数

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <div id="app">
        <ul>
            <li>姓:{{xing}}</li>
            <li>名:{{ming}}</li>
            <li>姓名: <input type="text" v-model="username"></li>
        </ul>
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            xing: 'Michael',
            ming: 'Jackson',
            // data里的数据时没有办法调用data里的数据的
            // username : xing +  ming
        },
        computed: {
            username: {
                get() {
                    return this.xing + ' ' + this.ming
                },
                set(newVal) {
                    // 当username的值发生改变时,会自动触发setter
                    console.log(newVal);    // 字符串; 'Michael Jack'
                    let arr = newVal.split(' ')     // ['Michael','Jack']
                    this.xing = arr[0]
                    if (this.ming === undefined) {
                        this.ming = ''
                        return
                    } else {
                        this.ming = arr[1]
                    }
                }
            }

        }
    })
</script>

效果图:

计算属性.gif

computedmethods区别

computed: 执行1次,因为computed有缓存

methods : 调用多少次就执行多少次,因为methods没缓存

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <div id="app">
        <ul>
            <li>姓:{{xing}}</li>
            <li>名:{{ming}}</li>
            <li>[computed]姓名:{{username}}</li>
            <li>[computed]姓名:{{username}}</li>
            <li>[methods]姓名:{{username1()}}</li>
            <li>[methods]姓名:{{username1()}}</li>
            <li>[methods]姓名:{{username1()}}</li>
        </ul>
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            xing: 'Michael',
            ming: 'Jackson',
        },
        computed: {
            username() {
                console.log('computed');
                return this.xing + ' ' + this.ming
            }
        },
        methods: {
            username1() {
                console.log('methods');
                return this.xing + ' ' + this.ming
            }
        }
    })
</script>

效果图:

computed和methods的区别.png

4. v-model原理

v-model 其实是个语法糖,它背后本质上包含了两个操作:

  1. v-bind 绑定input元素的value属性
  2. v-on 指令绑定input元素的input事件
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <div id="app">
        <!-- <input type="text" v-model="msg"> -->
        <!-- <input type="text" v-bind:value="msg" v-on:input="iptChange"> -->
        <!-- $event代替事件中的e -->
        <input type="text" :value="msg" @input="msg=$event.target.value">   
        <h3>{{msg}}</h3>
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            msg : '你好世界'
        },
        methods:{
            iptChange(e){   // e 事件对象   元素 dom对象
                // 修改msg
                this.msg = e.target.value
            }
        }
    })
</script>

效果图:

v-model原理.gif

5. 数组操作

数组操作从刚开始学习js就一直再用,就不写效果图和代码了,简单的总结几个常用的...

push: 从数组的后面添加,返回被删除的数据

pop: 从数组的后面删除

unshift: 从数组的前面添加,返回被删除的数据

shift: 从数组的前面删除

splice: 替换,删除

forEach: 循环(没有返回值)

map: 循环(有返回值)

filter: 过滤

reduce: 叠加

6. 自定义过滤器

全局过滤器

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <div id="app">
        <!-- 
            完成效果:
            <h3>¥21.80元</h3>
         -->
        <h3>{{price | filterMoney}}</h3>
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    // 过滤器
    // Vue.filter(过滤器名称,回调函数)
    Vue.filter('filterMoney', val => {
        // toFixed 数字的方法 去小数点后(位数)
        // 最好先将 val转为数字类型 不然有些情况会报 toFixed is not function
        return '¥' + Number(val).toFixed(2) + '元'
    })

    new Vue({
        el: "#app",
        data: {
            price: 21.8
        }
    })
</script>

效果图:

全局过滤器.png

局部过滤器

局部过滤器和全局过滤器差别不大,唯一的区别就是全局过滤器可以全部共享

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>

<body>
    <div id="app">
        <!-- 
            完成效果:
            <h3>¥21.80元</h3>
         -->
        <h3>{{price | filterMoney}}</h3>
    </div>
</body>

</html>
<script src="./vue.js"></script>
<script>
    new Vue({
        el: "#app",
        data: {
            price: 21.8 
        },
        filters: {
            filterMoney(val) {
                return '¥' + val.toFixed(2) + '元'
            }
        }
    })
</script>

效果图:

局部过滤器.png

7. 本地存储

localStorage永久存储

// 添加数据;setItem的value值是字符串类型的数据
localStorage.setItem('name','张三');
// 获取数据
localStorage.getItem('name'); // 张三
// 删除数据
localStorage.removeItem('name');
// 清空
localStorage.clear();

sessionStorage临时会话存储

// 添加数据;setItem的value值是字符串类型的数据
sessionStorage.setItem('name','张三');
// 获取数据
sessionStorage.getItem('name'); // 张三
// 删除数据
sessionStorage.removeItem('name');
// 清空
sessionStorage.clear();

cookie

需要用live server打开

添加: document.cookie = 'username="张三"'

三. 指令与传值

1. 数据劫持(对象属性的配置)

value 给某个key添加值

writable 设置某个key可否被修改,默认为false

configurable 设置某个key可否被删除,默认为false

enumerable 设置当前对象能否枚举所有属性,默认为false

let obj = {}
        Object.defineProperty(obj,'msg',{
            value : '你好世界', 
            writable : true,
            configurable : true,
            enumerable : true
        })

        console.log(obj.msg);   // 你好世界

        obj.msg = 'hello world'
        // 删除一个属性
        // delete obj.msg
        console.log(obj.msg);

        // 枚举(罗列)一个对象的属性
        console.log(Object.keys(obj));

2. 自定义属性

3. 组件

4. 父传子

5. 子传父

6. 插槽

四. webpack与脚手架

五. todolist[微型项目]