一、技术栈
image.png二、参考文献
三、引入
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
[v-cloak]{
display:none;
}
</style>
<!-- 2. 使用CDN -->
<!-- <script src="https://cdn.jsdelivr.net/npm/vue"></script> -->
<!-- 3. npm加载 npm i vue -->
</head>
<body>
<div id="app" v-cloak>
<h1>{{ msg }}</h1>
状态码是:<span>{{ code }}</span>
</div>
<!-- 1. 直接下载源码,使用script标签引入 -->
<script src="vue.js"></script>
<script type="text/javascript">
new Vue({
el:'#app', //element 挂载在DOM节点上
data:{
msg:"欢迎学习VUE",
code:"200"
}
});
</script>
</body>
</html>
四、常用指令
1、v-bind(简写为:)
动态地绑定一个或多个特性,或一个组件 prop 到表达式
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
.bg-color-red{
background: red;
}
.color-white{
color:#fff;
}
.color-blue{
color:blue;
}
</style>
</head>
<body>
<div id="app">
<span :class="cla" :style="style">这里是文字</span>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
cla:{
"bg-color-red":true,
"color-white":true
},
style:{
background:"yellow",
color:"lightgreen"
}
}
})
</script>
</body>
</html>
2、v-on(简写为:@)
绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
</head>
<body>
<div id="app">
<input type="button" value="点击" v-on:click="sayhello">
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
new Vue({
el:'#app',
data:{},
methods:{
sayhello(){
alert('hello')
}
}
});
</script>
</body>
</html>
案例:跑马灯
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<input type="button" value="浪起来" @click="lang">
<input type="button" value="猥琐发育" @click="weisuo">
<p>{{msg}}</p>
</div>
</body>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script>
new Vue({
el:"#app",
data:{
msg:"猥琐发育,别浪~",
timer:null
},
methods:{
lang(){
clearInterval(this.timer);
this.timer = setInterval(()=>{
this.msg = this.msg.substring(1)+this.msg.substring(0,1);
},300)
},
weisuo(){
clearInterval(this.timer);
}
}
})
</script>
</html>
3、v-model
在表单控件或者组件上创建双向绑定
案例:计算器
<!DOCTYPE html>
<html lang="zh">
<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></title>
<style type="text/css">
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<input type="text" v-model:value="num1">
<select v-model:value="fuhao">
<option value ="+" >+</option>
<option value ="-">-</option>
<option value ="*">×</option>
<option value ="/">÷</option>
</select>
<input type="text" v-model:value="num2">
<button @click="cal()">=</button>
<span v-text="re"></span>
</div>
<script src="vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
num1: '',
num2:'',
fuhao:'',
re: ''
},
methods:{
cal:function(){
this.re = eval(this.num1 + this.fuhao + this.num2) ;
}
},
computed:{
}
});
</script>
</body>
</html>
4、v-for
遍历
<!DOCTYPE html>
<html lang="zh">
<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></title>
</head>
<body>
<div id="app" v-cloak>
<ul>
<li v-for="user in users" :key="user.id"><input type="checkbox">{{user.id}}-----{{user.name}}</li>
</ul>
<button @click="del">shanchu</button>
<!-- <ol>
<li v-for="(iten,key) in zhangsan">{{iten}}--{{key}}</li>
</ol> -->
</div>
<script src="vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
users:[
{id:2,name:'zengke'},
{id:3,name:'zhangzhen'},
{id:4,name:'lihaoshuahg'},
{id:7,name:'xiongli'},
{id:9,name:'yanhe'}
],
zhangsan:{
age:19,
sex:"man",
grade:'大三年级'
},
},
methods:{
del(){
this.users.shift()
}
}
});
</script>
</body>
</html>
五、filter
过滤器
<!DOCTYPE html>
<html lang="zh">
<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></title>
</head>
<body>
<div id="app" v-cloak>
<p>{{ msg | change('--') | dada('**') }}</p>
</div>
<div id="dapp">
{{msg | dada('xixi')}}
</div>
<script src="js/vue.js"></script>
<script type="text/javascript">
//全局过滤器.任何一个Vue节点都可以使用
Vue.filter('change',function(data,arg){
return data.replace(/天真/g,arg);
});
Vue.filter('dada',function(data,arg){
return data.replace(/我/g,arg);
});
new Vue({
el:"#app",
data:{
msg:"天真的我对天真的自己说,我是这个世界上最天真的人呢!"
},
// 局部过滤器
filters:{
dada:function(data,arg){
return data.replace(/我/g,arg)+'--------------------'; //就近原则
}
}
});
new Vue({
el:"#dapp",
data:{
msg:"快乐的池塘里我有一只快乐的我小青蛙"
}
})
</script>
</body>
</html>
六、键盘事件
<!DOCTYPE html>
<html lang="zh">
<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></title>
</head>
<body>
<div id="app" v-cloak>
<input type="text" @keyup.82="print">
{{ msg }}
</div>
<script src="js/vue.js"></script>
<script type="text/javascript">
//自定义键盘事件修饰符
// Vue.config.keyCodes.add = 82;
new Vue({
el:"#app",
data:{
msg:''
},
methods:{
print(event){
this.msg = event.target.value;
}
}
});
</script>
</body>
</html>
七、自定义指令
<!DOCTYPE html>
<html lang="zh">
<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></title>
</head>
<body>
<form action="" id="app">
用户名<input type="text" id="user" v-focus><br><br>
<!-- 使用自定义的指令必须要添加v-前缀 vue指令的规范是所有的指令都是以v-前缀开始的 -->
密码<input type="text"><br><br>
<input type="submit">
</form>
</body>
<script src="../day1/vue.js" type="text/javascript" charset="utf-8"></script>
<script>
/*
window.onload = function(){
document.getElementById('user').focus();
}
*/
//扩展VUE指令,自定义指令
//全局的
//参数一:指令的名称,注意这里的指令的名称是定义的时候,不需要添加v-前缀
//参数二:是一个指令的配置对象
Vue.directive('focus',{
//配置项,钩子函数
//第一个参数,指令操作的节点
bind:function(el){
//指令在第一次调用的时候出发,VUE的虚拟dom在进行渲染的时候触发.这个时候节点还没有进入真实dom
},
inserted:function(el){
//在虚拟dom进去到真实dom的时候调用
el.focus();
},
update:function(el){
//在节点更新的时候使用
}
});
new Vue({
el:"#app",
data:{
}
});
</script>
</html>
八、自定义有值指令
<!DOCTYPE html>
<html lang="zh">
<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></title>
</head>
<body>
<div id="app" v-cloak>
<p v-fontsize:style="'20px'" >要经常给妈妈点钱,让妈妈去挥霍吧!</p>
</div>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
Vue.directive('fontsize',{
bind:function(el,binding){
// binding.arg 元素的键(style)
el[binding.arg].fontSize = binding.value;
console.log(binding)
},
inserted:function(){},
update:function(){}
})
Vue.directive('name',function(el,song){
// el.操作
})
new Vue({
el:"#app",
data:{
}
});
</script>
</body>
</html>
九、自定义指令对象传参
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
div>div{
width:20px;
height:20px;
background: #2AC845;
}
.show{
border: 1px dashed #007AFF;
}
.size{
width:200px;
height: 200px;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<div v-bind:class="style" v-style:style="{'font-size':'20px',background:'red'}">
lalalala
</div>
</div>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
Vue.directive('style',function(el,bin){
for(let i in bin.value){
el.style[i] = bin.value[i];
}
})
new Vue({
el:"#app",
data:{
style:{
show: true,
size:true
}
}
});
</script>
</body>
</html>
十、局部定义
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
<!-- <input type="text" v-focus> -->
</div>
<footer id="dapp">
<input type="text" v-focus>
</footer>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
/*
Vue.directive('focus',{
bind:function(){},
inserted:function(el){
el.focus();
},
update:function(){}
})
*/
new Vue({
el:"#app",
data:{
},
directives:{
focus:{
bind:function(){},
inserted:function(el){
el.focus();
},
update:function(){}
}
}
});
new Vue({
el:"#dapp",
data:{
}
});
</script>
</body>
</html>
十一、vue-resource
网络请求
<!DOCTYPE html>
<html lang="zh">
<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></title>
<style>
ul{
list-style: none;
}
ul li {
width:100px;
height:150px;
border:1px solid #ccc;
margin: 20px;
}
ul li img{
width:100%;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<ul>
<li v-for="user in list">
<img v-bind:src="user.avatar_url" alt="user.login">
{{user.login}}
</li>
</ul>
</div>
<script src="../day1/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-resource@1.5.1"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
list:[]
},
created:function(){
this.$http.get('https://api.github.com/users').then(function(response){
this.list = response.body;
},function(){
});
}
});
</script>
</body>
</html>
十二、axios
基于promise用于浏览器和node.js的http客户端
特点
- 支持浏览器和node.js
- 支持promise
- 能拦截请求和响应
- 能转换请求和响应数据
- 能取消请求
- 自动转换JSON数据
- 浏览器端支持防止CSRF(跨站请求伪造)
发送请求的两种方式
<!DOCTYPE html>
<html lang="zh">
<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></title>
</head>
<body>
<div id="app" v-cloak>
<input type="button" value="获取" @click="getlist">
<ul>
<li v-for="item in list" :key="item.id">item.name</li>
</ul>
</div>
<script src="../day1/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
list:[]
},
methods:{
getlist:function(){
axios.get('http://localhost/vue_api/index.php?m=api&a=getlist').then(response=>{
this.list = response.data;
console.log(this.list);
}).catch(error=>{
//处理错误
})
}
},
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
<input type="text" v-model:value="id">
<input type="text" v-model:value="name">
<input type="button" value="提交" @click="add">
</div>
<script src="../day1/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
id:"",
name:''
},methods:{
add(){
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
/*
axios.post('http://localhost/vue_api/index.php?m=api&a=addcar',{id:this.id,name:this.name,ctime:new Date().toUTCString()}).then(response=>{
console.log(response.data);
})
*/
axios({
method:'post',
url:'http://localhost/vue_api/index.php?m=api&a=addcar',
data:{
id:this.id,
name:this.name,
ctime:new Date().toUTCString()
},
headers:{
'Content-Type':'application/x-www-form-urlencoded'
},
//在传递post数据的时候如果没有经过这样的处理,那么后端接收数据会非常麻烦.
/*
transformRequest:[
data=>{
let params = '';
for (var index in data) {
params += index + '=' + data[index] + '&'
}
return params;
}
]
*/
}).then(response=>{
console.log(response.data);
})
}
}
});
</script>
</body>
</html>
十三、动画
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
@keyframes boom{
0%{
transform: scale(0);
}
50%{
transform: scale(1.5);
}
100%{
transform: scale(1);
}
}
.v-enter-active{
animation: boom 1s ease;
}
.v-leave-active{
animation: boom 1s reverse;
}
p{
width:200px;
height:200px;
background: #4CD964;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<button @click="flag=!flag">boom</button>
<!-- 所有需要进行动画或者过度的元素必须添加在transition标签里面 -->
<transition>
<p v-show="flag">好烦你呀</p>
</transition>
</div>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
flag:true
}
});
</script>
</body>
</html>
十四、使用动画类实现动画
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css">
</head>
<body>
<div id="app" v-cloak>
<button @click="flag=!flag">animate</button>
<!-- 如果传入的值是一个固定的值,那么这个值表示的是进场与离场动画相同的时间 -->
<!-- :duration="1000" -->
<transition name="my"
enter-active-class="bounceInDown"
leave-active-class="bounceOutDown"
:duration="{enter:800,leave:500}"
>
<div v-show="flag" class="animated">中午睡觉吃了一只蚊子</div>
</transition>
</div>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
flag:false
}
});
</script>
</body>
</html>
十五、钩子函数实现动画效果
<!DOCTYPE html>
<html lang="zh">
<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></title>
<style>
#app div{
width:50px;
height:50px;
background: cyan;
border-radius: 50%;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<button @click="flag=!flag">动画</button>
<transition
@before-enter="before"
@enter="enter"
@after-enter="after"
>
<div v-show="flag"></div>
</transition>
</div>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
flag:false
},
methods:{
// el表示要操作的DOM对象
before(el){
el.style.transform = 'translate(0,0)';
},
enter(el,done){
el.offsetWidth ;
// 需要使用offset系列实现动画的刷新或者平滑过渡
el.style.transform = 'translate(350px,150px)';
el.style.transition = 'all .3s ease';
done(); //down回调函数就是指下面after函数
},
after(el){
this.flag= !this.flag;
}
}
});
</script>
</body>
</html>
十六、列表过渡
<!DOCTYPE html>
<html lang="zh">
<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></title>
<style>
li{
line-height: 50px;
padding:5px;
border:1px dashed #333;
margin-bottom: 10px;
text-indent: 1em;
width:100%
}
li:hover{
background: lightseagreen;
transition: all 0.3s ease;
}
input {
margin-left:40px;
height:60px;
width:200px;
font-size: 20px;
text-indent: 20px;
}
.my-enter,
.my-leave-to{
transform: translateY(200px);
opacity: 0;
}
.my-enter-active,
.my-leave-active{
transition: all 1s ease-in-out;
}
.my-move{
transition : all 1s ;
}
.my-leave-active {
position: absolute;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<input type="text" v-model:value="id">
<input type="text" v-model:value="name">
<input type="button" value="添加" @click="add">
<transition-group name="my" tag="ul" appear >
<li v-for="(item,index) in list" :key="item.id" @click="del(index)">{{item.id}}. {{item.name}}</li>
</transition-group>
</div>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
id:'',
name:'',
list:[
{id:1,name:'魏忠贤'},
{id:3,name:'赵高'},
{id:4,name:'曹正淳'},
{id:6,name:'李公公'},
]
},
methods:{
add(){
this.list.push({id:this.id,name:this.name});
this.id = this.name = '';
},
del(i){
this.list.splice(i,1);
}
}
});
</script>
</body>
</html>
十七、生命周期函数
参考文献:https://segmentfault.com/a/1190000011381906
beforeCreate
-
类型:
Function
-
详细:
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
-
参考:生命周期图示
created
-
类型:
Function
-
详细:
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,
$el
属性目前不可见。 -
参考:生命周期图示
beforeMount
-
类型:
Function
-
详细:
在挂载开始之前被调用:相关的
render
函数首次被调用。该钩子在服务器端渲染期间不被调用。
-
参考:生命周期图示
mounted
-
类型:
Function
-
详细:
el
被新创建的vm.$el
替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当mounted
被调用时vm.$el
也在文档内。注意
mounted
不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉mounted
:mounted: function () { this.$nextTick(function () { // Code that will run only after the // entire view has been rendered }) }
该钩子在服务器端渲染期间不被调用。
-
参考:生命周期图示
beforeUpdate
-
类型:
Function
-
详细:
数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。
-
参考:生命周期图示
updated
-
类型:
Function
-
详细:
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
注意
updated
不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 vm.$nextTick 替换掉updated
:updated: function () { this.$nextTick(function () { // Code that will run only after the // entire view has been re-rendered }) }
该钩子在服务器端渲染期间不被调用。
-
参考:生命周期图示
activated
-
类型:
Function
-
详细:
keep-alive 组件激活时调用。
该钩子在服务器端渲染期间不被调用。
-
参考:
deactivated
-
类型:
Function
-
详细:
keep-alive 组件停用时调用。
该钩子在服务器端渲染期间不被调用。
-
参考:
beforeDestroy
-
类型:
Function
-
详细:
实例销毁之前调用。在这一步,实例仍然完全可用。
该钩子在服务器端渲染期间不被调用。
-
参考:生命周期图示
destroyed
-
类型:
Function
-
详细:
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
该钩子在服务器端渲染期间不被调用。
errorCaptured
2.5.0+ 新增
-
类型:
(err: Error, vm: Component, info: string) => ?boolean
-
详细:
当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回
false
以阻止该错误继续向上传播。你可以在此钩子中修改组件的状态。因此在模板或渲染函数中设置其它内容的短路条件非常重要,它可以防止当一个错误被捕获时该组件进入一个无限的渲染循环。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
<button @click="msg='还好吧'">改变</button>
{{msg}}
</div>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
msg:'今天真是个好日子呀'
},
methods:{},
computed:{},
filters:{},
directives:{},
components:{}, //组件
beforeCreate:function(){
alert('beforeCreate');
},
created:function(){
alert('created');
},
beforeMount:function(){
alert('beforeMount');
},
mouted:function(){
alert('mouted');
},
beforeUpdate:function(){
alert('beforeUpdate');
},
updated:function(){
alert('updated');
},
beforeDestroy:function(){
alert('beforeDestroy');
},
destroyed:function(){
alert('destroyed');
}
});
</script>
</body>
</html>
十八、创建组建的方式
//法一
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
<!-- //全局组件可以使用在任何一个VUE所挂载的DOM上。 -->
<!-- //使用的组件的方式是将组建用于类似于HTML的结构,按照HTML双标签的格式书写 -->
<mycom></mycom>
</div>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
/*
//创建组件对象
var com= Vue.extend({
template:'<h3>这里是组件在内容</h3>'
});
//注册组件
//参数1是组件的名称,使用组件的时候要使用这个名称
//参数2是组件的对象
Vue.component('mycom',com);
*/
Vue.component('mycom',Vue.extend({
template:'<h3>也行</h3>'
}))
new Vue({
el:"#app",
data:{
}
});
</script>
</body>
</html>
//法二
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
<my-com></my-com>
</div>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
//组件的名称可以是驼峰法命名,但是在使用的时候要替换成以中划线分隔的形式
Vue.component('my-com',{
template:'<h3>这里是组件模板</h3>'
});
new Vue({
el:"#app",
data:{
}
});
</script>
</body>
</html>
//法三
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
<mycom></mycom>
</div>
<!-- //需注意模板必须是放置在挂载节点之外。 -->
<!-- 使用id作为组件的标识 -->
<!-- 组件的模板只允许具有一个根节点 -->
<template id="tl">
<div>
<h3>这里是组件</h3>
<div>lalalal</div>
</div>
</template>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
Vue.component('mycom',{
template: '#tl'
})
new Vue({
el:"#app",
data:{
}
});
</script>
</body>
</html>
//法四
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
<mycom></mycom>
</div>
<!-- 每一个组件都是一个VUE的实例 -->
<script id="el" type="x-template">
<div>这里是组件内容</div>
</script>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
Vue.component('mycom',{
template:"#el",
//组件的数据必须是一个函授,而且这个函数必须返回的是一个对象,而且这个对象必须是内置定义的对象
data:function(){
return {};
}
})
new Vue({
el:"#app",
data:{
}
});
</script>
</body>
</html>
案例:组件计算器
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
<mycom></mycom>
<mycom></mycom>
<mycom></mycom>
<mycom></mycom>
<mycom></mycom>
</div>
<div id="dapp">
<mycom></mycom>
</div>
<template id="el">
<div>
<button @click="add">+1</button>
{{count}}
</div>
</template>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
Vue.component('mycom',{
template:'#el',
data:function(){
//每一次返回的是一个新的对象,不同的组件之间是不会相互影响的
return {
count:0
};
},
methods:{
add(){
this.count++;
}
}
})
new Vue({
el:"#app",
data:{
}
});
new Vue({
el:'#dapp'
})
</script>
</body>
</html>
十九、私有组件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
<mycom></mycom>
</div>
<div id="dapp">
<mycom></mycom>
</div>
<template id="cc">
<div>
这里是私有组件
</div>
</template>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
},
components:{
mycom:{
template:"#cc"
}
}
});
new Vue({
el:"#dapp"
})
</script>
</body>
</html>
二十、组件切换
//法一:v-if
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
<a href="" @click.prevent="flag=true">登录</a>
<a href="" @click.prevent="flag=false">注册</a>
<login v-if="flag"></login>
<register v-else="flag"></register>
</div>
<template id="login">
<div><h3>这里是登录组件</h3></div>
</template>
<template id="register">
<div>
<h3>这里是注册组件</h3>
</div>
</template>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
flag:false
},
components:{
login:{
template:"#login"
},
register:{
template:"#register"
}
}
});
</script>
</body>
</html>
//法二:components
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
h3{
width:80%;
height:300px;
background: lightgreen;
margin:80px auto;
}
.my-animate-enter,
.my-animate-leave-to{
opacity: 0;
transform: translateX(50px);
}
.my-animate-enter-active,
.my-animate-leave-active{
transition: all 1s ease;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<a href="" @click.prevent="com='login'">登录</a>
<a href="" @click.prevent="com='register'">注册</a>
<transition name="my-animate" mode="out-in">
<component :is="com"></component>
</transition>
<!-- component 组件切换-->
<!-- trasnition 过度动画-->
<!-- transition-group 列表的过度动画-->
<!-- template 组件的模板-->
</div>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
com:'login'
},
components:{
login:{
template:'<h3>这是登录组件</h3>'
},
register:{
template:'<h3>这是注册组件</h3>'
}
}
});
</script>
</body>
</html>
二十一、组件传值
//父组件向子组件传值
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
父组件向子组件传值,使用数据绑定的方式传递。:后面的值必须在组建中使用pros接收。否则在子组件中没有办法获取到父组件通过这种方式传过来的值
<mycom :pmsg="parentmsg" ></mycom>
</div>
<template id="el">
<div>
<h2>这里是我创建的组件:{{msg}}-{{pmsg}}</h2>
</div>
</template>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
parentmsg:'古道西风瘦马'
},
components:{
mycom:{
template:'#el',
data(){
return {
msg:'风吹草低见牛羊',
}
},
methods:{
},
//这里使用pros接受的数据的名称与组件传递的时候绑定的名称是一模一样的
props:['pmsg']
}
},
});
</script>
</body>
</html>
//父组件向子组件传递方法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
{{conso('不怕热')}}
对于方法来说,传递到子组件要是用事件绑定的形式
<mycom v-on:func="conso"></mycom>
</div>
<template id="el">
<button @click="tirrger">点击触发父组件的conso方法</button>
</template>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
},
methods:{
conso(i){
console.log('30度的日子就要来临了---'+i)
}
},
components:{
mycom:{
template:'#el',
data:function(){
return {};
},
props:[],
methods:{
tirrger(){
//对于父组件传递的方法而言,其实并不是将这个方法传递给子组件,而是要求子组件将这个方法进行触发.
//$emit 函数触发的函数如果是需要传递参数,那么按照参数的顺序从第二个参数开始进行传递
this.$emit('func','不怕辣');
}
}
}
}
});
</script>
</body>
</html>
//子组件向父组件传递方法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app" v-cloak>
{{conso('不怕热')}}
对于方法来说,传递到子组件要是用事件绑定的形式
<mycom v-on:func="conso"></mycom>
</div>
<template id="el">
<button @click="tirrger">点击触发父组件的conso方法</button>
</template>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
msg:''
},
methods:{
conso(i){
this.msg = i;
}
},
components:{
mycom:{
template:'#el',
data:function(){
return {
msg:'僵小鱼'
};
},
props:[],
methods:{
tirrger(){
//对于父组件传递的方法而言,其实并不是将这个方法传递给子组件,而是要求子组件将这个方法进行触发.
//$emit 函数触发的函数如果是需要传递参数,那么按照参数的顺序从第二个参数开始进行传递
this.$emit('func',this.msg);
}
}
}
}
});
</script>
</body>
</html>
案例:列表评论
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div id="app" v-cloak>
<discuss @func="flash"></discuss>
<ul class="list-group">
<li class="list-group-item" v-for="item in list" :key="item.id">
<span class="badge">{{item.name}}</span>
{{item.content}}
</li>
</ul>
</div>
<template id="el">
<form action="">
<div class="form-group">
<label for="author">作者</label>
<input type="text" class="form-control" id="author" v-model:value="author">
</div>
<div class="form-group">
<label for="content">内容</label>
<textarea id="content" class="form-control" v-model:value="content"></textarea>
</div>
<div class="form-group">
<input type="button" class="form-control btn-primary" value="发表" @click="add">
</div>
</form>
</template>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
list:[]
},
methods:{
flash(){
this.list = JSON.parse(localStorage.getItem('discuss-list') || '[]');
}
},
components:{
discuss:{
template:'#el',
data(){
return {
author:'',
content:''
};
},
methods:{
add(){
let list = JSON.parse(localStorage.getItem('discuss-list') || '[]');
list.push({id:Math.random(100),name:this.author,content:this.content});
localStorage.setItem('discuss-list',JSON.stringify(list));
this.author=this.content = '';
this.$emit('func');
}
}
}
},
created:function(){
this.flash();
}
});
</script>
</body>
</html>
二十二、插槽
<!DOCTYPE html>
<html lang="zh">
<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></title>
</head>
<body>
<div id="app" v-cloak>
<com>
<!-- 插槽机制也能够帮助我们实现数据的传递,只是这种传递是停留在视图层的,并没有进入到代码层 -->
here is the best place!---{{pm}}
</com>
</div>
<template id="el">
<div>
<h1>这里是组件</h1>
{{msg}}
<slot></slot>
</div>
</template>
<script src="../day1/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
pm:'my name is pm'
},
components:{
com:{
template:"#el",
data(){
return {
msg:"这是组件数据"
};
}
}
}
});
</script>
</body>
</html>
二十三、路由
参考文献:https://router.vuejs.org/zh/
什么是路由?
- 我们认识的路由
进入到网站的根目录,然后根据文件夹的名称或者文件名去找到对应的文件,然后运行
- 后端的路由
指网络上的某一个资源URL
后端框架的出现,以及安全性的考虑,后端一般做单一的入口
例如:http://localhost/vue_api/index.php?m=api&a=getlist
单一的入口是指在这个入口文件中,通过路由参数的方式(m=api&a=getlist)将请求分发给不同的资源或者文件处理
- 前端路由
锚点实现的路由
前端的路由是不会发生页面的刷新或者页面的重启请求的
hash值的变化是不会造成页面重新请求的
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
/* mint-active */
.router-link-active{
background: #00FFFF;
color:lightseagreen;
font-size: 20px;
}
.v-enter,
.v-leave-to{
opacity: 0;
transform: translateX(200px);
}
.v-enter-active,
.v-leave-active{
transition: all 1s ease;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<!-- 使用router-link的标签实现路由的连接 -->
<router-link to="/login" tag="span">登录</router-link>
<router-link to="/register" tag="span">注册</router-link>
<!-- <router-link to="/guanggai" tag="span">逛街</router-link> -->
<!-- <a href="#/login">登录</a>
<a href="#/register">注册</a> -->
<transition mode="out-in">
<router-view></router-view>
</transition>
</div>
<script src="../lib/vue.js"></script>
<script src="../lib/vue-router.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const login = {
template:`
<div>
这是登录组件
</div>
`,
};
const register = {
template:`
<div>
这是注册组件
</div>
`,
}
new Vue({
el:"#app",
data:{
},
//不能这样使用
<!--components:{
guanggai:{
template:'<div>这是逛街</div>'
}
},-->
//路由规则
router: new VueRouter({
routes:[
//redirect重定向,将符合规则的路由发送到指定的路由
{path:'/',redirect:'/login'},
{path:'/login',component:login},
{path:'/register',component:register},
// {path:'/guanggai',component:guanggai}
],
linkActiveClass:'is_selected'
})
});
</script>
</body>
</html>
二十四、vuex
参考文献:https://vuex.vuejs.org/zh/
概念:在多个组件中共享状态(需要多个组件共享的变量全部存储在一个对象里面,然后将这个对象放在顶层的Vue实例中,让其他组件可以使用,并且是响应式)
适用情况:用户登陆状态、用户名称、头像、地理位置,商品收藏、购物车中的物品等等
image.png
网友评论