Vue全家桶--04 Vue.js 核心技术

4.1 Vue入门开发

4.1.1 VS Code创建工程

4.1.2 创建HTML和安装Vue

npm instal vue@2.6.10

4.1.3 编写html代码

<!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>Document</title>
</head>
<body>
    <div >
        <!--{{}} 用于标签体内显示数据 -->
        hello,{{ msg }}<br/>
        <!--v-model进行数据的双向绑定-->
        <input type="text" v-model="msg" />
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        new Vue({
            el:'#app',//指定被Vue管理的入口,值为选择器,不可以指定body或者html
            data:{ //用于初始化数据,在Vue实例管理的Dom节点下,可通过模板请求语法来引用
                msg:"vue.js"
            }
        });
        
    </script>
</body>
</html>

4.2 MVVM模型

什么是MVVM模型?

MVVM:Model--View--ViewModel,一种软件架构的风格

*Model----模型,数据对象,(data中的属性)

*View----视图,模板页面,用于渲染

*ViewModel----视图模型,本质上就是Vue实例

**核心思想:通过数据驱动视图!!!

**把需要改变视图的数据初始化到Vue中,然后再通过修改Vue中的数据,从而实现对视图的更新

**声明式编程----按照Vue的特定语法进行声明开发,就可以实现对应功能,不需要我们直接操作Dom元素

**命令式编程----类似Jquery,需要手动去操作Dom才能实现对应功能

4.3 Vue Devtools插件

Vue Devtools插件安装,谷歌浏览器

4.4 模板数据绑定渲染

4.4.1 双大括号语法{{}}

格式:{{ 表达式 }}

作用:使用在标签体中,用于获取数据;可以使用JS表达式

<!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>Document</title>
</head>
<body>
    <div >
        <h3>双大括号</h3>
        <p>{{ msg }}</p>
        <p>{{ num + 1 }}</p>
        <input type="text" v-model="num" >
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                msg:'hello',
                num:1
            }
        });
    </script>
</body>
</html>

4.4.2 一次性插值 v-once

通过使用 v-once 指令,也可以执行一次性的插值,当数据改变时,插值处的内容不会更新。

<body>
    <div >
        <h3>v-once 一次性插值</h3>
        <p>{{ msg }}</p>
        <p v-once>{{ msg }}</p>
        <input type="text" v-model="msg" >
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                msg:'hello'
            }
        });
    </script>
</body>

4.4.3 输出HTML指令 v-html

格式:v-html='xxx'

作用:如果是HTML格式数据,双大括号会将数据解释为普通文本,为了输出真正的HTML,你需要使用v-html指令。

   Vue为了防止XSS攻击,在此指令上做了安全处理,当发现输出内容有script标签时,则不渲染。

****XSS攻击主要利用JS脚本注入到网页中,读取Cookie值(Cookie一般存储了登录身份信息),读取到了发生到黑客服务器,从而黑客可以使用你的账户做非法操作;XSS攻击还可以在你进入到支付时,跳转到钓鱼网站。

<body>
    <div >
            <h3>3.指令输出真正的 HTML 内容 v-html</h3>
            {{contentHtml}}
            <!-- v-html:
                1.如果输出的内容是html数据,双大括号讲数据以普通文本方式进行输出,
                为了输出真正html的效果,就需要使用v-html指定
                2.为了防止 XSS攻击
             -->
            <p v-html='contentHtml'></p>
            <p v-html='contenthtml2'></p>
    
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                msg:'hello',
                contentHtml:"<span >123</span>",
                contenthtml2:`<span >123
                    <script>alert('12');<\/script>
                </span>`
            }
        });
    </script>
</body>

4.4.4 v-bind 元素绑定指令

完整格式:v-bind:元素的属性名='xxxx'

缩写格式: :元素的属性名='xxx'

作用:将数据动态绑定到指定的元素上

<body>
    <div >
            <h3>4.元素绑定指令 v-bind</h3>
            <img  v-bind:src="imgUrl" alt="">
             <img  :src="imgUrl" alt="">
             <a :href="baiduUrl" target="_blank" >跳转</a>
    
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                msg:'hello',
                contentHtml:"<span >123</span>",
                contenthtml2:`<span >123
                    <script>alert('12');<\/script>
                </span>`,
                imgUrl:'https://www.cnblogs.com/images/logo.svg?v=R9M0WmLAIPVydmdzE2keuvnjl-bPR7_35oHqtiBzGsM',
                baiduUrl:'https://www.baidu.com'
            }
        });
    </script>
</body>

4.4.5 v-on 事件绑定指令

完整格式:v-on:事件名称='事件处理函数名'

缩写格式:@事件名称="事件处理函数名" 注意:@后面没有冒号

作用:用于监听DOM事件

