前端 之 Vue初试

Vue简介

vue是以数据驱动的web渐进式框架

vue的优点:

  • 以数据驱动,不直接操作DOM,效率高
  • 单页面应用,减少请求页面次数,速度快
  • 数据的双向绑定,更新快
  • 虚拟DOM,开发操作数据,数据更新虚拟DOM,虚拟DOM渲染真实DOM
  • 组件化开发

vue的使用:

方式一:在官网下载js文件,添加到项目中
<script src="js/vue.min.js"></script>
方式二:引入CDN
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
或者:
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

Vue事件

实例

<div id="app"></div>

<script>
// new一个Vue就是一个实例
// 实例与页面对应挂载点的所有页面结构一一绑定
// 一个页面中可以出现多个实例(挂载点),建议只出现一个实例,且挂载点用id
new Vue({
    // 挂载点
    el: "#app"
})
</script>

数据 data

data为插件表达式中的变量提供数据 ,data中的数据可以通过Vue实例直接或间接访问

<div id="app">
    <!-- 插值表达式中存放的为变量,变量需要在vue实例的$data中进行初始化 -->
	{{ msg }}
</div>

<script>
var app = new Vue({
    el: "#app",
    data: {
        msg: "数据"
    }
})
	console.log(app.$data.msg);
    console.log(app.msg);
</script>

方法 methods

<style>
    .box { background-color: orange }
</style>
<div id='app'>
    // v-on:为事件绑定的指令
    <p class="box" v-on:click="pClick">测试</p>
	<p class="box" v-on:mouseover="pOver">测试</p>
</div>
<script>
    var app = new Vue({
    	el: '#app',
    	data:{
    		msg:'我是提示信息'
    	}
        // methods为挂载点内部提供方法的实现体
    	methods: {
            pClick:funcation () {
                // 点击测试
                alert(this.msg)
            },
            pOver:funcation () {
                // 悬浮测试
                alert(this.msg)
            }
    	}
    })
</script>

计算 computed

<div id="app">
 	<input type="text" v-model="a">
    <input type="text" v-model="b">
    <div>
        {{ c }}
    </div>
</div>

<script>
	// 一个变量依赖于多个变量
    new Vue({
        el: "#app",
        data: {
            a: "",
            b: "",
        },
        computed: {
        // 在computed中定义的变量的值等于绑定的函数的返回值
        // 绑定的函数中出现的所有vue变量都会被监听
            c: function() {
                // this代表该vue实例
                return this.a + this.b;
            }
        }
    })
</script>

监听 watch

<div id="app">
 	<input type="text" v-model="ab">
    <div>
        {{ a }}
        {{ b }}
    </div>
</div>

<script>
	// 多个变量依赖于一个变量
    new Vue({
        el: "#app",
        data: {
            ab: "",
            a: "",
            b: "",
        },
        watch: {
         // 后方绑定的函数就是监听前方的变量,变量值改变,函数被调用
            ab: function() {
                // 逻辑根据需求而定
                this.a = this.ab[0];
                this.b = this.ab[1];
            }
        }
    })
</script>

分隔符delimiters

<div id='app'>
    ${ msg }
</div>
<script>
    new Vue({
    	el: '#app',
    	data: {
    		msg: 'message'
    	},
    	// 为了防止与后端模板语法发生冲突,使用delimiters可以修改,数据的插入格式。
        delimiters: ['${', '}']
    })
</script>

生命周期钩子

  • 表示一个vue实例从创建到销毁的这个过程,将这个过程的一些时间节点赋予了对应的钩子函数
  • 钩子函数: 满足特点条件被回调的方法
new Vue({
    el: "#app",
    data: {
        msg: "message"
    },
    beforeCreate () {
        console.log("实例刚刚创建");
        console.log(this.msg);         
    },
    created () {
        console.log("实例创建成功, data, methods已拥有");
        console.log(this.msg);
    },
    mounted () {
        console.log("页面已被vue实例渲染, data, methods已更新");
    }
    // 拿到需求 => 确定钩子函数 => 解决需求的逻辑代码块
})

Vue指令

文本操作指令

<div id="app">
    <!-- 插值表达式 -->
    <p>{{ msg1 }}</p>
    <!-- 原文本会被msg替换 -->
    <p v-text="msg2">原文本</p>
    <!-- 可以解析带html标签的文本信息 -->
    <p v-html="msg3"></p>
    <!-- v-once控制的标签只能被赋值一次 -->
    <p v-once="msg3"  v-on:mouseover="action">{{ msg3 }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            msg1: '**msg1**',
            msg2: '<b>**msg2**</b>',
            msg3: '<b>**msg3**</b>',
        },
        methods: {
            action: function () {
                // var msg = this.$data.msg4;
                this.msg3 = '<i>**new msg3**</i>'
            }
        }
    })
