<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://how2j.cn/study/vue.min.js"></script>
</head>
<style>
[v-cloak]{
display: none;
}
</style>
<body>
<div id="app">
<p v-cloak>{
{
msg}}</p>
<!-- v-text没有闪烁问题,但却覆盖元素中内容 -->
<h4 v-text="msg"></h4>
<div v-html="msg2"></div>
<input type="button" value="一个按钮" v-bind:title="mytitle + '123'">
<!-- v-bind:简写-> : v-click:简写-> @ -->
<input type="button" value="一个按钮" :title="mytitle + '123'" id="btn" @click="show">
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
msg:"123",
msg2:"123456
",
mytitle:"这是自定义的title",
},
methods: {
show: function(){
alert(123);
}
},
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://how2j.cn/study/vue.min.js"></script>
</head>
<body>
<div id="app">
<input type="button" value="run" @click="run">
<input type="button" value="stop" @click="stop">
<p>{
{
textmsg}}</p>
</div>
</body>
<script>
var vm=new Vue({
el:"#app",
data:{
textmsg:"这是走马灯内容",
IntervalID:null,
},
methods: {
run:function(){
if(this.IntervalID!=null) return;
this.IntervalID=setInterval(()=>{
console.log(this.textmsg)
var start=this.textmsg.substring(0,1)
var end=this.textmsg.substring(1)
this.textmsg=end+start;
},500)
},
stop:function(){
clearInterval(this.IntervalID);
this.IntervalID=null;
}
},
});
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://how2j.cn/study/vue.min.js"></script>
</head>
<style>
.inner{
width: 100%;
height: 500px;
background-color: aquamarine;
}
</style>
<body>
<!-- <div id="app" class="inner" @click.capture="divhandler"> -->
<div id="app" class="inner" @click.self="divhandler">
<!-- <input type="button" value="戳他1" @click.stop="btnhandler"> -->
<input type="button" value="戳他2" @click="btnhandler">
<a href="https://www.baidu.com" @click.prevent="baidu">baidu</a>
<a href="https://www.baidu.com" @click.prevent.once="baidu">baidu</a>
<!-- self只阻止了自己的冒泡,而stop阻止了上面所有的冒泡 -->
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
msg:"123",
msg2:"123456
",
mytitle:"这是自定义的title",
},
methods: {
btnhandler(){
console.log("btn点击")
},
divhandler(){
console.log("div点击")
},
baidu(){
console.log("baidu")
}
},
});
</script>
</body>
</html>
<!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>
</head>
<body>
<div id="app">
<h4>{
{
msg}}</h4>
<!-- v-bind只能实现单向绑定 v-model可以实现双向绑定 只运用在表单中s -->
<input type="text" v-model="msg">
</div>
<script src="./vue.min.js"></script>
<script>
var vm = new Vue({
el:'#app',
data:{
msg:"星空不问赶路人,时光不负有心人"
},
methods:{
}
});
</script>
</body>
</html>
<!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>
</head>
<body>
<div id="app">
<input type="text" v-model="n1">
<select v-model="ope">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
<input type="text" v-model="n2">
<input type="button" value="=" @click="eq">
<input type="text" v-model="result" value="">
</div>
<script src="./vue.min.js"></script>
<script>
var vm = new Vue({
el:'#app',
data:{
n1: 0,
n2: 0,
result: 0,
ope: '+',
},
methods:{
eq:function(){
// 尽量不要使用eval()这里只是为了方便,可以使用switch.
this.result=eval(this.n1+this.ope+this.n2);
}
}
});
</script>
</body>
</html>
<!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>
</head>
<style>
.red{
color: red;
}
.thin{
font-weight: 200;
}
.italic{
font-style: italic;
}
.active{
letter-spacing: 0.5em;
}
</style>
<body>
<div id="app">
<h1 class="red thin">只是一个简单的h1</h1>
<!-- 第一种使用方式 传递数组 v-bind -->
<h1 :class="['red','thin']">只是一个简单的h1</h1>
<!-- 使用三元表达式-->
<h1 :class="['red','thin',flag?'active':'']">只是一个简单的h1</h1>
<!-- 使用对象的方式,提高代码可读性-->
<h1 :class="['red','thin',{'active':flag}]">只是一个简单的h1</h1>
<!-- 直接使用对象 -->
<h1 :class="classObj">只是一个简单的h1</h1>
</div>
<script src="./vue.min.js"></script>
<script>
var vm = new Vue({
el:'#app',
data:{
flag:true,
classObj:{
thin:true,active:false}
},
methods:{
}
});
</script>
</body>
</html>
<!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.min.js"></script>
</head>
<body>
<div id="app">
<h1 :style="styleObj1">这是一个h1</h1>
<h1 :style="{color:'red','font-weight':200}">这是一个h1</h1>
<h1 :style="[styleObj1,styleObj2]">这是一个h1</h1>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
styleObj1:{
color:'red','font-weight':200},
styleObj2:{
'font-style':'italic'}
},
methods:{
}
});
</script>
</body>
</html>
<!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>
</head>
<body>
<div id="app">
<!-- 循环普通数组 -->
<p v-for="(item,i) in list1">{
{
item}}---{
{
i}}</p>
<!-- 循环对象数组 -->
<p v-for="item in list2">{
{
item.id}}---{
{
item.name}}</p>
<!-- 遍历对象 -->
<p v-for="(val,key,i) in user">{
{
key}}---{
{
val}}---{
{
i}}</p>
<!-- 迭代数字 -->
<p v-for="count in 10">这是第{
{
count}}次循环</p>
<div>
<label for="">
ID:<input type="text" v-model="id">
</label>
<label for="">
Name:<input type="text" v-model='name'>
</label>
<input type="button" value="添加" @click="add">
</div>
<!-- key属性的使用 -->
<!-- 用key指定唯一字符串/数字 确保一一对应 -->
<p v-for="item in list3" :key="item.id">
<input type="checkbox">
{
{
item.name}}
</p>
</div>
<script src="./vue.min.js"></script>
<script>
var vm = new Vue({
el:'#app',
data:{
id:'',
name:'',
list1:[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:'jacky',
age:18
},
list3:[
{
id:1,name:"zs1"},
{
id:2,name:"zs2"},
{
id:3,name:"zs3"},
{
id:4,name:"zs4"},
],
},
methods:{
add:function(){
this.list3.unshift({
id:this.id,name:this.name});
}
}
});
</script>
</body>
</html>
<!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>
</head>
<body>
<div id="app">
<input type="button" value="切换" @click="toggle">
<!-- v-if的特点是会删除或创建元素 -->
<h3 v-if="flag">只是v-if控制的元素</h3>
<!-- v-show的特点只是切换了display:none样式 -->
<!-- v-show切换性能消耗较少 初始渲染性能消耗大 -->
<!-- 比如一个控件从来没有用过但依然被渲染出来了只不过display为none而已,但如果是v-if那就根本不会渲染 -->
<h3 v-show="flag">只是v-show控制的元素</h3>
</div>
<script src="./vue.min.js"></script>
<script>
var vm = new Vue({
el:'#app',
data:{
flag:true,
},
methods:{
toggle(){
this.flag=!this.flag;
}
}
});
</script>
</body>
</html>
运用前一天学习的内容和一些新东西,完成一个列表demo
实现了查找和增加功能。
具体要点都在注释里了。
<!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>
</head>
<script src="https://how2j.cn/study/js/jquery/2.0.0/jquery.min.js"></script>
<link href="https://how2j.cn/study/css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
<script src="https://how2j.cn/study/js/bootstrap/3.3.6/bootstrap.min.js"></script>
<body>
<div id="app">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">品牌</h3>
</div>
<div class="panel-body form-inline">
<label for="">
ID <input type="text" class="form-control" v-model="id" >
</label>
<label for="">
Name <input type="text" class="form-control" v-model="name" @keyup.enter='add'>
<!-- 这里也可以使用自定义的按键修饰符 Vue.config.keycode.f2 = 123 @keyup.f2='add'也就是设置了按f2就可以添加-->
</label>
<input type="button" value="添加" class="btn btn-primary" @click="add">
<label for="">
搜索名称关键字:<input type="text" class="form-control" v-model="keywords">
</label>
</div>
</div>
<table class="table table-hover table-bordered table-striped">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Ctime</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<!-- <tr v-for="item in list" :key="item.id"> 只能满足全部数据的渲染不能实现渲染搜索的数据 -->
<!-- 在search方法内部通过过滤的方法,来实现搜索数据,返回新数组 -->
<tr v-for="item in search(keywords)" :key="item.id">
<td>{
{
item.id}}</td>
<td>{
{
item.name}}</td>
<td>{
{
item.ctime|nameope()}}</td>
<td>
<a href="" @click.prevent="del(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script src="./vue.min.js"></script>
<script>
var vm = new Vue({
el:'#app',
data:{
id:'',
name:'',
keywords:'',
list:[
{
id:1,name:"奔驰",ctime:new Date()},
{
id:2,name:"宝马",ctime:new Date()},
{
id:3,name:"特斯拉",ctime:new Date()}
],
},
methods:{
add(){
if(this.id!=""){
this.list.push({
id:this.id,name:this.name,ctime:new Date})
this.id=""
this.name=""
}
else{
alert("id不能为空哦")
}
},
del(id){
var that=this
this.list.some(function(item,i){
if(item.id==id){
that.list.splice(i,1)
return true
}
})
},
//根据关键字,搜索数据
search(keywords){
// var newList=[]
// this.list.forEach(item=>{
// if(item.name.indexOf(keywords)!=-1){
// newList.push(item)
// }
// })
// return newList
// }
//forEach some filter findIndex这些都属于数组的新方法,都会对数组的每一项进行遍历,进行相关操作
//只是有一些小区别。
return this.list.filter(item=>{
//if(item.name.indexOf(keywords)!=-1)
if(item.name.includes(keywords)){
return item
}
})
}
},
//过滤器 使用格式{
{name|nameope}}
filters:{
nameope:function(date,pattern=""){
var dt=new Date(date)
var y=dt.getFullYear()
//padStart() 方法用另一个字符串填充当前字符串(如果需要的话,会重复多次),以便产生的字符串达到给定的长度。从当前字符串的左侧开始填充。
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.getHours().toString().padStart(2,'0')
var ss=dt.getSeconds().toString().padStart(2,'0')
return `${
y}-${
m}-${
d}-${
mm}:${
hh}:${
ss}`
}
}
}
});
</script>
</body>
</html>
学习了一下自定义指令做了一些简单修改
<!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>
</head>
<script src="https://how2j.cn/study/js/jquery/2.0.0/jquery.min.js"></script>
<link href="https://how2j.cn/study/css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
<script src="https://how2j.cn/study/js/bootstrap/3.3.6/bootstrap.min.js"></script>
<body>
<div id="app">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title" v-fontweight="900" v-fontsize="'30px'">品牌</h3>
</div>
<div class="panel-body form-inline">
<label for="" >
ID <input type="text" class="form-control" v-model="id" >
</label>
<label for="">
Name <input type="text" class="form-control" v-model="name" @keyup.enter='add'>
<!-- 这里也可以使用自定义的按键修饰符 Vue.config.keycode.f2 = 123 @keyup.f2='add'也就是设置了按f2就可以添加-->
</label>
<input type="button" value="添加" class="btn btn-primary" @click="add">
<label for="">
<!-- 这里v-focus是自定义指令 -->
搜索名称关键字:<input type="text" class="form-control" v-model="keywords" id="search" v-focus v-color="'blue'">
</label>
</div>
</div>
<table class="table table-hover table-bordered table-striped">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Ctime</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<!-- <tr v-for="item in list" :key="item.id"> 只能满足全部数据的渲染不能实现渲染搜索的数据 -->
<!-- 在search方法内部通过过滤的方法,来实现搜索数据,返回新数组 -->
<tr v-for="item in search(keywords)" :key="item.id">
<td>{
{
item.id}}</td>
<td>{
{
item.name}}</td>
<td>{
{
item.ctime|nameope()}}</td>
<td>
<a href="" @click.prevent="del(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script src="./vue.min.js"></script>
<script>
// 自定义指令
Vue.directive('focus', {
// 每当指令绑定到元素时,执行且只执行一次
bind:function(el){
// el.focus() 放在这里并不会调用,因为绑定指令的时候,元素还没有插入dom树中,focus()没有作用
},
// 插入到DOM中的时候,会执行inserted函数
inserted:function(el){
el.focus()
},
// 当VNode更新就会执行
updated:function(el){
}
});
Vue.directive('color', {
// 每当指令绑定到元素时,执行且只执行一次
bind:function(el,binding){
// 设置颜色
el.style.color=binding.value
},
inserted:function(el){
},
updated:function(el){
console.log(1)
}
});
var vm = new Vue({
el:'#app',
data:{
id:'',
name:'',
keywords:'',
list:[
{
id:1,name:"奔驰",ctime:new Date()},
{
id:2,name:"宝马",ctime:new Date()},
{
id:3,name:"特斯拉",ctime:new Date()}
],
},
methods:{
add(){
if(this.id!=""){
this.list.push({
id:this.id,name:this.name,ctime:new Date})
this.id=""
this.name=""
}
else{
alert("id不能为空哦")
}
},
del(id){
var that=this
this.list.some(function(item,i){
if(item.id==id){
that.list.splice(i,1)
return true
}
})
},
//根据关键字,搜索数据
search(keywords){
// var newList=[]
// this.list.forEach(item=>{
// if(item.name.indexOf(keywords)!=-1){
// newList.push(item)
// }
// })
// return newList
// }
//forEach some filter findIndex这些都属于数组的新方法,都会对数组的每一项进行遍历,进行相关操作
//只是有一些小区别。
return this.list.filter(item=>{
//if(item.name.indexOf(keywords)!=-1)
if(item.name.includes(keywords)){
return item
}
})
}
},
//过滤器 使用格式{
{name|nameope}}
filters:{
nameope:function(date,pattern=""){
var dt=new Date(date)
var y=dt.getFullYear()
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.getHours().toString().padStart(2,'0')
var ss=dt.getSeconds().toString().padStart(2,'0')
return `${
y}-${
m}-${
d}-${
mm}:${
hh}:${
ss}`
}
}
},
directives:{
'fontweight':{
bind:function(el,binding){
el.style.fontWeight=binding.value
}
},
'fontsize':function(el,binding){
el.style.fontSize=parseInt(binding.value)+'px'
}
}
});
//获取焦点的原生方法
// document.getElementById("search").focus()
// 改用通过自定义指令实现获取焦点
</script>
</body>
</html>
学习了Vue实例的生命周期具体要点都在注释中了。
贴一张很重要的图!!!
<!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>
</head>
<body>
<div id="app">
</div>
<script src="./vue.min.js"></script>
<script>
var vm = new Vue({
el:'#app',
data:{
},
methods:{
},
//创建阶段
beforeCreate () {
//1.
//生命周期函数,实例完全创建之前会执行他。
//在这个函数中执行的时候,data和method都还没有被初始化。
},
created () {
//2.
//在这个函数中data和method已经被初始化好了。
},
beforeMount () {
//3.
//Vue编译模板完成,执行Vue指令生成最终的模板字符串
//渲染为内存中的DOM,此时只是在内存中渲染好了模板并没有挂载到真正的页面中
//这是页面内容比如{
{msg}}这种形式的,还没有被替换
},
mounted () {
//4.
//已经挂载好页面了,可以看到渲染好的页面了。
//只要执行完这个函数就会进入从创建阶段到运行阶段
},
//运行阶段
beforeUpdate () {
//data 改变了之后执行
//界面 尚未和最新的数据保持同步
},
updated () {
//在这之前根据data最新的数据在内存中重新渲染出最新的DOM树,然后重新渲染真实的页面,实现页面的更新。
//这里的页面和内容都是最新的
},
//销毁阶段
beforeUpdate () {
//进入销毁阶段,但还没有执行销毁过程
//data和 method以及指令,过滤器都还可用
},
destroyed () {
//组件已完全销毁,所有上面的内容都不可用了
}
});
</script>
</body>
</html>
使用vue-resource发起get,post,jsonp请求
<!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.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
</head>
<body>
<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("http://vue.studyit.io/api/getlunbo").then(function(result){
console.log(result.body)
},function(err){
console.log('失败了')
})
},
postInfo(){
this.$http.post("http://vue.studyit.io/api/post",{
},{
emulateJSON:true}).then(function(result){
console.log(result.body)
})
},
jsonpInfo(){
this.$http.jsonp("http://vue.studyit.io/api/jsonp",{
},{
}).then(function(result){
console.log(result.body)
})
}
}
});
</script>
</body>
</html>
这里涉及到了跨域问题,我顺便又复习了一下Ajax,然后模拟客户端服务端实现一个跨域请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function show(data){
console.log(data)
}
</script>
<script src="http://127.0.0.1:3000/getscript?callback=show"></script>
</body>
</html>
服务端代码
const http=require('http')
const urlModule=require ('url')
const server =http.createServer()
server.on('request',function(req,res){
const {
pathname:url,query}=urlModule.parse(req.url,true)
if(url==='/getscript'){
var data={
name:'jacky',
age:18,
}
var scriptStr=`${
query.callback}(${
JSON.stringify(data)})`
res.end(scriptStr)
}else{
res.end('404')
}
})
server.listen(3000,function(){
console.log("server listen at http://127.0.0.1:3000")
})
学习了一下vue动画
要点都在注释中,几种方式都实现了
<!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.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css">
<!-- 自定义样式 来控制translation内部的元素实现动画 -->
</head>
<style>
.v-enter,
.v-leave-to{
opacity: 0;
transform:translateY(150px);
}
.v-leave-active,
.v-enter-active{
transition: all 0.8s ease;
}
.my-enter,
.my-leave-to{
opacity: 0;
transform:translateX(150px);
}
.my-leave-active,
.my-enter-active{
transition: all 0.8s ease;
}
</style>
<body>
<div id="app" >
<!-- 点击按钮使h3显示 在点击让h3隐藏 -->
<input type="button" @click="toggle" value="切换">
<transition name="my" mode="">
<h3 v-if="flag">这是一个h3标签</h3>
</transition>
<transition name="" mode="">
<h3 v-if="flag">这是一个h3标签</h3>
</transition>
<!-- 使用第三方类加载动画 -->
<transition name="" mode="" enter-active-class="animated bounceIn" leave-active-class="animated bounceOut" :duration="1000">
<h3 v-if="flag">这是一个h3标签</h3>
</transition>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
flag:false
},
methods:{
toggle(){
this.flag=!this.flag
}
}
});
</script>
</body>
</html>
为了实现半场动画效果需要用到vue动画的钩子函数
<!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.min.js"></script>
</head>
<style>
.ball{
width: 15px;
height: 15px;
border-radius: 50%;
background-color: brown;
margin: 10px;
}
</style>
<body>
<div id="app">
<input type="button" value="快到碗里来" @click="flag=!flag">
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
>
<div class="ball" v-show="flag">
</div>
</transition>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
flag:false
},
methods:{
beforeEnter(el){
el.style.transform="translate(0,0)"
},
enter(el,done){
el.offsetWidth
el.style.transform="translate(100px,450px)"
el.style.transition="all 1s ease"
done()
// done()函数是aterEnter的一个引用
// 官方规定必须调用,否则会有因为同步产生一些延迟影响
},
afterEnter(el){
this.flag=!this.flag
}
}
});
</script>
</body>
</html>
如果用js原生写的话就是
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.ball{
width: 15px;
height: 15px;
border-radius: 50%;
background-color: brown;
margin: 10px;
}
.fall{
/* transition: all 2s;
transform: translate(500px,500px); */
animation: change 2s;
animation-fill-mode: forwards;
}
@keyframes change {
0% {
transform:translate(0,0) scale(1)}
99% {
transform: translate(200px,450px);}
100%{
transform:scale(0) translate(0,0)}
}
</style>
<body>
<div>
<input type="button" name="" id="" value="启动" onclick="change()">
<div class='ball' id="ball"></div>
</div>
<script>
function change(){
var h=document.getElementById("ball");
h.classList.toggle("fall");
}
</script>
</body>
</html>
最后实现一个列表的动画,添加内容删除内容都哟与动态效果
<!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.min.js"></script>
</head>
<style>
li{
border: 1px dashed #999;
margin: 5px;
line-height: 35px;
padding: 5px;
list-style: none;
font-size: 10px;
width: 100%;
}
.v-enter,
.v-leave-to{
opacity: 0;
transform: translateY(80px);
}
.v-enter-active,
.v-leave-active{
transition: all 0.6s ease;
}
.v-leave-active{
position: absolute;
}
.v-move{
transition: all 0.6s ease;
}
li:hover{
background-color: rgb(247, 149, 165);
transition: all 2s ease;
}
</style>
<body>
<div id="app">
<div>
<label for="">
ID: <input type="text" v-model="id">
</label>
<label for="">
NAME: <input type="text" v-model="name">
</label>
<input type="button" value="添加" @click="add">
</div>
<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>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
id:'',
name:'',
list:[
{
id :1,name:"张婧仪"},
{
id :2,name:"王心怡"},
{
id :3,name:"周也"},
{
id :4,name:"小黑"},
]
},
methods:{
add(){
this.list.push({
id:this.id,name:this.name})
},
del(id){
this.list.splice(id,1)
}
}
});
</script>
</body>
</html>
实际上都差不多只是不同的写法罢了。
<!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.min.js"></script>
</head>
<body>
<div id="app">
<!-- 如果有大写字母则需要注意标签 -->
<my-com1></my-com1>
<mycom2></mycom2>
<mycom3></mycom3>
<login></login>
</div>
<template id="com3">
<p>这是第三种方式</p>
</template>
<script>
// 创建组件的第一种方式
// 使用Vue.extend创建全局组件
// 模板要用一个根元素包裹
var com1=Vue.extend({
template:'这是第一种方式
'
})
Vue.component('myCom1',com1)
//第二种方式
//也可以写在一起
Vue.component('mycom2',Vue.extend({
template:'这是第二种方式
'
}))
//第三种方式
Vue.component('mycom3',{
template: '#com3'})
var vm = new Vue({
el:'#app',
data:{
},
methods:{
},
components: {
login:{
template:'这是私有组件
'
}
}
});
</script>
</body>
</html>
<!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.min.js"></script>
</head>
<body>
<div id="app">
<mycom1></mycom1>
<mycom2></mycom2>
</div>
<template id="com2">
<div>{
{
count}}<input type="button" @click='add' value="+"></div>
</template>
<script>
// 组件中的data必须是方法且返回一个对象
Vue.component('mycom1',Vue.extend({
template:'引用data数据{
{msg}}
',
data () {
return {
msg:'这是组件中的数据',
}
},
methods: {
}
}))
Vue.component('mycom2',{
template: '#com2',
data () {
return {
count:0,
}
},
methods: {
add(){
this.count++
}
}
})
var vm = new Vue({
el:'#app',
data:{
},
methods:{
}
});
</script>
</body>
</html>
<!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.min.js"></script>
</head>
<style>
.v-enter,
.v-leave-to{
opacity: 0;
transform: translateX(150px);
}
.v-enter-active,
.v-leave-active{
transition: all 0.6s ease;
}
</style>
<body>
<div id="app">
<!-- 切换组件的第一种方式 -->
<!-- <a @click.prevent='flag=true'>登录</a>
<a @click.prevent='flag=false'>注册</a>
<login v-if='flag'></login>
<register v-else='flag'></register> -->
<!-- 切换组件的第二种方式 -->
<a href="" @click.prevent="conName='login'">登录</a>
<a href="" @click.prevent="conName='register'">注册</a>
<!-- <component :is="conName"></component> -->
<!-- 为组件添加一些动画 -->
<transition name="" mode="out-in">
<component :is="conName"></component>
</transition>
</div>
<script>
Vue.component('login',{
template:'登录
'
})
Vue.component('register',{
template:'注册
'
})
var vm = new Vue({
el:'#app',
data:{
flag:true,
conName:'login',
},
methods:{
}
});
</script>
</body>
</html>
<!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.min.js"></script>
</head>
<body>
<div id="app">
<mycom1></mycom1>
<mycom2></mycom2>
</div>
<template id="com2">
<div>{
{
count}}<input type="button" @click='add' value="+"></div>
</template>
<script>
// 组件中的data必须是方法且返回一个对象
Vue.component('mycom1',Vue.extend({
template:'引用data数据{
{msg}}
',
data () {
return {
msg:'这是组件中的数据',
}
},
methods: {
}
}))
Vue.component('mycom2',{
template: '#com2',
data () {
return {
count:0,
}
},
methods: {
add(){
this.count++
}
}
})
var vm = new Vue({
el:'#app',
data:{
},
methods:{
}
});
</script>
</body>
</html>
<!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.min.js"></script>
</head>
<body>
<div id="app">
<!-- 父组件在引用子组件的时候通过属性绑定,把数据传给子组件 -->
<com1 :parentmsg="msg" @fun="show"></com1>
</div>
<template id="mycom1">
<div>
<p>这是子组件---{
{
parentmsg}}</p>
<input type="button" @click="myclick" value="触发父组件的方法">
</div>
</template>
<script>
var vm = new Vue({
el:'#app',
data:{
msg:'父组件的内容'
},
methods:{
show(data){
this.msg= this.msg+" 加了一些新内容"+data
}
},
components: {
// 经过验证,默认子组件默认无法访问父组件的数据和方法 需要父组件向子组件传值
com1:{
template:'#mycom1',
data () {
return {
//子组件中的data数据是自己私有的,比如ajax请求回来的数据就可以放在这里
}
},
methods: {
myclick(){
//调用父组件的fun方法
this.$emit('fun',123);
}
},
props: ['parentmsg'],
// props的数据都是只读的(实际上修改数据界面还是会改变,但Vue不建议这样做,会警告),而data是可读可写的。
}
}
});
</script>
</body>
</html>
运用组件知识写了一个评论列表案例
<!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.min.js"></script>
<script src="https://how2j.cn/study/js/jquery/2.0.0/jquery.min.js"></script>
<link href="https://how2j.cn/study/css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
<script src="https://how2j.cn/study/js/bootstrap/3.3.6/bootstrap.min.js"></script>
</head>
<body>
<div id="app">
<cmt-box @load="loadComments"></cmt-box>
<ul class="list-group">
<li class="list-group-item" v-for="item in list" :key="item.id">
<span class="badge">评论人:{
{
item.user}}</span>
{
{
item.content}}
</li>
</ul>
</div>
<template id="tmp1">
<div>
<div class="form-group">
<label for="">评论人</label>
<input type="text" class="form-control" v-model="user">
</div>
<div class="form-group">
<label for="">评论内容</label>
<textarea class="form-control" v-model="content"></textarea>
</div>
<div class="form-group">
<input type="button" class="btn btn-primary" value="发表评论" @click="postComment"></input>
</div>
</div>
</template>
<script>
var contentBox={
template: "#tmp1",
data () {
return {
user:"",
content:"",
}
},
methods: {
postComment(){
var comment={
id:Date.now(),user:this.user,content:this.content}
var list=JSON.parse(localStorage.getItem('cmts')||'[]')
list.unshift(comment)
localStorage.setItem('cmts',JSON.stringify(list))
this.user=''
this.content=''
this.$emit('load');
}
}
}
var vm = new Vue({
el:'#app',
data:{
list:[
{
id:Date.now(),user:'张婧仪',content:'善良勇敢有担当'},
{
id:Date.now(),user:'王心怡',content:'云烟成雨'},
{
id:Date.now(),user:'薛之谦',content:'认真的雪'}
]
},
created () {
this.loadComments()
},
methods:{
loadComments(){
var list=JSON.parse(localStorage.getItem('cmts')||'[]')
this.list=list
}
},
components: {
'cmt-box': contentBox,
}
});
</script>
</body>
</html>
<!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.min.js"></script>
</head>
<body>
<div id="app">
<input type="button" value="获取文本元素" @click='getElement'>
<h3 id="myh3" ref="myh3">今天天气很好</h3>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
},
methods:{
getElement(){
console.log(this.$refs.myh3.innerText)
// 也可以运用到组件中
}
}
});
</script>
</body>
</html>
<!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.min.js"></script>
<script src="./vue-router.js"></script>
<style>
/* 可以使用自定义的css样式也可以直接在原有的css样式上添加 */
.router-link-active,.myActive{
color: red;
font-style: italic;
}
.v-enter,.v-leave-to{
opacity: 0;
transform: translateX(180px);
}
.v-enter-active,
.v-leave-active{
transition: all 0.8s ease;
}
</style>
</head>
<body>
<div id="app">
<!-- <a href="#/login">登录</a>
<a href="#/register">注册</a> -->
<router-link to="/login?id=10">登录1</router-link>
<router-link to="/login/10">登录2</router-link>
<router-link to="/register">注册</router-link>
<!-- router-link默认渲染a标签 -->
<transition name="" mode="out-in">
<router-view></router-view>
</transition>
<!-- 被当做一个占位符 -->
</div>
<script>
// 组件模板对象
var login1={
template:'这是登录组件 ----利用query的方式传参---id是{
{$route.query.id}}
',
created () {
console.log(this.$route.query.id)
}
}
var login2={
template:'这是登录组件 ----利用params的方式传参---id是{
{$route.params.id}}
',
created () {
console.log(this.$route.params.id)
}
}
var register={
template:'这是注册组件
'
}
// 导入路由包之后就有一个路由构造函数了
var routerObj = new VueRouter({
// 路由匹配规则
routes :[
// {path:'/',component: login},
{
path:'/',redirect: '/login'},
{
path:'/login',component: login1},
{
path:'/login/:id',component: login2},
{
path:'/register',component: register},
],
linkActiveClass:'myActive'
});
var vm = new Vue({
el:'#app',
data:{
},
methods:{
},
router: routerObj
});
</script>
</body>
</html>
<!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.min.js"></script>
<script src="./vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/account">Account</router-link>
<router-view></router-view>
</div>
<template id="tmp">
<div>
<p>这是Account组件</p>
<router-link to="/account/login">登录</router-link>
<router-link to="/account/register">注册</router-link>
<router-view ></router-view>
</div>
</template>
<script>
var account={
template:'#tmp'
}
var login={
template:'这是登录组件
'
}
var register={
template:'这是注册组件
'
}
var router=new VueRouter({
routes:[
{
path: '/account', component: account ,
// 使用childern实现子路由不要带/,否则永远以根路径开始请求
children:[
{
path:'login',component: login},
{
path:'register',component: register}
]
},
// { path: '/account/login', component: login },
// { path: '/account/register', component: register },
]
})
var vm = new Vue({
el:'#app',
data:{
},
methods:{
},
router
});
</script>
</body>
</html>
<!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.min.js"></script>
<script src="./vue-router.js"></script>
<style>
*{
margin: 0;
padding: 0;
}
.head{
background-color: aquamarine;
height: 80px;
}
.container{
display: flex;
height: 600px;
}
.left{
background-color: blue;
flex: 2;
}
.main{
background-color: chartreuse;
flex: 8;
}
</style>
</head>
<body>
<div id="app">
<router-view name='default'></router-view>
<div class="container">
<router-view name='left'></router-view>
<router-view name='main'></router-view>
</div>
</div>
<script>
var header={
template:"这是头部区域
"
}
var left={
template:"这是侧边区域
"
}
var main={
template:"这是主体区域
"
}
var router=new VueRouter({
routes:[
// {path:'/',component:header},
// {path:'/left',component:left},
// {path:'/main',component:main},
{
path:'/',components:{
'default':header,
'left':left,
'main':main
}},
]
})
var vm = new Vue({
el:'#app',
data:{
},
methods:{
},
router:router
});
</script>
</body>
</html>
实现的一个名称小案例
要求实现两个文本框内容拼接并放在第三个文本框中。
有三种实现方式:
第一种常规想法运用methods:
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>Documenttitle>
<script src="./vue.min.js">script>
head>
<body>
<div id="app">
<input type="text" v-model="firstname" @keyup="getName">
<input type="text" v-model="lastname" @keyup="getName">
<input type="text" v-model="name">
div>
<script>
var vm = new Vue({
el:'#app',
data:{
firstname:"",
lastname:"",
name:"",
},
methods:{
getName(){
this.name=this.firstname+this.lastname
}
}
});
script>
body>
html>
第二种运用watch:
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>Documenttitle>
<script src="./vue.min.js">script>
head>
<body>
<div id="app">
<input type="text" v-model="firstname">+
<input type="text" v-model="lastname">=
<input type="text" v-model="name">
<p>watch还可以监视路由的变化p>
div>
<script>
var vm = new Vue({
el:'#app',
data:{
firstname:"",
lastname:"",
name:"",
},
methods:{
getName(){
this.name=this.firstname+this.lastname
},
},
// 使用这个属性,可以监听data指定数据的变化,然后触发这个watch对应的函数
watch: {
firstname:function(newVal,oldVal){
console.log("监视到了firstname的变化了")
// this.name=this.firstname+'-'+this.lastname
this.name=newVal+'-'+this.lastname
},
lastname:function(newVal,oldVal){
console.log("监视到了firstname的变化了")
// this.name=this.firstname+'-'+this.lastname
this.name=this.firstname+'-'+newVal
},
}
});
script>
body>
html>
watch的优点相比于其他的方式在于他可以监听一些虚拟的,不能放置监听事件的一些属性,比如说路由。
这个例子可以说明
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>Documenttitle>
<script src="./vue.min.js">script>
<script src="./vue-router.js">script>
head>
<body>
<div id="app">
<router-link to="/account">Accountrouter-link>
<router-view>router-view>
div>
<template id="tmp">
<div>
<p>这是Account组件p>
<router-link to="/account/login">登录router-link>
<router-link to="/account/register">注册router-link>
<router-view >router-view>
div>
template>
<script>
var account={
template:'#tmp'
}
var login={
template:'这是登录组件
'
}
var register={
template:'这是注册组件
'
}
var router=new VueRouter({
routes:[
{
path: '/account', component: account ,
// 使用childern实现子路由不要带/,否则永远以根路径开始请求
children:[
{
path:'login',component: login},
{
path:'register',component: register}
]
},
// { path: '/account/login', component: login },
// { path: '/account/register', component: register },
]
})
var vm = new Vue({
el:'#app',
data:{
},
methods:{
},
router,
watch: {
'$route.path':(newVal,oldVal)=>{
console.log(newVal+'---'+oldVal)
}
}
});
script>
body>
html>
第三种实现方式是利用计算属性computed:
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>Documenttitle>
<script src="./vue.min.js">script>
head>
<body>
<div id="app">
<input type="text" v-model="firstname">+
<input type="text" v-model="lastname">=
<input type="text" v-model="name">
div>
<script>
var vm = new Vue({
el:'#app',
data:{
firstname:"",
lastname:"",
// name:"",
},
methods:{
},
// 在这个对象中可以定义一些属性-计算属性
// 计算属性实际上是方法,但引用时不用加()当做属性来使用。
// 计算属性内部依赖的data数据,只要发生改变就会立即重新计算其值
// 计算数据会被缓存起来,如果没有改变则会直接调用。
computed: {
name:function(){
return this.firstname+'-'+this.lastname
}
}
});
script>
body>
html>
三者之前区别和许多要点都在注释中了。