<body>
    <div >
        <h3>5.v-on 事件绑定</h3>
        <input type="text" v-model='calcute'>
        <button v-on:click="add">点击+1</button>
        <button @click="add2(12)">点击+2</button>

    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: 'hello',
                contentHtml: "<span >123</span>",
                contenthtml2: `<span >123
                    <script>alert('12');<\/script>
                </span>`,
                imgUrl: 'https://www.cnblogs.com/images/logo.svg?v=R9M0WmLAIPVydmdzE2keuvnjl-bPR7_35oHqtiBzGsM',
                baiduUrl: 'https://www.baidu.com',
                calcute: 10
            },
            methods: {
                add: function () {
                    this.calcute = this.calcute + 1;
                    return this.calcute;
                },
                add2: function (value) {
                    this.calcute = this.calcute + value - 0;
                    return this.calcute;
                }
            }
        });
    </script>
</body>

4.5 计算属性和监听器

4.5.1 计算属性 computed

computed选项定义计算属性

计算属性类似于methods选择中定义的函数,区别:

**计算属性 会进行缓存,只在相关响应式依赖发生改变时它们才会重新求值

**函数 每次都会执行函数体进行计算

<body>
    <div >
        <h3> 计算属性和监听器 </h3>
        chinese: <input type="text" v-model="chinesescore"> <br />
        english: <input type="text" v-model="englishscore"> <br />

        <!-- v-model 调用函数时,不能少了() -->
        total: <input type="text" v-model="add()"><br>
        <!-- v-model 调用计算属性时 不需要(),因为它是个属性 -->
        total(computed): <input type="text" v-model="sum"><br>

    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                chinesescore: 90,
                englishscore: 98
            },
            methods: {
                add: function () {
                    var total = (this.chinesescore - 0) + (this.englishscore - 0);
                    return total;
                }
            },
            computed:{
                sum:function(){
                    var total = (this.chinesescore - 0) + (this.englishscore - 0);
                    return total;
                }
            }
        });
    </script>
</body>

4.5.2 计算属性(双向绑定)

计算属性默认只有getter,不过需要时可以提供一个setter,可以实现双向绑定

<body>
    <div >
        <h3> 计算属性和监听器 </h3>
        chinese: <input type="text" v-model="chinesescore"> <br />
        english: <input type="text" v-model="englishscore"> <br />

        <!-- v-model 调用函数时,不能少了() -->
        total: <input type="text" v-model="add()"><br>
        <!-- v-model 调用计算属性时 不需要(),因为它是个属性 -->
        total(computed): <input type="text" v-model="sum"><br>
        total(computed get/set): <input type="text" v-model="sum2" name="" >
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                chinesescore: 90,
                englishscore: 98
            },
            methods: {
                add: function () {
                    var total = (this.chinesescore - 0) + (this.englishscore - 0);
                    return total;
                }
            },
            computed:{
                sum:function(){
                    var total = (this.chinesescore - 0) + (this.englishscore - 0);
                    return total;
                },
                sum2:{
                    get:function(){
                        console.log("计算属性 sum2.get 被调用!");
                        return (this.chinesescore - 0) + (this.englishscore - 0);
                    },
                    set:function(newvalue){
                        console.log("计算属性 sum2.set 被调用!");
                        var avg = newvalue / 2;
                        this.chinesescore = avg;
                        this.englishscore = avg;
                    }
                }
            }
        });
    </script>
</body>

4.5.3 监听器 watch

**当属性数据发生变化时,对应属性的回调函数会自动调用,在函数内部进行计算

**通过watch选项或者vm实例的$watch()来监听指定的属性

<body>
    <div >
        chinese: <input type="text" v-model="chinesescore"> <br />
        englist: <input type="text" v-model="englishscore"> <br />

        总分(监听器):<input type="text" v-model="sumScore3"><br>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                chinesescore: 89,
                englishscore: 88,
                sumScore3: 177
            },
            watch: {
                chinesescore: function (newvalue, oldvalue) {
                    this.sumScore3 = (newvalue - 0) + (this.englishscore - 0)
                }
            }
        });

        vm.$watch('englishscore', function (newvalue) {
            this.sumScore3 = (newvalue - 0) + (this.chinesescore - 0)
        });
    </script>
</body>

4.6 Class与Style v-bind 绑定

***v-bind 单向绑定!只有数据更改了,视图才会更改!视图更改了,数据是不会更改的!双向绑定是可以的都会更改!

通过 class 列表和 style 指定样式是数据绑定的一个常见需求。它们都是元素的属性,都用 v-bind 处理,其中表达

式结果的类型可以是:字符串,对象或者数组。

