• Vue--基础1


    Vue

    Vue是一个轻量级的前端框架,渐进式Javascript框架,它是当下国内很火的一个Javascript MVVM库,它是以数据驱动和组件化的思想构建的。

    相比较于Jquery的DOM操作,Vue是数据驱动的,不需要再通过获取标签对象在进行操作。通过一些特殊的语法,把DOM和数据绑定在一起,一旦你创建了绑定,DOM将和数据保持同步,每当数据发生变化,DOM也会相应的更新。

    Vue管理页面很强大,它可以控制一个页面的一个标签,也可以控制一个页面,甚至控制一个项目,我们只需要把一个项目的页面一次性传到前台,不需要的可以先保存在客户端的内存缓存中,当需要的时候在进行加载

    Vue的优点

    • 综合了Angular和React的优点,上手快(一手文档是中文),完全开源免费
    • 单页面的Web运用,服务于移动端,只需要向后台请求数据就可以了
    • MVVM设计模式
    • 数据驱动,在缓存中根据数据处理DOM,再渲染给真实DOM
    • 页面缓存机制--虚拟DOM
    • 数据的双向绑定

    MVVM模式

    MVVM------Model-View-ViewModel

    下图描述了Vue中ViewModel是如何和View以及Model进行交互的。

    ViewModel是Vue.js的核心,它是一个Vue实例。Vue实例是作用于某一个HTML元素上的,这个元素可以是HTML的body元素,也可以是指定了id的某个元素。

    当创建了ViewModel后,双向绑定是如何达成的呢?

    首先,我们将上图中的DOM Listeners和Data Bindings看作两个工具,它们是实现双向绑定的关键。
    从View侧看,ViewModel中的DOM Listeners工具会帮我们监测页面上DOM元素的变化,如果有变化,则更改Model中的数据;
    从Model侧看,当我们更新Model中的数据时,Data Bindings工具会帮我们更新页面中的DOM元素。

    Hello World示例

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title>Hello World示例</title>
    	</head>
    
    	<body>
    		<!--这是我们的View-->
    		<div id="app">
    			{{ message }}
    		</div>
    	</body>
    	<script src="js/vue.js"></script>
    	<script>
    		// 这是我们的Model
    		var exampleData = {
    			message: 'Hello World!'
    		}
    
    		// 创建一个 Vue 实例或 "ViewModel"
    		// 它连接 View 与 Model
    		new Vue({
    			el: '#app',
    			data: exampleData
    		})
    	</script>
    </html>
    

    使用Vue的过程就是定义MVVM各个组成部分的过程的过程

    1. 定义View
    2. 定义Model
    3. 创建一个Vue(ViewModel)实例,用于连接View和Model

    挂载点

    在上述示例中,通过挂载点进行Vue实例绑定,进行了页面绑定

    选项对象el属性指向View,el:"#app"表示该Vue实例挂载到<div id="app">...</div>这个元素,data属性指向Model,data: exampleData表示我们的Model是exampleData对象。

    Vue挂载点的注意事项:

    1. 挂载点只遍历第一个匹配的结果
    2. html与body标签不可以作为挂载点
    3. 挂载点的只一般就采用id选择器(唯一性)

    插值表达式与过滤器

    在Vue中有很多种数据绑定方式,最基础的形式是文本插值,使用一对{{ }}包裹变量,如运行{{ message }}会被数据对象的message属性替换,所以页面会输出Hello World!

    <div id="app">
        <!-- 插值表达式 -->
        <!-- 可以进行数据处理 -->
        <h1>{{ msg.split('')[0] }}</h1>
        <h2>{{ info + msg }}</h2>
        <h3>{{ num * num }}</h3>
        <!--num作为过滤器的参数,过滤器的返回值就是表达式的值-->
        <h4>{{ num | my_filter }}</h4>
        <!--过滤器f1被传递了四个参数a,b,c,d,并将过滤结果做出f2的参数再过滤-->
        <h4>{{ a, b | f1(c, d) | f2 }}</h4>
        <h4>{{ arr | f3 }}</h4>
    </div>
    
    <script src="js/vue.js"></script>
    <script>
        
        // 创建过滤器
        Vue.filter('my_filter', function (v) {
            console.log(v);
            return 999
        });
    	
        Vue.filter('f1', function (a, b, c, d) {
            console.log(a, b, c, d);
            // return '过滤后的逻辑结果'
            return a + b + c + d
        });
    
        Vue.filter('f2', function (v) {
            console.log(v);
            return v * v
        });
    
        Vue.filter('f3', function (v) {
            let new_arr = [];
            for (n of v) {
                if (n >= 60) {
                    new_arr.push(n)
                }
            }
            return new_arr
        });
    
        // 产生Vue实例对象
        new Vue({
            el: '#app',
            // data成员用来为vue控制的变量提供值
            data: {
                msg: 'message',
                info: '信息',
                num: 10,
                a: 1,
                b: 2,
                c: 3,
                d: 4,
                arr: [23, 59, 62, 97]
            }
        })
    </script>
    
    

    Vue指令

    • 文本指令
    • 属性指令
    • 事件指令
    • 表单指令
    • 条件指令

    文本指令

    格式:

    1. {{ 变量表达式 }}:渲染变量
    2. v-text='变量表达式':渲染变量
    3. v-html='html标签' :渲染可被解析的html标签
    4. v-once='被限制的变量':内容还是通过上面三种进行渲染, 如果内容中包括被限制的变量,则渲染后的内容不会发生变化
    <div id="app">
        <!-- 文本指令 -->
        <h2 v-text="msg + '!!!'"></h2>
        <h2 v-text="htm"></h2>
        <h2 v-html="htm"></h2>
    
        <input type="text" v-model="msg">
        <h3>{{ msg }}</h3>
        <!--一次性渲染,插值表达式中的任何一个变量被限制,整个结果就不可变-->
        <h3 v-once="htm">{{ msg + htm }}</h3>
        <!-- 只要有v-once,这个标签渲染完成后就不会发生变化 -->
        <h3 v-once>{{ msg }}</h3>
    </div>
    <script src="js/vue.js"></script>
    <script>
        new Vue({
            el: '#app',
            data: {
                msg: 'message',
                htm: '<i>标签内容是否被解析</i>'
            }
        })
    </script>
    

    属性指令

    格式:v-bind:属性名='属性值',可以简写成 :属性名='属性值'

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>属性指令 - 控制样式</title>
        <style>
            .div {
                 200px;
                height: 200px;
                background-color: red;
            }
    
            .box {
                 200px;
                height: 200px;
            }
            .blue {
                background-color: blue;
            }
            .green {
                background-color: green;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <div class="div" style="border-radius: 50%"></div>
            <!--属性指令:v-bind:属性名="属性值" => v-bind: 可以简写为 :
            eg: v-bind:style="{color: 'red'}"
            -->
    
            <!--自定义属性:没有太多应用场景-->
            <!--只是普通的自定义属性-->
            <div abc="xyz"></div>  
            <!-- 通过Vue进行变量替换 -->
            <div v-bind:abc="xyz"></div>
    
            <!--title属性-->
            <div :title="xyz" class="div" style="border-radius: 50%"></div>
    
            <!--style属性-->
            <!--1)变量:变量的值为字典-->
            <div :style="my_style"></div>
            <!--2)字典中的多个变量-->
            <div :style="{ w, height: h, background: b}"></div>
    
            <!--class属性-->
            <!--<div class="box blue"></div>-->
            <div :class="c"></div>
            <div :class="[c1, c2]"></div>
            <div :class="[c1, 'blue']"></div>
            <!--x为类名,是否生效有变量y(true|false)值决定-->
            <!-- x只能是类名,不可以通过data进行变量替换 -->
            <div :class="{x: y}"></div>
            <div :class="[{'box': true}, c2]"></div>
        </div>
    </body>
    <script src="js/vue.js"></script>
    <script>
        new Vue({
            el: '#app',
            data: {
                xyz: 'ABC',
                my_style: {
                     '100px',
                    height: '100px',
                    'background-color': 'cyan',
                    borderRadius: '50%'
                },
                w: '50px',
                h: '50px',
                b: 'red',
                c: 'box blue',
                c1: 'box',
                c2: 'green',
                y: true,
            }
        })
    </script>
    </html>
    

    事件指令

    格式:v-on:指令="fn变量",可以简写成 @指令="fn变量"

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>事件指令</title>
        <style>
            .div1 {
                 200px;
                height: 200px;
                background-color: red;
            }
    
            /*没有vue,不显示,有vue,会移除该属性 => 没有闪烁的显示内容*/
            [v-cloak] {
                display: none;
            }
            
            div {
                 50px;
                height: 50px;
                background-color: red;
                border-radius: 50%;
                text-align: center;
                line-height: 50px;
                color: white;
                cursor: pointer;
            }
        </style>
    </head>
    
    <body>
        <div id="app" v-cloak>
            <!--事件指令 v-on:事件名="fn变量" => v-on: 可以简写为 @
            v-on:click="clickAction"
            @dblclick="dblclickAction"
            -->
    
            <!--内容操作:每点一次,内容+1-->
            <h2 v-once="num">{{ num }}</h2>
            <h2>{{ num }}</h2>
            <div v-on:click="clickAction" class="div1">{{ num }}</div>
    
            <hr>
            <!--样式操作:点击切换背景颜色-->
            <div @click="changeColor" class="div1" :style="{backgroundColor: bgColor}"></div>
            <!--样式操作:点击切换整体样式-->
            <div @click="changeStyle" :style="my_style"></div>
            
             <!--没有传值默认传 事件对象 -->
            <div @click="btnClick1">{{ msg }}</div>
            <!--方法()不会直接调用方法,而是在点击触发后进行传参,接收到的参数就是传入的参数-->
            <div @click="btnClick2(1, msg)">{{ msg }}</div>
            <!--一旦书写 方法() 就不再传入事件对象,通过 $event 手动传入事件对象-->
            <div @click="btnClick3(msg, $event, $event)">{{ msg }}</div>
    
        </div>
    </body>
    <script src="js/vue.js"></script>
    <script>
        let app = new Vue({
            el: '#app',
            data: {
                num: 100,
                bgColor: 'cyan',
                my_style: {
                     '100px',
                    height: '100px',
                    backgroundColor: 'orange'
                },
                msg: 'box'
            },
            methods: {
                clickAction: function () {
                    // console.log(app.num);
                    // console.log(this.num);
                    this.num ++
                },
                changeColor () {  // 方法的写法
                    // if (this.bgColor == 'cyan') {
                    //     this.bgColor = 'blue'
                    // } else {
                    //     this.bgColor = 'cyan'
                    // }
                    // python:this.bgColor = 'cyan' if this.bgColor != 'cyan' else 'blue'
                    this.bgColor = this.bgColor != 'cyan' ? 'cyan' : 'blue'
                },
                changeStyle: () => {  // 这种写法,内部拿不到this(指向的是window)
                    app.my_style = app.my_style.backgroundColor == 'orange' ?
                        {
                             '200px',
                            height: '200px',
                            backgroundColor: 'yellow'
                        }
                        :
                        {
                             '100px',
                            height: '100px',
                            backgroundColor: 'orange'
                        }
                },
                btnClick1(ev) {
                    console.log(ev);
                    console.log(ev.clientX);
                },
                btnClick2(a, b, c) {
                    console.log(a, b, c)
                },
                btnClick3(a, b, c) {
                    console.log(a, b, c)
                },
            }
        });
        // 外界访问实例内部的数据
        console.log(app);
        console.log(app.$el);
        console.log(app.$data.num);
        console.log(app.num);
    
    </script>
    </html>
    

    表单指令

    格式:v-model="变量":无简写方式

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>表单指令</title>
    </head>
    <body>
        <div id="app">
    
            <form action="">
                <!--表单指令:v-model="变量"-->
    
                <!--双向绑定:一个地方修改值,所有地方的数据都会被更新-->
                <div>
                    <input type="text" v-model="info" name="usr">
                    <input type="password" v-model="info" name="pwd">
                    <p>{{ info | infoFilter }}</p>
                </div>
    
                <div>
                    <!--单选框:v-model="变量存放的是某个单选框的value值,代表该选框选中"-->
                    男<input type="radio" name="sex" value="male" v-model="sex_val">
                    女<input type="radio" name="sex" value="female" v-model="sex_val">
                </div>
    
    
                <div>
                    <!--单独的复选框:v-model="true|false代表该选框是否选中"-->
                    是否同意<input v-model="cb_val" value="yes" type="checkbox" name="agree">
                </div>
    
                <div>
                    <!--群复选框:v-model="存放选中选框value的数组"-->
                    男<input v-model="cbs_val"  value="male" type="checkbox" name="hobby">
                    女<input v-model="cbs_val"  value="female" type="checkbox" name="hobby">
                    哇塞<input v-model="cbs_val"  value="others" type="checkbox" name="hobby">
                    <p>{{ cbs_val }}</p>
                </div>
    
                <div>
                    <input type="submit">
                </div>
            </form>
            
        </div>
    </body>
    <script src="js/vue.js"></script>
    <script>
        Vue.filter('infoFilter', (info) => {
            return info ? info : '初始内容'
        });
    
        new Vue({
            el: '#app',
            data: {
                info: '',
                // 默认值可以决定单选框默认选项
                sex_val: 'female',
                // 默认值为true,单一复选框为选中,反之false为不选中
                cb_val: 0,
                // 数组中存在的值对应的复选框默认为选中状态
                cbs_val: ["others"]
            }
        })
    </script>
    </html>
    

    条件指令

    格式:

    1. v-if="true|false":条件为true时显示内容,且屏蔽下方分支为false时隐藏不渲染到页面
    2. v-else-if="true|false"v-if不成立时才看v-else-ifv-else-if成立会屏蔽下方分支
    3. v-else="true|false"v-ifv-else-if都不成立,v-else才成立
    4. v-show="true|false":条件为true时显示内容,为false时隐藏渲染到页面,但是display:none
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <style>
            .btn1 {  400px; }
            .box {
                 200px;
                height: 200px;
                float: left;
            }
            .wrap:after {
                content: '';
                display: block;
                clear: both;
            }
            .red { background-color: red }
            .blue { background-color: blue }
        </style>
        <style>
            .btn-wrap { height: 25px }
            .btn {
                 100px;
                height: 25px;
                float: left;
            }
            .page {
                 300px;
                height: 150px;
            }
            .p1 { background-color: pink }
            .p2 { background-color: yellow }
            .p3 { background-color: green }
        </style>
    </head>
    <body>
        <div id="app">
            <!--条件指令
            v-if="true|false"
            v-show="true|false"
            -->
            <button class="btn1" @click="btnClick">{{ title }}</button>
            <div class="wrap">
                <!--v-if隐藏时不渲染,v-show隐藏时用display:none渲染-->
                <!--v-if隐藏时在内存中建立缓存,可以通过key属性设置缓存的键-->
                <div class="box red" v-if="is_show" key="box_red"></div>
                <div class="box blue" v-show="is_show"></div>
            </div>
    
            <div class="btn-wrap">
                <button class="btn" @click="changePage('pink')">粉</button>
                <button class="btn" @click="changePage('yellow')">黄</button>
                <button class="btn" @click="changePage('green')">绿</button>
            </div>
            <div>
                <!--v-if成立会屏蔽下方分支、v-else-if一样f成立会屏蔽下方分支-->
                <!--v-if不成立时才看v-else-if、v-else-if成立会屏蔽下方分支-->
                <!--v-if、v-else-if都不成立,v-else才成立-->
                <div class="page p1" v-if="page == 'pink'"></div>
                <div class="page p2" v-else-if="page == 'yellow'"></div>
                <div class="page p3" v-else></div>
            </div>
        </div>
    </body>
    <script src="js/vue.js"></script>
    <script>
        new Vue({
            el: '#app',
            data: {
                title: '隐藏',
                is_show: true,
                page: localStorage.page || 'pink'
            },
            methods: {
                btnClick() {
                    this.title = this.title == '隐藏' ? '显示' : '隐藏';
                    this.is_show = !this.is_show;
                },
                changePage(page) {
                    this.page = page;
                    localStorage.page = page;  // 永久缓存
                    // sessionStorage.page = page;  // 临时缓存
                }
            }
        })
    </script>
    
    </html>
    

    pre指令

    格式:v-pre,直接放在标签中就会生效,只要标签中有v-pre指令,表示该标签及其子标签都会解除Vue控制

    <div id="app">
        <p v-pre>
        <!--v-pre的内部解除vue控制,都是原义输出-->
        <!-- 页面显示:{{ msg }},此时{{ }}不是插值表达式 -->
        <p>{{ msg }}</p>  
        <!-- html解析为:<span v-on="abc"></span>,此时的v-on不是指令,abc也不是变量,不会报错 -->
        <span v-on="abc"></span>
        </p>
    </div>
    
    <script>
        new Vue({
            el: '#app',
            data: {
                msg: "message"
            }
        })
    </script>
    

    循环指令

    格式:

    1. 列表的遍历:v-for="(值[, 索引] in 列表"
    2. 字典的遍历:v-for="(值[, 键[, 索引]]) in 字典"
    <div id="app">
        <!--列表的循环-->
        <div>
            <!--只取 值-->
            <p p v-for="i in arr"> 值:{{ i }} </p>
            <hr>
    
            <!--只取 值和索引-->
            <p v-for="(i, ind) in arr">第{{ ind + 1}}个值:{{ i }}</p>
            <hr>
        </div>
    
        <!--字典的循环-->
        <div>
            <!--取value值-->
            <p v-for="v in stu">
                {{ v }}
            </p>
            <hr>
            <!--取value,key值-->
            <p v-for="(v, k) in stu">
                {{ k }}: {{ v }}
            </p>
            <hr>
    
            <!--取value,key,索引值-->
            <p v-for="(v, k, ind) in stu">
                {{ k, v, ind | f1 }}
            </p>
            <hr>
        </div>
        <!--列表套字典,循环遍历-->
        <div>
            <!--以表格的形式呈现-->
            <table border="1px" cellspacing="0">
                <tbody>
                <tr>
                    <th>项次</th>
                    <th>姓名</th>
                    <th>年龄</th>
                    <th>性别</th>
                </tr>
                <tr v-for="(stu, ind) in stus">
                    <td>{{ ind + 1 }}</td>
                    <td v-for="v in stu">{{ v }}</td>
                </tr>
                </tbody>
            </table>
            <hr>
    
            <!--取出所有的值,键,索引-->
            <!--以如下形式显示
                name: hades | age:27| gender:男
                name: Tom | age:13 | gender:男
            -->
            <p v-for="stu in stus">
                <span v-for="(v, k, ind) in stu">
                    <!--{{i?' | ' : ''}}{{k}}:{{v}}-->
                    {{ ind | f2 }}{{ k }}: {{ v }}
                </span>
            </p>
        </div>
    
    </div>
    
    <script>
        new Vue({
            el: '#app',
            data: {
                arr: [1, 3, 5, 7, 4],
                stu: {
                    'name': 'hades',
                    'age': 27,
                    'gender': 'mela'
                },
                stus: [
                    {
                        'name': 'hades',
                        'age': 26,
                        'gender': 'male'
                    },
                    {
                        'name': 'tom',
                        'age': 13,
                        'gender': 'male'
                    },
                    {
                        'name': 'jerry',
                        'age': 18,
                        'gender': 'female'
                    },
                    {
                        'name': 'bonnie',
                        'age': 16,
                        'gender': 'female'
                    }
                ]
            },
    
            filters: {
                f1(k, v, ind) {
                    return k + ':' + v + '(' + ind + ')';
                    // return `${k}:${v}(${ind})`
                },
    
                f2(i) {
                    // i 为0 则为假,返回'',否则返回' | '
                    return i ? ' | ' : ''
                }
            }
        })
    </script>
    

    案例

    需求:一个评论框,用户输入评论后,把值显示在评论框下方,同时清空评论框,当用户点击评论时,删除评论

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>test</title>
        <style>
            /*鼠标悬浮字体变红,光标变为小手爪*/
            p:hover {
                color: red;
                cursor: pointer;
            }
        </style>
    </head>
    <body>
    <div id="app">
        <input type="text" v-model="info">
        <button @click="addMsg">提交</button>
        
        <p v-for="(msg, i) in msgs" @click="delMsg(i)">
            <span>#{{ i+ 1 }}楼 </span>{{ msg }}
        </p>
    </div>
    </body>
    <script src="js/vue.js"></script>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                info: '',
                msgs: JSON.parse(sessionStorage.msgs || '[]'),
            },
            methods: {
                addMsg() {
                    let info = this.info;
                    // console.log(info);
                    if (info) {
                        // this.msgs.push(this.info);  // 尾增
                        this.msgs.unshift(info);  // 首增
                        // 内容提交完成后,清空输入框内容
                        this.info = '';
                        // 保存在前台,当页面关闭后再次打开,数据不会发生变化
                        sessionStorage.msgs = JSON.stringify(this.msgs)
                    }
                },
                
                delMsg(i) {
                    //splice(开始的位置,删除的个数,增加的值(可以是多个值))
                    this.msgs.splice(i, 1);
                    sessionStorage.msgs = JSON.stringify(this.msgs)
                }
            }
        })
    </script>
    </html>
    
  • 相关阅读:
    PHP将unicode转utf8最简法
    【搬运】systemctl 命令完全指南
    【转】Linux下apache/httpd服务启动与停止
    【转】Apache Digest验证
    Apache安装及配置ssl
    PHP获取某个表与其他表的关联关系算法
    Mysql查看版本,端口命令
    解决Windows下网络原因Composer安装失败问题
    kafka总结
    关于自增加
  • 原文地址:https://www.cnblogs.com/Hades123/p/11420642.html
Copyright © 2020-2023  润新知