</script>

斗篷指令

<style type="text/css">
    [v-cloak] { display: none; }
</style>
<div id="app" v-cloak>
    {{ msg }}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script type="text/javascript">
	new Vue({
		el: "#app",
		data: {
			msg: "message"
		}
	})
</script>
<!-- 避免页面闪烁-->

属性指令

<!-- 给自定义全局属性绑定变量 -->
<p v-bind:abc="abc"></p>
<!-- 以原字符串形式绑定全局属性 -->
<p v-bind:title="'abc'"></p>
<!-- 单类名绑定 -->
<p v-bind:class="c1"></p>
<!-- 多类名绑定 -->
<p v-bind:class="[c2, c3]"></p>
<!-- 类名状态绑定 -->
<p v-bind:class="{c4: true|false|var}"></p>
<!-- 多类名状态绑定 -->
<p v-bind:class="[{c5: true}, {c6: flase}]"></p>

<!-- 样式绑定 -->
<div :style="div_style"></div>
<div :style="{width: '100px', height: '100px', backgroundColor: 'blue'}"></div>
<script type="text/javascript">
	new Vue({
		el:"#app",
		data: {
            abc: "abc",
            c1: "p1",
            c2: "p2",
            c3: "p3",
			div_style: {
				width: "200px",
				height: "200px",
				backgroundColor: "cyan"
			}
		}
	})
</script>
<!-- v-bind: 指令可以简写为 : -->

属性指令示例:

<head>
    <style>
        .rDiv {
            width: 100px;
            height: 100px;
            background-color: red;
        }
        .gDiv {
            width: 200px;
            height: 50px;
            background-color: green;
        }
        .br {
            border-radius: 50%;
        }
    </style>
</head>
<div id="app">
    <!-- 属性指令:用vue绑定属性,将属性内容交给vue处理 -->
    <!-- 语法:v-bind:属性名="变量"  (v-bind: 可以简写为 :) -->
    <p class="" style="" v-bind:lin="oo" :wow="jj"></p>

    <!-- class 属性 -->
    <p :class="c1" @click="action1"></p>
    <!-- 多类名 -->
    <p :class="[c1, c2]"></p>
    <!-- 'br' 固定写死的数据,不再是变量 -->
    <p :class="[c1, 'br']"></p>

    <!-- style 属性 -->
    <!-- 一个变量:该变量值为{},{}内部完成一个个属性的设置 -->
    <p class="gDiv" :style="s1">12345</p>
    <!-- 一个{}:{}内一个个属性有一个个变量单独控制 -->
    <p class="gDiv" :style="{fontSize: fs, color: c}">67890</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            oo: 'lin',
            jj: 'wow',
            c1: 'rDiv',
            c2: 'br',
            s1: {
                fontSize: '30px',
                color: 'pink'
            },
            fs: '20px',
            c: 'orange'
        },
        methods: {
            action1: function () {
                if (this.c1 == 'rDiv') {
                    this.c1 = 'gDiv'
                } else {
                    this.c1 = 'rDiv'
                }
            }
        }
    })
</script>
</html>

事件指令

<!-- v-on: 指令 简写 @ -->
<!-- 不传参事件绑定,但事件回调方法可以获取事件对象 -->
<p @click="fn"></p>
<!-- ()可以传入具体实参 -->
<p @click="fn()"></p>
<!-- ()情况下,事件对象应该显式传入 -->
<p @click="fn($event)"></p>

事件指令示例:

<div id="app">
    <!-- v-on:事件名="函数名"  可以简写为 @事件名="函数名"  (v-on: => @)-->
    <p v-on:click="action1">{{ msgs[0] }}</p>
    <p @click="action2">{{ msgs[1] }}</p>

    <!-- 事件的传参 -->
    <ul>
        <li @click="liAction(100)">列表项1</li>
        <li @click="liAction(200)">列表项2</li>
        <li @click="liAction(300)">列表项3</li>
    </ul>
    <!-- 鼠标事件的对象:直接写函数名,默认将鼠标事件对象传入 -->
    <div @click="func1">func1</div>
    <!-- 鼠标事件的对象:一旦添加(),就必须手动传参,$event就代表鼠标事件对象 -->
    <div @click="func2($event, 'abc')">func2</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            msgs: ['11111', '22222']
        },
        methods: {
            action1: function () {
                alert(this.msgs[0])
            },
            action2: function () {
                alert(this.msgs[1])
            },
            liAction: function (num, msg) {
                console.log(num, msg)
            },
            func1: function (ev) {
                console.log(ev)
            },
            func2: function (ev, msg) {
                console.log(ev);
                console.log(msg)
            }
        }
    })