语法格式:v-bind:class='表达式' 或 :class='表达式' / v-bind: 或 :

    *class的表达式可以为:

      字符串---- :class="activeClass"

      对象---- :class="{active:isActive,error:hasError}"

      数组---- :class="['active','error']" 注意这里要加上单引号,不然是获取data中的值

    *style的表达式一般为对象

      :px'}"

      注意:对象中的value值activeColor和fontSize是data中的属性

<!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>Document</title>
    <style>
        .active {
            color: green;
        }

        .delete {
            background-color: aqua;
        }

        .error {
            font-size: 35px;
        }
    </style>
</head>
<body>
    <div >
        <h3>class绑定,v-bind:class或者:class</h3>
        <p v-bind:class="aciveClass">字符串表达式</p>
        <!-- key值是样式名,value是data中的属性值,为true渲染 -->
        <p :class="{delete:isDel,error:isErr}">对象表达式</p>
        <p :class="['active','delete','error']">数组表达式</p>
        <h3 :>style绑定 v-bind:style或者:style</h3>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                aciveClass: 'active',
                isDel: true,
                isErr: false,
                activrColor:'blue'
            }
        });
    </script>
</body>
</html>

4.7 条件渲染 v-if

4.7.1 v-if 是否渲染当前元素

   v-else-if

   v-else

**v-show与v-if 类似,v-show只是元素始终会被渲染并保留在DOM中,通过切换元素的Css属性display来显示或者隐藏

<body>
    <div >
        <h3>v-if 条件渲染</h3>
        <input v-model='seen' type="checkbox" name="" >勾选后显示
        <div v-if='seen' :class='activeClass'></div>
        <p v-else>红块不显示了</p>

        <br>
        <h3>v-show 条件显示</h3>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm=new Vue({
            el:'#app',
            data:{
                activeClass:'box',
                seen:true
            }
        });
    </script>
</body>

4.7.2 v-if与v-show比较

**什么时候元素被渲染?

  v-if如果在初始条件为假,则什么也不做,每当条件为真时,都会重新渲染条件元素

  v-show不管初始条件是什么,元素总是会被渲染,并且基于CSS进行切换

**使用场景选择

  v-if有更高的切换开销,

  v-show有更高的初始渲染开销

  因此,如果需要非常频繁地切换,则使用v-show比较好;如果在运行后条件很少改变,则使用v-if较好。

4.8 列表渲染 v-for

4.8.1 迭代数组

  v-for="(alias,index) in array"

  alias:数组元素迭代的别名;index:数组索引值从0开始(可选)

4.8.2 迭代对象的属性

  v-for="(value,key,index) in Object"

  value:每个对象的属性值;key:属性名(可选);index:索引值(可选)

4.8.3 可以of替代in作为分隔符

DEMO

<body>
    <div >
        <h3>v- for 遍历 列表渲染/迭代数组 </h3>
        <ul>
            <!--
                 e代表数组emp中的一个元素,index代表数组的下标/索引值
                 注意:使用key特殊属性,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素

                 注意:可以使用of或者in作为分隔符
            -->
            <li v-for=' (e,index) in emp' :key="index">
              {{index+1}},  {{e.name}},{{e.salary}}
            </li>
        </ul>

        <h3>迭代对象</h3>
        <ul>
            <!-- value key index 循环要注意顺序
                value 对象的属性值
                key 对象的属性名
                index 索引值
            -->
            <li v-for="(value,key,index) in person">
                {{index}},{{key}},{{value}}
            </li>
        </ul>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>

        new Vue({
            el: '#app',
            data: {
                emp: [
                    { name: 'zq', salary: 2000 },
                    { name: 'q1', salary: 1800 },
                    { name: 'q2', salary: 1500 }
                ],
                person:{
                    name:'xxx0',
                    sex:'man',
                    old:17,
                    salary:1500
                }
            }
        });

    </script>

</body>

4.9 事件处理 v-on

4.9.1 事件处理方法

完整格式:v-on:事件名="函数名" 或 v-on:事件名="函数名(参数......)"

缩写格式:@事件名="函数名" 或 @事件名="函数名(参数......)" 注意:@后面没有冒号

event:函数中的默认形参,代表原生DOM事件

  *当调用的函数,有多个参数传入时,需要使用原生DOM事件,则通过$event作为实参传入

作用:用于监听DOM事件

<body>
    <div >
        <h3>事件处理方法 v-on v-on:事件/@事件</h3>
        <button v-on:click="say">say {{ msg }}</button>
        <!-- $event 代表的是原生的Dom事件 -->
        <button @click="warm('zq',$event)">warm</button>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg:'hello'
            },
            methods: {
                say: function (event) {
                    alert(this.msg);
                    alert(event.target.tagName);
                },
                warm:function(value,$event){
                    alert(value+','+event.target.innerHTML);
                }
            }
        });
    </script>
