Vue实例创建
<!-- 1.导入vue的包 -->
<script src="vue.js"></script>
<script>
//2. 创建一个vue的实例
// 当我们导入包之后,在浏览器的内存中,就多了一个vue构造
//相当于MV
var vm = new Vue({
el : '#app', //表示当前我们 new 的这个实例,要控制页面上的哪个区域
//data 相当于M
data : { //data属性中,存放的是 el 中要用的数据
msg: '学习vue'// 通过 vue 提供的指令,很方便的把数据渲染到页面上,程序员不再手动操作DOM元素了
},
methods:{ //这个methods属性中定义了当前vue实例所有可用的方法
show:function(){
alert("hello")
}
}
})
</script>
v-
- v-clock 能够解决 插值表达式 闪烁问题
<style>
/* 给v-clock设置样式 */
[v-clock] {
display: none;
}
</style>
<p v-cloak>{{ msg }}</p>
- 默认 v-text 没有 闪烁问题,但是会覆盖元素中{{ }}中原本的内容
<div v-text="msg2"></div>
- v-html 在JavaScript 中显示动态HTML
<div v-html="msg2"></div>
- v-on 简写为 @ ,事件绑定 的指令
<input type="button" value="按钮" v-on:click="show">
<input type="button" value="按钮" @mouseover="show"><!--事件click,mouseover(鼠标覆盖就出现)-->
- v-bind 简写为 :, 属性绑定 的指令(单项)
<input type="text" :value="msg" style="width:100%">
<h1 :class="{'red':true,thin:false,italic:true}">我是一只聪明的小汤姆</h1>
<h1 :class="['thin','red',flag?'active':'']">我是一只聪明的小汤姆</h1>
<h1 :style="[styleObj1,styleObj2]">我是聪明的小汤姆</h1>
// 使用数组同时绑定多个
data:{
styleObj1:{color:'red','font-weight':200},
styleObj2:{'font-style':'italic'}
}
- v-model 表示表单输入的绑定 (双向)
input(radio, text, address, email …) select checkbox textarea…
<select v-model="opt">
<option value="+">+</option>
<option value="-">-</option>
</select>
<input type="text" v-model:value="msg" style="width:100%">
- v-for 用来迭代元素和显示列表
在使用v-for 的同时,指定唯一的 字符串/数字 类型 :key 值
<p v-for="(item,i) in list" :key="item.id">
<input type="checkbox">
{{item.id}}----{{item.name}}
</p>
<!-- 循环普通数组 -->
<p v-for="(item,i) in list">索引值:{{i}}----每一项:{{item}}</p>
<!-- 循环对象数组 -->
<p v-for="(user,i) in list1">{{user.id}}-----{{user.name}}------{{i}}</p>
<!-- 循环对象 -->
<p v-for="(val,key,i) in list2">{{val}}-----{{key}}-------{{i}}</p>
<p v-for="count in 10">这是第{{count}}次循环</p>
in 后面我们可以放 普通数组,对象数组, 对象,还可以放 数字 此时前面的count从1开始
- v-if 特点:每次都会重新删除或创建元素
- v-show 特点:每次不会重新删除和创建元素,只是切换了元素display:none 样式
v-if 有较高的切换性能消耗 v-show 有较高的初始渲染消耗
循环数组
data:{
// 循环普通数组
list:[1,2,3,4,5],
// 循环对象数组
list1:[
{id:1,name:'xiao1'},
{id:2,name:'xiao2'},
{id:3,name:'xiao3'},
{id:4,name:'xiao4'},
],
// 循环对象
list2:{
id:1,
name:'xiaoming',
age:17
}
}
走马灯
<!DOCTYPE html>
<html lang="en">
<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>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<input value="走起来" type="button" @click="run"/>
<input value="停下来" type="button" @click="stop"/>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
msg:'农夫山泉有点甜',
intervalId:null //在data 中定义 定时器Id
},
methods:{
run(){
if(this.intervalId!=null) return;
this.intervalId = setInterval(()=>{
var start = this.msg.substring(0,1)
var end = this.msg.substring(1)
this.msg = end + start
},400)
},
stop(){
clearInterval(this.intervalId)
this.intervalId = null;
}
}
})
</script>
</body>
事件修饰符
- 使用 .capture 实现捕获触发事件(从外到里)的机制
<div class="inner" @click.capture="div1hander">
- 使用 .self 实现只有点击当前元素的时候,才会触发事件处理函数
<div class="inner" @click.self="div1hander">
- 使用 .stop 阻止冒泡
- .self 只阻止自己身上冒泡行为的触发,并不会真正阻止冒泡行为
<input value="戳他" type="button" @click.stop="btnhander">
- 使用 .prevent 阻止默认事件
- 使用 .once 只触发一次事件处理函数
- 事件修饰符可以一起用
<a href="http://www.baidu.com" @click.prevent.once="linkclick">baidu</a>
品牌管理案例
<!DOCTYPE html>
<html lang="en">
<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>
<script src="vue.js"></script>
</head>
<body>
<div id='app'>
<div>
<div>
<h3>添加品牌</h3>
</div>
<div>
<label>
Id:
<input type="text" v-model="id">
</label>
<label>
Name:
<input type="text" v-model="name" @keyup.end="add">
</label>
<input type="button" value="添加" @click="add()">
<label>
搜索关键字:
<input type="text" v-model="keywords" id="search" v-focus v-color="'blue'">
</label>
</div>
</div>
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Ctime</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr v-for="item in search(keywords)" :key="item.id">
<td>{{item.id}}</td>
<td v-text="item.name"></td>
<td>{{item.ctime|dataFormat('')}}</td>
<td>
<a href=" " @click.prevent="del(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<div>
<h4 v-color="'pink'" v-fontweight="20" v-fontsize="'70px'">{{dt|dataFormat}}</h4>
</div>
<script>
//全局过滤器,进行时间的格式化
Vue.filter('dataFormat',function(datester,pattern=""){
var dt = new Date(datester)
var y = dt.getFullYear()
//padStart(2,'0') 用于头部零的情况 padEnd(2,'0') 用于尾部零的情况
//第一个参数:总长度
//第二个参数: 用什么填充
var m = (dt.getMonth()+1).toString().padStart(2,'0')
var d = (dt.getDate()).toString().padStart(2,'0')
if(pattern.toLowerCase() === 'yyyy-mm-dd'){
return y+"-"+m+"-"+d
}else{
var hh = (dt.getHours()).toString().padStart(2,'0')
var mm = (dt.getMinutes()).toString().padStart(2,'0')
var ss = (dt.getSeconds()).toString().padStart(2,'0')
return y+"-"+m+"-"+d+" "+hh+":"+mm+":"+ss
}
})
Vue.directive('focus',{
bind:function(el){
el.focus()
},
inserted:function(el){
el.focus()
},
updated:function(el){
}
})
Vue.directive('color',{
bind:function(el,binding){
el.style.color = binding.value
}
})
var vm = new Vue({
el:'#app',
data:{
id:'',
name:'',
keywords:'',
list:[
{id:1,name:'奔驰',ctime:new Date()},
{id:2,name:'宝马',ctime:new Date()}
]
},
methods:{
add(){
this.list.push({id:this.id,name:this.name,ctime:new Date()})
this.id=this.name=''
},
del(id){
var index = this.list.findIndex(item=>{
if(item.id===id){
return true;
}
})
this.list.splice(index,1)
},
search(keywords){
return this.list.filter(item=>{
if(item.name.includes(keywords)){
return item
}
})
}
},
filetrs:{
dataFormat:function(datester,pattern){
var dt = new Date(datester)
var y = dt.getFullYear()
var m = dt.getMonth()+1
var d = dt.getDate()
if(pattern && pattern.toLowerCase()==='yyyy-mm-dd'){
return y+"-"+m+"-"+d
}else{
var hh = dt.getHours()
var mm = dt.getMinutes()
var ss = dt.getSeconds()
return y+"-"+m+"-"+d+" "+hh+":"+mm+":"+ss+"!!!"
}
}
},
directives:{ //自定义私有指令
'fontweight':{
bind:function(el,binding){
el.style.fontWeight=binding.value
}
},
'fontsize':function(el,binding){
el.style.fontSize = parseInt(binding.value)+"px"
}
}
})
</script>
</body>
过滤器
<div>
<p>{{msg|magFor('moring','noon')|test}}</p>
<div>
// 调用格式
{{name|'过滤器的名字'}}
//定义语法
//过滤器中的function ,第一个参数已经被规定死了,永远
//都是 过滤器 管道前面 传递过来的数据
<script>
Vue.filter('过滤器的名字magFor',function(msg,sgr,sgr2){
return msg.repalce(/早上/g,sgr+sgr2)
})
Vue.filter('text',function(msg){
return msg+'========'
})
var vm = new Vue({
el:"#app",
data:{
msg:'早上好!'
}
})
</script>
生命周期函数
创建阶段
beforeCreate(){}
第一个生命周期函数,表示实例完全被创建之前,会执行他
data 和 methods 中的数据都还没有初始化
created(){}
第二个生命周期函数
在created中,data 和methods中都已经初始化好了
methods方法,或者操作data中的数据,最早,只能在created中操作
beforeMount(){ }
第三个生命周期函数,表示模板已经在内存中,但是尚未把模板渲染到DOM中
页面中的元素,还没有被真正替换过来
mounted(){}
第四个生命周期函数,表示内存中的模板,已经真实的挂载到了页面中,
用户已经可以看到渲染好的页面了
是实例创建期间的最后一个生命周期函数
如果要通过某些插件操作页面上的DOM节点了,最早要在mounted中进行
运行阶段
beforeUpdate(){}
表示 我们的界面还没有被更新【数据已经被更新了】
页面中的显示的数据是旧的,页面尚未和最新的数据同步
updated(){}
页面和data 数据已经保持同步了,都是最新的
v-resource
vue-resource 依赖于Vue ,所有先后顺序要注意
get是从服务器上获取数据,post是向服务器传送数据,一般用于更新资源信息
<script src="vue.js"></script>
<!-- 注意: vue-resource 依赖于Vue ,所有先后顺序要注意 -->
<!-- this.$http -->
<script src="https://cdn.bootcss.com/vue-resource/1.5.1/vue-resource.js"></script>
<
<div id="app">
<input type="button" value="get请求" @click="getInfo">
<input type="button" value="post请求" @click="postInfo">
<input type="button" value="jsonp请求" @click="jsonpInfo">
</div>
<script>
var vm = new Vue({
el:'#app',
data:{},
methods:{
getInfo(){
this.$http.get('https://www.baidu.com/').then(result=>{
//通过resul.body 拿到服务器返回成功的数据
console.log(result.body)
})
},
postInfo(){
//手动的发起post请求,默认没有表单的格式,所以,有的服务器处理不了
//{emulateJSON:true} 设置提交的内容类型为普通表单数据格式
this.$http.post('https://www.baidu.com/',{},{emulateJSON:true}).then(result=>{
console.log(result.body)
})
},
jsonpInfo(){
this.$http.jsonp('https://www.baidu.com/').then(result=>{
console.log(result.body)
})
}
}
})
</script>
this.$http.post() 中接收三个参数:
第一个参数: 要请求的URL地址
第二个参数:要提交给服务器的数据,要以对象形式提交给服务器{name:this.name }
第三个参数: 是一个配置对象,要以哪种表单数据类型提交过去{emulateJSON:true} ,将数据提交给服务器 application/x-www-form-urlencoded
从数据库获取数据
<script src="vue.js"></script>
<!-- 注意: vue-resource 依赖于Vue ,所有先后顺序要注意 -->
<!-- this.$http -->
<script src="https://cdn.bootcss.com/vue-resource/1.5.1/vue-resource.js"></script>
<script>
// 如果我们通过全局配置,请求的数据接口的 根域名,则 在每次单独发起的 http 请求的时候,请求的 url 路径,应该以相对路径开头(前面不能带/) 否则不会启用根域名做拼接
Vue.http.option.root='http://vue.studyit.io/';
//全局启用emulateJSON选项
Vue.http.option.emulateJSON = true;
var vm = new Vue({
el:'#app',
data:{
name:'',
list:[
{id:1,name:'奔驰',ctime:new Date()},
{id:2,name:'宝马',ctime:new Date()}
]
},
created(){ // vm 的 data 和 method 初始化完毕
this.getALLList();
}
methods:{
add(){
this.$http.post('api/addproduct',{name:this.name},{emulateJSON:true}).then(result=>{
if(result.body.status===0){
// 成功了,需要手动调用getALLList
this.getALLList();
this.name=''
}else{
alert('失败了!')
}
})
},
del(id){
this.$http.get(''api/delproduct/'+id').then(result=>{
if(result.body.status === 0){
this.getALLList()
}else{
alert('失败!')
}
})
},
getALLList(){
this.$http.get('').then(result=>{
if(result.body.status===0){
this.list = result.body.message
}else{
alert('失败了!');
}
})
}
}
</script>
动画
一
v-enter [时间点] 进入之前,元素的起始状态,此时还没有开始进入
v-leave-to [时间点] 是动画离开之后的终止状态,此时,元素动画已经结束
<script>
.v-enter,
.v-leave-to{
opacity:0;
tranform: translateX(100px);
}
.my-enter,
.my-leave-to{
opacity: 0;
transform: translateY(100px);
}
</script>
v-enter-active [时间段]
v-laeve-active [时间段]
.v-enter-active,
.v-leave-active{
transition:all 0.8s ease; // 过渡的所有属性 0.8s过渡 过渡的状态
}
.my-enter-active,
.my-leave-active{
transition: all 0.8s ease;
}
<-- 1.使用transition 元素(官方提供),把需要被动画控制的元素,包裹起来 -->
<transition name="my">
<h3 v-if="flag">hi,我是h3</h3>
</transition>
二.animate
入场 bounceIn 出场 bounceOut
<script src="vue.js"></script>
<link rel="stylesheet" href="animate.css">
<transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="{enter:200,leave:400}">
<h3 v-if="flag" class="animated">hi!我是h3~~</h3>
</transition>
三.钩子半场动画
<style>
.ball{
width: 15px;
height: 15px;
border-radius:50%;
background-color: violet;
}
</style>
<div>
<input type="button" value="快到碗里来" @click="flag=!flag">
<transition @before-enter="beforeEnter" @enter="enter" @after-active="afterEnter">
<div class="ball" v-show="flag"></div>
</transition>
</div>
<script>
methods:{
//动画钩子函数的第一个参数:el表示动画要执行的那个DOM元素
beforeEnter(el){ //此时动画尚未开始
el.style.transform = "translate(0,0)" //设置小球的起始位置
},
enter(el,done){ //可以设置小球完成动画之后的,结束状态
//可以认为 el.offsetWidth 可以强制动画刷新
el.offsetWidth
el.style.transform = "translate(150px,450px)"
el.style.transition = 'all 1s ease'
// 这里的done 是afterEnter 函数的引用
done()
},
afterEnter(el){ //动画完成之后,会调用afterEnter
this.flag = !this.flag
}
}
</script>
四.列表动画
<style>
li{
border: 1px dashed #000000;
margin: 5px;
line-height: 35px;
padding-left: 5px;
font-size: 12px;
width:100%;
}
li:hover{
background-color: blue;
transition: all 0.4s ease;
}
.v-enter,
.v-leave-to{
opacity: 0;
transform: translateY(160px); //相对
}
.v-enter-active,
.v-leave-active{
transition: all 1s ease;
}
// .v-move 和 .v-leave-active 配合使用,能够使列表后续的元素,渐渐的飘上来的效果
.v-move{
transition:all 1s ease;
}
.v-leave-active{
position: absolute;
}
</style>
//在实现列表的过渡的时候,如果需要过渡的元素是通过v-for循环渲染出来的,
//不能使用transition 包裹,需要使用 transitionGroup
//appear 属性,实现页面刚展示出来时的入场效果
<input type="button" value="添加" @click="add">
<ul>
<transition-group appear tag="ul">
<li v-for="(item,i) in list" :key="item.id" @click="del(i)">
{{item.id}}----{{item.name}}
</li>
</transition-group>
</ul>
methods:{
add(){
his.list.push( {id:this.id,name:this.name} )
this.id=this.name=''
},
del(i){
this.list.splice(i,1)
}
}
组件
<div id="app">
<my-com1> // myCom1 如果 组件名称为 mycom1 <mycom1></mycom1>
</my-com1>
</div>
// 1.使用Vue.extend 来创建 全局 的Vue组件
<script>
var com1 = Vue.extend({
// 通过template 属性,指定了组件要展示的HTML属性
template:'<h3>这是使用 Vue.extend 创建的组件</h3>'
})
</script>
// 2.使用Vue.compenent('组件的名称',创建出来的组件模板对象)
Vue.compenent('myCom1',com1)
Vue.compenent('myCom1',Vue.extend({
template:'<h3>这是使用 Vue.extend 创建的组件</h3>'
}))
Vue.compenent('myCom1',{
template:'<h3>这是使用 Vue.extend 创建的组件</h3>'
})
- 组件可以有自己的data,但是组件中的data 必须是一个方法,并且必须返回return一个对象;使用方式一样。
- 组件可以有自己的方法
<div id="app">
<mycom1>
</mycom1>
<login></login>
</div>
<template id="tem1">
<div>
<input type="button" value="加1" @click="incream">
<h3>hi</h3>
</div>
</template>
<template id="temp2">
<h1>这是私有组件</h1>
</template>
<script>
Vue.compenent('mycom1',{
template:'#tem1',
data:function(){
return {
msg:'这是组件自己的msG',
count:0
}
},
methods:{
incream(){
this.count++
}
}
})
compenents:{ // 定义私有组件
login:{
template:'#tem2'
}
}
</script>
组件如何切换
Vue 提供了 component ,来展示对应组件的名称
component 占位符, :is 属性,用来指定要展示的组件的名称
通过 mode 属性实现组件切换时候的 模式
<div id="#app">
<a href="" @click.prevent="conNmae='denglu'">登录</a>
<a href="" @click.prevent="conName='zhuce'">注册</a>
<transition mode="out-in">
<component :is="comName"><conponent>
</transition>
//<a href="" @click.prevent="flag=true">登录</a>
//<a href="" @click.prevent="flag=flase">注册</a>
//<denglu v-if="flag"></denglu>
//<zhuce v-else="flag"></zhuce>
</div>
<script>
Vue.component('denglu',{
template:"<h1>登陆组件</h1>"
})
Vue.component('zhuce',{
template:"<h1>注册组件</h1>"
})
var vm = new Vue({
el:'#app',
data:{
conName:'denglu'
//flag = true
}
})
<script>