</script>

表单指令

  • 操作的是表单元素的value值
// 双向绑定
<input type="text" v-model="val" name="txt1">
<input type="text" v-model="val" name="txt2">
// 两个输入框绑定的是同一个val,那么其中一个input的内容改变会直接映射到另一个input上
// 单个复选框
// val默认为true(选框选中,提交给后台的为ck=on)
// val默认为false(选框未选中,不向后台提交该数据)
<input type="checkbox" v-model="val" name="ck">
// 多个复选框
// v-model绑定的是同一个变量
// 该变量的值为数组形式
// 出现在数组中的value对应的复选框默认为选中状态,eg: val: ['ppqiu', 'zqiu'] => 乒乓球,足球复选框默认选中
// 提交给后台数据: ck=ppqiu&ck=zqiu
篮球<input type="checkbox" value="lqiu" v-model="val" name="ck">
足球<input type="checkbox" value="zqiu" v-model="val" name="ck">
乒乓球<input type="checkbox" value="ppqiu" v-model="val" name="ck">
// 多个单选框
// v-model绑定的是同一个变量
// 该变量的值为每个单选框的value值,那么该单选框默认选中 eg: val: famale => 女单选框默认选中
// 提交给后台数据: sex=famale
男:<input type="radio" value="male" v-model="val" name="sex">
女:<input type="radio" value="famale" v-model="val" name="sex">

表单指令示例:

<div id="app">
    <!-- v-model针对于表单元素 -->
    <form action="" method="get">
        <!-- 1、双向绑定:服务于文本输入框 -->
        <!-- v-model存储的值为输入框的value值 -->
        <div>
            <input type="text" name="usr" v-model="in_val">
            <input type="password" name="ps" v-model="in_val" >
            <textarea name="info" v-model="in_val"></textarea>
        </div>

        <!-- 2、单选框 -->
        <div>
            <!-- 单选框是以name进行分组,同组中只能发生单选 -->
            <!-- v-model存储的值为单选框的value值 -->
            男:<input type="radio" name="sex" value="" v-model="ra_val">
            女:<input type="radio" name="sex" value="" v-model="ra_val">
            {{ ra_val }}
        </div>

        <!-- 3、单一复选框 -->
        <!-- v-model存储的值为true|false -->
        <!-- 或者为自定义替换的值 -->
        <div>
            <input type="checkbox" v-model='sin_val' true-value="选中" false-value="未选中" />
            {{ sin_val }}
        </div>

        <!-- 4、多复选框 -->
        <!-- v-model存储的值为存储值多复选框value的数组 -->
        <div>
            <input type="checkbox" value="喜好男的" name="cless" v-model='more_val' />
            <input type="checkbox" value="喜好女的" name="cless" v-model='more_val' />
            <input type="checkbox" value="不挑" name="cless" v-model='more_val' />
            {{ more_val }}
        </div>
    </form>
</div>

<script type="text/javascript">
	new Vue({
		el: '#app',
		data: {
			in_val: '',
			// 默认值可以决定单选框默认选项
			ra_val: '男',
			// 默认值为true,单一复选框为选中,反之false为不选中
			sin_val: '',
			// 数组中存在的值对应的复选框默认为选中状态
			more_val: ['喜好女的','不挑']
		}
	})
</script>

条件渲染指令

  • v-show
<div v-show="isShow"></div>
// 变量isShow值为true(显示,display: block)|false(隐藏,display: none)
  • v-if
<div v-if="isShow"></div>
// 变量isShow值为true(显示,渲染到页面)|false(隐藏,不渲染到页面)
  • v-if v-else-if v-else
<div v-if="tag == 0" key="0"></div>
<div v-else-if="tag == 1" key="1"></div>
<div v-else="tag == 2" key="2"></div> 
// v-else会默认与v-if等有条件的分支绑定
// v-else-if必须由条件才和有条件v-if分支绑定
// 变量tag取值在0~2之间,可以决定具体渲染那个div
// 全局属性key是为渲染过的分支建立缓存,加快该分支下一次被渲染的速度,key的值具有唯一性

条件指令示例:

<div id="app">
    <button @click="toggle">显隐切换</button>
    <!-- v-if -->
    <div class="box r" v-if="isShow"></div>
    <!-- v-show -->
    <div class="box o" v-show="isShow"></div>
    <!-- 1.条件渲染的值为true|false -->
    <!-- 2.true代表标签显示方式渲染 -->
    <!-- 3.false v-if不渲染到页面,v-show以display:none渲染到页面,但也不会显示 -->

    <!-- v-if v-else-if v-else 案例 -->
    <ul>
        <li @mouseover="changeWrap(0)">red</li>
        <li @mouseover="changeWrap(1)">green</li>
        <li @mouseover="changeWrap(2)">blue</li>
    </ul>
    <!-- red页面逻辑结构 -->
    <div class="wrap red" v-if="tag == 0" key="0">...</div>
    <!-- green页面逻辑结构 -->
    <div class="wrap green" v-else-if="tag == 1" key="1">...</div>
    <!-- blue页面逻辑结构 -->
    <div class="wrap blue" v-else key="2">...</div>
    <!-- v-if相关分支操作,在未显示情况下,是不会被渲染到页面中 -->
    <!-- 通过key全局属性操作后,渲染过的分支会建立key对应的缓存,提高下一次渲染速度 -->

    <!-- v-show 案例 -->
    <ul>
        <li @mouseover="changeMain(0)">red</li>
        <li @mouseover="changeMain(1)">green</li>
        <li @mouseover="changeMain(2)">blue</li>
    </ul>
    <!-- red页面逻辑结构 -->
    <div class="main red" v-show="whoShow(0)">...</div>
    <!-- green页面逻辑结构 -->
    <div class="main green" v-show="whoShow(1)">...</div>
    <!-- blue页面逻辑结构 -->
    <div class="main blue" v-show="whoShow(2)">...</div>
</div>
<script type="text/javascript">
	new Vue({
		el: "#app",
		data: {
			isShow: false,
			tag: 0,
			flag: 0
		},
		methods: {
			toggle () {
				this.isShow = !this.isShow;
			},
			changeWrap (num) {
				this.tag = num;
			},
			changeMain (num) {
				// this.flag num
				this.flag = num;
			},
			whoShow (num) {
				// this.flag num
				return this.flag == num;
			}
		}
	})
</script>

循环指令

  • v-for 遍历数组[]
<ul>
    <li v-for="(n, i) in list" :key="i">value:{{ n }} | index: {{ i }}</li>
</ul>
// list为提供的数组数据
// n为遍历的数组元素值,i为遍历的元素索引
// 一般列表渲染需要建立缓存 ,key是为遍历建立缓存,采用变量赋值,所以通过v-bind:指令操作
<script>
new Vue({
    el: "#app",
    data: {
        list: [1, 2, 3, 4, 5],
    }
})
</script>
  • v-for变量对象{}
    v-for变量对象{}时,接收三个值时,第一个为元素值,第二个为元素键,第三个为元素索引
<ul>
    <li v-for="(v, k, i) in dic" :key="k">value:{{ v }} | key:{{ k }} | index: {{ i }}</li>
</ul>
// dic为提供的对象(字典)数据
// v为遍历的对象值,k为对象值的键,i为对象值的索引
// key是为遍历建立缓存,采用变量赋值,所以通过v-bind:指令操作
<script>
new Vue({
    el: "#app",
    data: {
        dic: {
            name: 'linwow',
            age: 18,
            gender: 'femal'
        }
    }
})
</script>
  • 遍历的嵌套
<div v-for="(person, index) in persons" :key="index" style="height: 21px;">
    <div v-for="(v, k) in person" :key="k" style="float: left;">
        {{ k }} : {{ v }}&nbsp;&nbsp;&nbsp;
    </div>
</div>

<script>
new Vue({
    el: "#app",
    data: {
        persons: [
            {name: "linwow", age: 8},
            {name: "lin", age: 78},
            {name: "wowo", age: 77},
            {name: "wowlin", age: 38}
        ]
    }
})
</script>

评论案例

<style>
    span {
        margin-left: 100px;
        cursor: pointer;
        color: green;
    }
    span:hover {
        color: red;
    }
</style>
<div id="app">
    <p>
        <input type="text" v-model="val">
        <button @click="add">评论</button>
    </p>
    <ul>
        <li v-for="(info, i) in infos">
            {{ info }}
            <span @click="del(i)">x</span>
        </li>
    </ul>
</div>
</body>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            infos: [],
            val: ''
        },
        methods: {
            del: function (i) {
                // splice: 从哪个索引开始  操作的位数  操作成的结果(可变长)
                this.infos.splice(i, 1)
            },
            add: function () {
                let val = this.val;
                if (val) {
                    this.infos.splice(0, 0, val);
                    this.val = ''
                }
            }
        }
    })
</script>