</body>

4.9.2 事件修饰符

.stop 阻止单击事件继续传播 event.stopPropagation()

.prevent 阻止事件默认行为 event.preventDefault()

.once 点击事件将只会触发一次

<body>
    <div >
        <h3>事件修饰符</h3>
        <!--  防止单击事件继续传播 -->
        <div @click="todo">
            <button @click="dothis">单击事件会继续传播</button>
        </div>
        <br>
         <!-- .stop 阻止了单击事件的继续传播 -->
         <div @click="todo">
            <button @click.stop="dothis">阻止单击事件继续传播</button>
        </div>
        <br>
        <!--  阻止事件的默认行为 -->
        <a href="https://www.baidu.com" @click.prevent="dostop" target="_blank">baidu链接</a>
        <br>
        <br>
        <!--  点击事件只会触发一次 -->
        <button @click.once="doOnly">只触发一次</button>

    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg:'hello'
            },
            methods: {
                say: function (event) {
                    alert(this.msg);
                    alert(event.target.tagName);
                },
                warm:function(value,$event){
                    alert(value+','+event.target.innerHTML);
                },
                dothis: function () {
                    alert("dothis...");
                },
                todo: function () {
                    alert("todo");
                },
                dostop: function () {

                },
                doOnly: function () {
                    alert("doOnly");
                }
            }
        });
    </script>
</body>

4.9.3 按键修饰符

格式:v-on:keyup.按键名 或 @keyup.按键名

常用按键名:.enter

      .tab

      .delete(捕获删除或退格键)

      .esc

      .space

      .up

      .down

      .left

      .right

<body>
    <div >
        <h3>按键修饰符或按键码</h3>
        <input type="text" @keyup.enter="KeyEnter">
        <br>
        <input type="text" @keyup.space="KeySapce">
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg:'hello'
            },
            methods: {
                say: function (event) {
                    alert(this.msg);
                    alert(event.target.tagName);
                },
                warm:function(value,$event){
                    alert(value+','+event.target.innerHTML);
                },
                dothis: function () {
                    alert("dothis...");
                },
                todo: function () {
                    alert("todo");
                },
                dostop: function () {

                },
                doOnly: function () {
                    alert("doOnly");
                },
                KeyEnter: function () {
                    alert("当前按的是回车键!");
                },
                KeySapce:function(){
                    alert("当前按的是sapce键!");
                }
            }
        });
    </script>
</body>

4.10 表单数据双向绑定v-model

v-model 指令用于表单数据双向绑定,针对以下类型:

text 文本

textarea 多行文本

radio 单选按钮

checkbox 复选框

select 下拉框

<body>
    <div >
        <!-- @submit.prevent 阻止事件的默认行为,当前阻止的是action行为 -->
        <form action="#" @submit.prevent="addform">
            姓名(文本):<input type="text" v-model="userName">
            <br><br>

            性别(单选按钮):
            <input name="sex" type="radio" value="1" v-model='userSex' />男
            <input name="sex" type="radio" value="0" v-model='userSex' />女
            <br><br>

            技能(多选框):
            <span v-for="(e,index) in checkSkills">
                <input type="checkbox" name="skills" v-model='userSkill'  v-bind:value="e.code"><span>{{e.skillName}}</span>
            </span>
            <!-- <input type="checkbox" name="skills" value="java" v-model="userSkill">Java开发
            <input type="checkbox" name="skills" value="vue" v-model="userSkill">Vue.js开发
            <input type="checkbox" name="skills" value="python" v-model="userSkill">Python开发 -->
            <br><br>

            城市(下拉框):
            <select name="citys" v-model="chooseCity">
                <option v-for=" (e,index) in userCity" v-bind:value="e.code">
                    {{ e.cityName }}
                </option>
            </select>
            <br><br>

            说明(多行文本):<textarea cols="30" rows="5" v-model="desc"></textarea>
            <br><br>
            <button type="submit">提交</button>
        </form>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#demo',
            data: {
                userName: '',
                userSex: '1',
                userSkill: ['java', 'vue'],
                chooseCity: 'ks',
                userCity: [
                    { code: 'bj', cityName: '北京' },
                    { code: 'sh', cityName: '上海' },
                    { code: 'ks', cityName: '昆山' }
                ],
                checkSkills: [
                    { code: 'java', skillName: 'Java开发' },
                    { code: 'vue', skillName: 'Vue.js开发' },
                    { code: 'python', skillName: 'Python开发' }
                ],
                desc: '描述......'
            },
            methods: {
                addform: function () {
                    alert(this.userName + ', '
                        + this.userSex + ', '
                        + this.userSkill + ', '
                        + this.chooseCity + ', '
                        + this.desc)
                }
            }
        });
    </script>
</body>