vue学习
1.为什么学习vue框架
- 虚拟dom操作,帮助减少不必要的dom操作;提高渲染效率,双向数据绑定,让程序员专注于数据的业务逻辑。
2.框架和库的区别
- 框架:是一套完整的解决方案,对项目的侵入性比较大。
- 库(插件):提供某个小功能,需要更换时代价较小。
3.后端MVC和前端MVVM(实现数据的双向绑定)
- M保存的是每个页面中单独的数据
- vm是中间的调度者
- v是html结构
4.vue实例的基本结构
var vm = new Vue({
el:'#app',//表示我们实例的vue实例需要控制的区域
data:{
msg : 'helloWorld'
}
})
5.v-cloak 和 v-text、v-html、v-bind、v-on指令
- v-cloak是为了解决vue在插值时闪烁的问题,在网速较慢时,数据还没有刷新出来时将标签隐藏。
<style type="text/css">
[v-cloak]{
display: none;
}
</style>
<div id="app">
<p v-cloak>{{msg}}</p>
</div>
- v-text 和 插值表达式的区别是会将标签包括的内容覆盖掉
<!-- 123会被覆盖掉 -->
<p v-text="msg">123</p>
- v-html会将内容转化为HTML代码
<div v-html="msg2"></div>
data:{
msg:'helloworld',
msg2:'<h1>我是h1</h1>'
}
- v-bind 是用于绑定属性的指令(缩写 : ,该指令中可以书写合理的js表达式)
<input type="button" name="" id="" value="按钮" v-bind:title="title"/>
<input type="button" name="" id="" value="按钮" :title="title"/>
data:{
title:'我是title'
}
- v-on来处理事件绑定机制(缩写 @ )
<input type="button" name="" id="" value="按钮" v-on:click="show"/>
methods:{
show:function(){
alert('123456');
}
}
- 简单的字符跑马灯
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
</style>
</head>
<body>
<div id="app">
<input type="button" name="" id="" value="动" @click="lang"/>
<input type="button" name="" id="" value="静" @click="stop"/>
<p>{{msg}}</p>
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'#app',
data:{
msg:'你看我会动,而且动的还不是一点两点。',
interval : null
},
methods:{
lang(){
<!---- => 是将外面的this 和里面的this进行绑定>
this.interval = setInterval(() => {
var start = this.msg.substring(0,1)
var end = this.msg.substring(1)
this.msg = end + start
},400)
},
stop(){
clearInterval(this.interval)
}
}
})
</script>
</html>
6.事件修饰符
- .stop 阻止冒泡(阻止了外层div的点击事件)
<div id="app" @click="shop1">
<button type="button" @click.stop="shop">按钮</button>
</div>
methods:{
shop(){
console.log("这是按钮的")
},
shop1(){
console.log('这是外层div的')
}
}
- .prevent 阻止默认行为(一下代码不会再跳转到百度)
<a href="http://www.baidu.com" @click.prevent="linkclick">baidu</a>
linkclick(){
console.log('链接事件')
}
- .capture添加事件监听器时使用事件捕获模式(默认是冒泡机制-----最上面的最执行)
<div id="app" @click.capture="shop1">
<button type="button" @click="shop">按钮</button>
</div>
- .self 当该事件在元素本身的时候才会触发回调
<div id="app" @click.self="shop1">
<button type="button" @click="shop">按钮</button>
<!-- <a href="http://www.baidu.com" @click.prevent="linkclick">baidu</a> -->
</div>
- .once 事件只会执行一次
V-model 实现数据的双向绑定
- v-bind只能实现数据的单项绑定
<div id="app">
<p>{{msg}}</p>
<input type="text" name="" id="" value="" v-model="msg"/>
</div>
CSS样式
<style type="text/css">
.a{
width: 50px;
height: 50px;
background-color: #ADD8E6;
}
.b{
width: 100px;
height: 100px;
background-color: antiquewhite;
}
.c{
width: 150px;
height: 150px;
background-color: #00FF00;
}
</style>
<div :class="['a']"> 我是H1</div>
<!-- 使用三元表达式 -->
<div :class="[flag?'b':'']"></div>
<!-- 直接嵌套对象 -->
<div :class="[{'c':flag}]"></div>
<!-- 直接使用对象 -->
<div :class="{a:true}"></div>
V-for指令和key属性
<div id="app">
<!-- 循环普通数组 -->
<p v-for="(item , i) in list">值是:{{item}}------索引:{{i}}</p>
<!-- 循环对象数组 -->
<p v-for="user in list2">{{user.id}}------{{user.name}}</p>
<!-- 循环复杂对象 -->
<p v-for="(val,key) in user">{{val}}------ {{key}}</p>
<!-- 循环迭代数字 -->
<P v-for = "count in 10">{{count}}</P>
</div>
var vm = new Vue({
el: '#app',
data: {
list: [1, 2, 3, 4, 5, 6],//普通数组
list2 : [{id:1,name:'zs1'},//对象数组
{id:2,name:'zs2'},
{id:3,name:'zs3'},
{id:4,name:'zs4'}
],
user :{//对象
id :1,
name: '啦啦啦',
sex:'男'
}
}
})
V-if 和 v-show的使用和特点
- if会没次重新创建元素和删除元素(开销比较大)
- show是使用css样式来控制(开销较小,经常切换时应该使用show)
VUE的过滤器
- 过滤器的格式及调用(需要写在vue() 之前)
<p>{{msg | msgFormat('疯狂')}}</p>
<p>{{msg | msgFormat}}</p>
Vue.filter('msgFormat',function(msg,arg){//第一个参数是固定的传过来的msg 第二个参数msgFormat('疯狂')中的疯狂,也可以有多个参数
return msg.replace(/五/g,arg);
})
data:{
msg : '曾经有一段五真挚的感情摆五在我的面前,但我却没有好好五的珍惜,知道失去以后我才后悔五莫急'
}
- 时间格式过滤器
{{car.ctime | dataFormat}}
Vue.filter('dataFormat',function(datestr){
var dt = new Date(datestr)
var y = dt.getFullYear()
var m = dt.getMonth()
var d = dt.getDay()
return `${y}-${m}-${d}`
})
字符串的padStart方法的使用
//填充方法
string.padStart(填充完的总位数,用什么填充)
自定义按键修饰符
- 绑定点击回车键时执行方法 @keyup.enter
<input type="text" name="" id="" value="" class="form-control" v-model="name" @keyup.enter="add"/>
自定义全局指令实现文本框自动获取焦点
- 第一个参数时指令的名称 命名时不需要v- 但是使用时 需要加上
- 第二个参数是一个对象
Vue.directive('focus', {
//当指令被绑定到标签的时候
bind: function (el) {
// 聚焦元素
el.focus()
},
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
},
//当标签更新数据的时候
updata : function(){
}
})
利用钩子函数的第二个参数传递值
v-color = "'red'"
//自定义指令
Vue.directive('color',{
bind : function(el,binding){
el.style.color = binding.value
}
})
定义私有自定义指令
directives : {
'fontweight' : function(el,binding){
el.style.fontWeight = binding.value
}
}
简写自定义指令
- 当你只需要使用到 bind 和 updata 钩子函数时可以简写为这样子
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
生命周期函数(与el、data属性同级别)
- beforeCreate函数(创建之前调用的函数无法引用 data中的数据和method中的方法)
beforeCreate(){
console.log('vm2这是创建之前的方法')
}
- created 函数(vue对象完全实例完后调用的函数,它可以调用到data和method中的内容)
created(){
console.log(this.ctime)
this.show()
}
vue-resource发起get、post、jsonp请求
- 首先导入vue-resource的包 必须在vue之后导入
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script src="vue-resource.js" type="text/javascript" charset="utf-8"></script>
2.示例
methods: {
getinfo(){//发起get 请求
this.$http.get('http://jsonplaceholder.typicode.com/users').then(function(result){
console.log(result)
})
},
postinfo(){
this.$http.post('http://jsonplaceholder.typicode.com/users',{},{emulateJSON : true}).then(result=>{
console.log(result)
})
},
jsonpinfo(){
this.$http.jsonp('http://jsonplaceholder.typicode.com/users').then(result => {
console.log(result)
})
}
}
全局配置数据接口的根路径
Vue.http.options.root = 'http://www.liulongbin.top:3005/'
//在使用时只需要写一个相对路径就行 也就是地址的前面不需要再添加一个 /
api/delproduct/
全局配置emulateJSON属性
Vue.http.options.emulateJSON = true
Vue中的动画
使用过度类名实现动画
.v-enter,
.v-leave-to{
opacity: 0;
transform: translateX(150px);
}
.v-enter-active,
.v-leave-active{
transition :all 0.8s ease;
}
- 自定义V-前缀类名
my-enter 类名就可以控制动画了
<transition name = 'my'>
- 使用第三方类库animate.css
//入场效果 离场效果 入场时间花费四百毫秒 离场时间花费四百毫秒 :duration = "{enter : 200,leave : 400} //也可以分别设置时间
//animated 是支持类
<transition enter-active-class = "bounceIn" leave-active-class = "bounceOut" :duration = "400">
<h3 v-if = 'flag' class="animated">132456</h3>
</transition>
列表动画(添加和删除)
.v-enter,
.v-leave-to{
opacity: 0;
transform: translateY(80px);
}
.v-enter-active,
.v-leave-active{
transition: all 0.6s ease;
}
.v-move{
transition: all 0.6s ease;
}
.v-leave-active{
position: absolute;
}
//appear当页面刚开始刷新元素出现时会有动画效果 tag属性把transition渲染成ul标签 符合w3c规范
<transition-group appear tag="ul">
<li v-for="(item, index) in list" :key="index" @click = "del(index)">{{index}} ------ {{item.name}}</li>
</transition-group>
vue的组件
创建组件的方式
- 通过vue.extend进行创建
//直接以HTML标签的方式进行调用
<com1></com1>
//1.1通过Vue.extend来进行组件创建他会返回一个对象
var com1 =Vue.extend({
template : '<h3>这是通过Vue.extend进行创建的组件</h3>'
})
//1.2通过Vue.component注册组件('自定义的名称',组件对象)
Vue.component('com1', com1)
- 直接使用Vue.component进行创建
Vue.component('com2', {
template : '<h3>这是通过Vue.component进行创建的组件</h3>'
})
- 使用template
<template id="temp">
<div>
<h3>这是通过template标签进行创建的组件,
必须写在受#app控制的标签的外面,好处就是有代码提示和高亮</h3>
</div>
</template>
Vue.component('com3', {
template : '#temp1'
})
- 定义私有组件
<template id="temp2">
<div>
<h1>这是app2私有的组件</h1>
</div>
</template>
<div id="app2">
<login>
</div>
var vm2 = new Vue({
el : "#app2",
data : {
},
components : {
//login 不能出现特殊字符 - 等
login : {
template : '#temp2'
}
}
})
组件中的data
- 组件中的data 必须是一个方法且必须返回一个对象
<template id="com1">
<div>
<h1>这是组件----和他的值{{msg}}</h1>
</div>
</template>
<div id="app">
<com1></com1>
</div>
Vue.component('com1', {
template : '#com1',
data() {
return {
msg : '这是组件中msg的值'
}
},
})
组件之间的切换
- 使用vif velse 来进行切换
<div id="app">
<a href="" @click.prevent="flag = true">登录</a>
<a href="" @click.prevent="flag = false">注册</a>
<login v-if="flag"></login>
<regi v-else = "flag"></regi>
</div>
Vue.component('login', {
template : '<h3>登录</h3>'
})
Vue.component('regi', {
template : '<h3>注册</h3>'
})
flag : true
2.使用vue提供的conponent标签进行切换
<a href="" @click.prevent="comname = 'login'">登录</a>
<a href="" @click.prevent="comname = 'regi'">注册</a>
<component :is = "comname"></component>
comname : 'login'
父组件向子组件传值以及data和props的区别
//1.2用v-bind 绑定 父组件vm中的数据 msg
<com1 :msg1="msg"></com1>
//1.1定义私有组件
components: {
com1: {
template: "<h3>我是子组件中的h3-----{{msg1}}</h3>",
props: ['msg1']//1.3在子组件中的props数组中进行声明
}
}
子组件向父组件传值
<btn_num v-on:btn_prevent_add = "btn_prevent_count()"></btn_num> <!-- (4) 父组件监听btn_prevent_add事件触发btn_prevent_count方法 -->
<btn_num v-on:btn_prevent_add = "btn_prevent_count()"></btn_num> <!-- (4) 父组件监听btn_prevent_add事件触发btn_prevent_count方法-->
Vue.component("btn_num", {//创建组件
data:function() {
return {
count : 0//定义参数
}
},methods:{
btn_com_add:function(){//定义方法 (2)
this.count += 1
this.$emit("btn_prevent_add")//(3)
}
},
template:'<button @click = "btn_com_add()">{{count}}</button>'//组件模板(1)
})
methods: {
btn_prevent_count : function(){
this.count_num += 1
}
}
路由
什么是路由?
- 后端路由:对于普通的网站,所有的超链接都是URL地址,所有的url地址都对应着服务器上面的资源
- 前端路由:对于单页面程序来说主要通过url中的hash#号来实现不同页面之间的切换,同时hash有个特点http请求中不会包含#号后面的值
路由切换组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="../vue静态资源/bootstrap.css">
<script src="../vue静态资源/vue.js" type="text/javascript" charset="utf-8"></script>
<script src="../vue静态资源/vue-resource.js" type="text/javascript" charset="utf-8"></script>
<script src="../vue静态资源/vue-router.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<!-- 不能写成 /login 这样子会跳到一个真实的地址-->
<a href="#/login">登录</a>
<a href="#/register">注册</a>
<!--router-view 为组件提供放置容器 -->
<router-view></router-view>
</div>
</body>
<script type="text/javascript">
//组件对象
var login = {
template : '<h3>这是登录组件</h3>'
}
var register = {
template : '<h3>这是注册组件</h3>'
}
//VueRouter对象里面的routes数包含两个属性 path是前台地址栏输入的 component是组件对象
var routerObj = new VueRouter({
routes : [
{path : '/login',component : login},
{path : '/register',component : register}
]
})
var vm = new Vue({
el: "#app",
data: {
},
methods: {
},
router : routerObj //将vue对象和VueRouter对象进行关联
})
</script>
</html>
router-link的使用
- vue不提倡使用a标签加 #的方式来访问路由
- 而是使用router-link标签来进行访问,默认会被渲染成a标签,tag="span"可以将之渲染成span
<router-link to="/login" tag="span">登录</router-link>
<router-link to="/register">注册</router-link>
路由重定向redirect
当页面刷新时直接跳转到 /login 也就是显示登录组件
{path : '/',redirect : '/login'}
如何设置路由选中高亮
- 设置VueRouter对象的linkActiveClass属性
<style>
.myActive{
font-size: large;
}
</style>
var routerObj = new VueRouter({
routes : [
{path : '/login',component : login},
{path : '/',redirect : '/login'},
{path : '/register',component : register}
],linkActiveClass : 'myActive'
})