组件

  • 每一个组件都是一个vue实例
  • 每个组件均具有自身的模板template,根组件的模板就是挂载点
  • 每个组件模板只能拥有一个根标签
  • 子组件的数据具有作用域,以达到组件的复用

根组件

<div id="app">
    <h1>{{ msg }}</h1>
</div>
<script type="text/javascript">
	// 通过new Vue创建的实例就是根组件(实例与组件一一对应,一个实例就是一个组件)
	// 每个组件组件均拥有模板,template
	var app = new Vue({
		// 根组件的模板就是挂载点
		el: "#app",
		data : {
			msg: "根组件"
		},
		// 模板: 由""包裹的html代码块,出现在组件的内部,赋值给组件的$template变量
		// 显式书写模块,就会替换挂载点,但根组件必须拥有挂载点
		template: "<div>显式模板</div>"
	})
	// app.$template
</script>

局部组件

<div id="app">
    <local-tag></local-tag>
    <local-tag></local-tag>
</div>
<script>
    // 定义局部组件
    var localTag = {
        data () {
            return {
                count: 0
            }
        },
        template: '
        <button @click="btnAction">局部{{ count }}</button>
    ',
        methods: {
            btnAction () {
                this.count ++
            }
        }
    }
    new Vue({
        el: "#app",
        // 局部组件必须注册
        components: {
            'local-tag': localTag
        }
    })
</script>

全局组件

<div id="app">
    <!--在标签中建议使用 - 语法命名,对应js中就是驼峰命名-->
    <global-tag></global-tag>
    <global-tag></global-tag>
</div>
<script>
    // Vue.component(组件名, {组件主体});
	Vue.component('global-tag', {
		data () {
			return {
				count: 0
			}
		},
		template: '<button @click="btnAction">全局{{ count }}</button>',
		methods: {
			btnAction () {
				this.count ++
			}
		}
	})
    // 全局组件无需注册
    new Vue({
        el: "#app"
    })
</script>

父组件传递数据给子组件

  • 通过绑定属性的方式进行数据传递
<div id="app">
    <!-- global-tag就可以理解为自定义标签,使用msg变量值由父组件提供 -->
    <!-- global-tag标签代表的是子组件,supData为标签的自定义属性 -->
    <!-- 在子组件内部能拿到supData,就可以拿到父组件的信息 -->
    <global-tag :sup_data1='msg1' :supData2='msg2'></global-tag>
</div>
<script type="text/javascript">
	Vue.component('global-tag', {
		props:['sup_data1', 'supdata2'],
		template: '<div>{{ sup_data1 }} {{ supdata2 }}</div>'
	})
	new Vue({
		el: '#app',
		data: {
			msg1: '数据1',
			msg2: '数据2'
		}
	})
</script>

子组件传递数据给父组件

  • 通过发送事件请求的方式进行数据传递
<div id="app">
    <global-tag @send_action='receiveAction'></global-tag>
</div>
<script type="text/javascript">
	Vue.component('global-tag', {
		data () {
			return {
				sub_data1: "数据1",
				sub_data2: '数据2'
			}
		},
		template: '<div @click="clickAction">发生</div>',
		methods: {
			clickAction () {
                // $emit触发自定义的事件'send_action'
				this.$emit('send_action', this.sub_data1, this.sub_data2)
			}
		}
	})
	new Vue({
		el: '#app',
		methods: {
			receiveAction (v1, v2) {
				console.log(v1, v2)
			}
		}
	})
</script>

父子组件实现todoList

<div id="app">
    <div>
        <input type="text" v-model="val">
        <button type="button" @click="submitMsg">提交</button>
    </div>
    <ul>
        <!-- <li v-for="(v, i) in list" :key="i" @click="removeMsg(i)">{{ v }}</li> -->
        <todo-list v-for="(v, i) in list" :key="i" :v="v" :i="i" @delect_action="delect_action"></todo-list>
    </ul>
</div>
<script type="text/javascript">
	Vue.component("todo-list", {
		template: "<li @click='delect_action'><span>第{{ i + 1 }}条: </span><span>{{ v }}</span></li>",
		props: ['v', 'i'],
		methods: {
			delect_action () {
				this.$emit("delect_action", this.i)
			}
		}
	})
	
	new Vue({
		el: "#app",
		data: {
			val: "",
			list: []
		},
		methods: {
			submitMsg () {
				// 往list中添加input框中的value
				if (this.val) {
					this.list.push(this.val);
					this.val = ""
				}
			},
			delect_action(index) {
				this.list.splice(index, 1)
			}
		}
	})
</script>

猜你喜欢

转载自blog.csdn.net/linwow/article/details/93899429