VUE.JS学习笔记
基于VUE框架开发的开源前端项目,这个是我学完后开发的开源实例项目,大家有兴趣的可以一起交流,喜欢的话别忘了star一下哦。
Vue的基本使用步骤
<body>
<div id="app">
<div>{
{msg}}div>
div>
<script type="text/javascript" src="./js/vue.js">script>
<SCript type="text/javascript">
var vm = new Vue({
el: '#app',//通过标签获得显示路径(元素挂载位置:可以是CSS选择器或者DOM元素)
data: {
//模型数据(值是一个对象)
msg: 'hello world'
}
});
SCript>
body>
把数据填充到HTML中,前端渲染方法:
模板语法概览
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HELLO WORDtitle>
<style>
[v-cloak]{
display: none;
}
style>
head>
<body>
<div id="app">
<div v-cloak>{
{msg}}div>
div>
<script type="text/javascript" src="./js/vue.js">script>
<SCript type="text/javascript">
// v-cloak指令用法:
// 1、提供样式
// [v-cloak]{
// display:none;
// }
// 2、在差值表达式所在的标签中添加V-cloak指令
// 背后原理:先通过样式隐藏内容,然后在内存中进行值的替换,替换好后再显示最终的结果
var vm = new Vue({
el: '#app', //通过标签获得显示路径
data: {
msg: 'hello world'
}
});
SCript>
body>
*相比插值表达式更加简洁
<span v-text="msg">span>
<span>{
{msg}}span>
*存在安全问题
*本网站内部数据可以使用,来自第三方的数据不可用
<div v-html="html">div>
*显示原始信息,跳过编译过程(分析编译过程)
<span v-pre>{
{ this will not be compiled }}span>
如何理解响应式
*html5中响应式(屏幕尺寸的变化导致样式的变化)
*数据的响应式(数据的变化导致页面内容的变化)
什么是数据绑定
*数据绑定:将数据填充到标签中
v-once 值编译一次
*显示内容之后不再具有响应式功能
*应用场景:如果后续显示的信息不需要再修改,可以使用V-ONCE,可以提高性能
<div v-once>
{
{info}}
div>
<script>
var vm = new Vue({
el: '#app', //通过标签获得显示路径
data: {
info:'once'
}
});
script>
你可以用 v-model
指令在表单 、
及
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。
<input v-model="message" placeholder="edit me">
<p>Message is: {
{ message }}p>
M(model):提供数据
V(view——DOM元素):提供页面展示效果
VM(View-Model):实现控制逻辑
v-on指令用法
<input type='button' v-on:click='num++'/>
v-on指令简写
<input type='button' @click='num++'/>
绑定事件处理函数:
事件绑定-参数传递
1.如果事件直接绑定函数名称,那么默认会传递事件对象作为事件函数的第一个参数
2.如果事件绑定函数调用,那么事件必须作为最后一个参数显示传递,并且事件对象的名称必须是$event
<div id='app'>
{
{num}}
div>
<input type='button' @click='handlea'/>
<input type='button' @click='handle(1,2.$event)'/>
<script>
var vm = new Vue({
el: '#app', //通过标签获得显示路径
data: {
num:0
},
methods:{
handle:function(event){
console.log(enent.target.targetName);
this.num++;
}
handle:function(p1,p2,event){
//函数中的this是VUE的实例对象
console.log(p1,p2);
console.log(event.target.innerHTML);
console.log(this===vm);
this.num++;
}
}
});
script>
事件修饰符:
.stop 阻止事件冒泡
<a @click.stop='handle'>跳转a>
.prevent阻止默认行为
<a @clidk.prevent='handle'>跳转a>
键盘按键修饰符:
.enter回车键
<input v-on:keyup.enter='submit'>
.delete删除键
<input v-on:keyup.delete='delete'>
v-bind指令用法
<a v-bind:href='url'>跳转a>
缩写模式
<a :href='url'>跳转a>
v-model的底层实现原理分析
<input v-bind:value="msg" v-on:input="msg=$event.target.value">
对象语法
<div id='app' v-bind:class="{ active: isActive,err:isErr }">div>
<script>
var vm = new Vue({
el: '#app', //通过标签获得显示路径
data: {
isActive:true,
isErr:true
},
methods:{
handle:function(){
this.isActive=!this.isActive;
this.isErr=!this.isErr
}
}
});
script>
数组语法
<div id='app' v-bind:class="[avtiveClass,errorClass]">div>
<script>
var vm = new Vue({
el: '#app', //通过标签获得显示路径
data: {
activeClass:active,
errorClass:err
},
methods:{
handle:function(){
this.activeClass='';
this.errorClassr='';
}
}
});
script>
对象绑定和数组绑定可以结合使用
class绑定的值可以简化操作
默认的class如何处理?默认样式会保留
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HELLO WORDtitle>
<style>
.active{
background-color: antiquewhite;
}
.err{
background-color: rebeccapurple;
}
.test{
color: blue;
}
style>
head>
<body>
<div id="app">
<div :class='[activeClass,errorClass,{test:isTest}]'>测试样式div>
<button @click='handle'>切换button>
div>
<script type="text/javascript" src="./js/vue.js">script>
<SCript type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
activeClass:'active',
errorClass:'err',
isTest:true
},
methods: {
handle : function(){
this.activeClass='';
this.errorClass='';
this.isTest=!this.isTest;
}
},
});
SCript>
body>
对象处理语法
<div id='app' v-bind:style="{
color:activeColor,fintSize:fintSize}">
<button @click='handle'> 切换 button>
div>
<script>
var vm = new Vue({
el: '#app', //通过标签获得显示路径
data: {
activeColor:'blue',
fintSize:'1px'
},
methods: {
handle : function(){
this.activeColor='yellow';
this.fintSize='2px';
}
},
});
script>
数组语法
<div v-bind:style="[baseStyles,overridingStylrs]">div>
<body>
<div id="app">
<div v-if='score>=90'>优秀div>
<div v-else-if='score<90 && score>=80'>优良div>
<div v-else-if="score<80 && score>60">及格div>
<div v-else>不及格div>
<div v-show='flag'>v-show测试div>
<button @click='handle'>切换button>
div>
<script type="text/javascript" src="./js/vue.js">script>
<SCript type="text/javascript">
//v-show原理:控制元素样式是否显示 ==dispaly:none/block
var vm = new Vue({
el: '#app',
data: {
score:55,
flag:false
},
methods: {
handle:function(){
this.flag=!this.flag;
}
},
});
SCript>
body>
<li v-for='item in list'>{
{item}}li>
<li v-for='(item,index) in list'>{
{item}}+'------'{
{index}}li>
<li :key='item.id' v-for='(item,index) in list'>{
{item}}+'----'{
{index}}li>
example
<body>
<div id="app">
<div>水果列表div>
<ul>
<li v-for='item in fruits'>{
{item}}li>
<li v-for='(item,index) in fruits'>{
{item}}+'---'+{
{index}}li>
<li :key='index' v-for='(item,index) in myfruits'>
<span>{
{item.cname}}span>
<span>'------'span>
<span>{
{item.ename}}span>
li>
ul>
div>
<script type="text/javascript" src="./js/vue.js">script>
<SCript type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
fruits:['app','orange','banana'],
myfruits:[
{
cname:'苹果',
ename:'apple'
},
{
cname:'香蕉',
ename:'banana'
},
{
cname:'橘子',
ename:'orange'
},
]
},
methods: {
handle:function(){
}
},
});
SCript>
body>
<div v-for='(value,key,index) in object'>{
{value+key+index}}div>
<li v-if="v=='lisi'" v-for='(value,key,index) in obj'>{
{index+'--'+key+'--'+value}}li>
example
<body>
<div id="app">
<ul>
<li v-for='(v,k,i) in obj'>{
{i+'--'+k+'--'+v}}li>
<li v-if="v=='lisi'" v-for='(v,k,i) in obj'>{
{i+'--'+k+'--'+v}}li>
ul>
div>
<script type="text/javascript" src="./js/vue.js">script>
<SCript type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
obj:{
uname:'lisi',
age:12,
gender:'male'
}
},
methods: {
}
});
SCript>
body>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style type="text/css">
.tab ul {
overflow: hidden;
padding: 0;
margin: 0;
}
.tab ul li {
box-sizing: border-box;
padding: 0;
float: left;
width: 100px;
height: 45px;
list-style: none;
text-align: center;
border-top: 1px solid blue;
border-right: 1px solid blue;
cursor: pointer;
}
.tab ul li:first-child {
border-left: 1px solid blue;
}
.tab ul li.active {
background-color: orange;
}
.tab div {
width: 500px;
height: 300px;
display: none;
text-align: center;
font-size: 30px;
line-height: 300px;
border: 1px solid blue;
border-top: 0px;
}
.tab img {
width: 500px;
height: 300px;
}
.tab div.current {
display: block;
}
style>
head>
<body>
<div id='app'>
<div class="tab">
<ul>
<li ::key="item.id" @click='handle(index)' :class='currentIndex==index?"active" : ""'
v-for='(item,index) in obj'>{
{item.name}}li>
ul>
<div :key="item.id" :class='currentIndex==index?"current" : ""' v-for='(item,index) in obj'>
<img :src="item.path">
div>
div>
div>
<script type="text/javascript" src="./js/vue.js">script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
currentIndex: 0,//当前索引,默认为0
obj: [{
id: 1,
name: '海',
path: './img/海.jpg'
},
{
id: 2,
name: '洋',
path: './img/洋.jpg'
},
{
id: 1,
name: '猫',
path: './img/猫.jpg'
}
]
},
methods: {
handle: function (index) {
this.currentIndex = index;
}
}
})
script>
body>
html>
<body>
<form action="">
<div id='app'>
<div>
<span>姓名:span>
<span>
<input type="text" v-model='uname'>
span>
div>
<div>
<span>性别:span>
<span>
<input type="radio" id='male' value="1" v-model='gender'>
<label for="male">男label>
<input type="radio" id='female' value="2" v-model='gender'>
<label for="female">女label>
span>
div>
<div>
<span>爱好:span>
<span>
<input type="checkbox" id='ball' value='0' v-model='hobby'>
<label for="ball">篮球label>
<input type="checkbox" id='sing' value="1" v-model='hobby'>
<label for="sing">唱歌label>
<input type="checkbox" id='dance' value="2" v-model='hobby'>
<label for="dance">跳舞label>
span>
div>
<div>
<span>职业:span>
<select v-model='ocupation'>
<option value="0">请选择职业option>
<option value="1">程序员option>
<option value="2">会计option>
select>
div>
<div>
<span>个人简介:span>
<span>
<textarea v-model='msg'>textarea>
span>
div>
<div>
<input type="submit" @click.prevent='handle' value="提交">
div>
div>
form>
<script type="text/javascript" src="./js/vue.js">script>
<script type="text/javascript">
var vm=new Vue({
el:'#app',
data:{
uname:'',
gender:1,
hobby:[],
ocupation:0,
msg:''
},
methods: {
handle:function(){
console.log(this.uname);
console.log(this.gender);
console.log(this.hobby.toString());
console.log(this.ocupation);
console.log(this.msg);
}
},
})
script>
body>
<input v-model.number='age' type='number'>
<input v-model.lazy='msg' type='text'>
<input v-model.trim='msg' type='text'>
自定义指令使用手册链接
Vue.directive('focus',{
inserted:function(el){
//获取元素焦点;
el.focus();
}
})
<input type='text' v-focus>
//全局指令
Vue.directive('color',{
inserted:function(el,binding){
el.style.backgroundColor=binding.value.color;
}
})
//如果想注册局部指令,组件中也接受一个 directives 的选项:
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
然后你可以在模板中任何元素上使用新的 v-focus
property,如下:
<input v-focus>
computed:{
//计算属性
reversedMessage:function(){
//计算名
return this.msg.split(' ').reverse().jion('');//计算方法体
}
}
用于侦听数据变化,当数据变化时,会触发侦听器的方法。
数据变化时执行异步或开销较大的操作
<body>
<div id='app'>
<div>
<span>姓:span>
<span>
<input type="text" v-model='FirstName'>
span>
div>
<div>
<span>名:span>
<span>
<input type="text" v-model='lastName'>
span>
div>
<div>
{
{fullName}}
div>
div>
<script type="text/javascript" src="./js/vue.js">script>
<script type="text/javascript">
Vue.directive('focus',{
inserted:function(el){
el.focus();
}
});
var vm=new Vue({
el:'#app',
data:{
FirstName:'tom',
lastName:'kaite',
fullName:'tom kaite'
},
watch: {
FirstName:function(val){
this.fullName=val+' '+this.lastName;
},
lastName:function(val){
this.fullName=this.FirstName+' '+val;
}
},
})
script>
body>
格式化数据,比如将字符串格式化为首字母大写,将日期格式化为指定格式等;
//自定义过滤器(全局)
Vue.filter('过滤器名称',function(value){
//过滤器业务逻辑
})
//自定义过滤器(局部)
filter:{
upper:function(val){
//过滤器业务逻辑
}
}
<div>
{
{msg | upper}}
div>
<div>
{
{msg | upper |lower}}
div>
<div v-bind:id="id | formatId">
div>
<body>
<div id="app" >
<div>{
{current|format('yyyy-MM-dd hh:mm:ss')}}div>
div>
<script text="text/javascript" src="./js/vue.js">script>
<script text="text/javascript">
Vue.filter('format', function (value, arg) {
function dateFormat(date, str) {
if (typeof date === "string") {
var mts = date.match(/(\/Date\((\d+)\/)/);
if (mts && mts.length >= 3) {
date = parseInt(mts[2]);
}
}
date = new Date(date);
if (!date || date.toUTCString() == "Invalid Date") {
return "";
}
var map = {
"M": date.getMonth() + 1,
"d": date.getDate(),
"h": date.getHours(),
"m": date.getMinutes(),
"s": date.getSeconds(),
"q": Math.floor((date.getMonth() + 3) / 3),
"S": date.getMilliseconds()
}
str = str.replace(/([yMdhmsqS])+/g, function (all, t) {
var v = map[t];
if (v !== undefined) {
if (all.length > 1) {
v = '0' + v;
v = v.substr(v.length - 2);
}
return v;
} else if (t === 'y') {
return (date.getFullYear() + '').substr(4 - all.length);
}
return all;
});
return str;
};
return dateFormat(value,arg);
});
var vm=new Vue({
el:'#app',
data:{
current:new Date()
}
})
script>
body>
挂载(初始化相关属性)
beforeCreate
created
beforeMount
mounted
更新(元素或组件的变更操作)
beforeUpdate
updated
销毁(销毁相关属性)
befpreDestroy
destpryed
数组更新检测使用手册链接
Vue.set(vm.items,indexOfltem,newValue)
vm.$set(vm.items,indexOfltem,newValue)
1.参数一表示要处理的数组名称
2.参数二表示要处理的数组的索引
3.参数三表示要处理的数组的值
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style type="text/css">
.grid {
margin: auto;
width: 800px;
text-align: center;
}
.grid table {
border-top: 1px solid #c2d89a;
width: 100%;
border-collapse: collapse;
}
.grid th td {
padding: 10;
border: 1px dashed orange;
height: 35px;
line-height: 35px;
}
.grid th {
background-color: orange;
}
.grid .book {
padding-bottom: 10px;
padding-top: 5px;
background-color: #f3dcab;
}
.grid .total {
height: 30px;
line-height: 30px;
background-color: #f3dcab;
border-top: 1px solid #c2d89a;
}
style>
head>
<body>
<div id="app">
<div class="grid">
<table>
<thead>
<tr>
<th>编号th>
<th>名称th>
<th>时间th>
<th>操作th>
tr>
thead>
<tbody>
<div class="book">
<label for='tid'>编号:label>
<input type="text" id="tid" v-model='tid' :disabled='flag' v-focus>
<label for="tname">名称:label>
<input type="text" id="tname" v-model='tname'>
<button @click='handlesubmit' :disabled='submitflag'>提交button>
div>
<div class="total">
<span>图书总数:{
{total}}span>
div>
<tr :key='item.id' v-for='item in books'>
<td>{
{item.id}}td>
<td>{
{item.name}}td>
<td>{
{item.date|format('yyyy-MM-dd hh:mm:ss')}}td>
<td>
<a href="" @click.prevent='update(item.id)'>修改a>
<span>|span>
<a href="" @click.prevent='deletedata(item.id)'>删除a>
td>
tr>
tbody>
table>
div>
div>
<script type="text/javascript" src="./js/vue.js">script>
<script type="text/javascript">
Vue.directive('focus', {
inserted: function (el) {
//获取元素焦点;
el.focus();
}
})
Vue.filter('format', function (value, arg) {
function dateFormat(date, str) {
if (typeof date === "string") {
var mts = date.match(/(\/Date\((\d+)\/)/);
if (mts && mts.length >= 3) {
date = parseInt(mts[2]);
}
}
date = new Date(date);
if (!date || date.toUTCString() == "Invalid Date") {
return "";
}
var map = {
"M": date.getMonth() + 1,
"d": date.getDate(),
"h": date.getHours(),
"m": date.getMinutes(),
"s": date.getSeconds(),
"q": Math.floor((date.getMonth() + 3) / 3),
"S": date.getMilliseconds()
}
str = str.replace(/([yMdhmsqS])+/g, function (all, t) {
var v = map[t];
if (v !== undefined) {
if (all.length > 1) {
v = '0' + v;
v = v.substr(v.length - 2);
}
return v;
} else if (t === 'y') {
return (date.getFullYear() + '').substr(4 - all.length);
}
return all;
});
return str;
};
return dateFormat(value, arg);
});
var vm = new Vue({
el: '#app',
data: {
tid: '',
tname: '',
flag: false,
submitflag: false,
books: []
},
methods: {
handlesubmit: function () {
//修改数据
if (this.flag) {
this.books.some((item) => {
if (item.id == this.tid) {
item.name = this.tname;
return true;
}
});
this.tid = '';
this.tname = '';
this.flag = false;
} else {
//添加数据
var book = {
};
book.id = this.tid;
book.name = this.tname;
book.date = new Date();
this.books.push(book);
this.submitflag = false;
this.tid = '';
this.tname = '';
}
},
update: function (id) {
//根据ID找到相关数据,filter过滤函数,找到就返回符合条件的数据
var book = this.books.filter(function (item) {
return item.id == id;
});
this.tid = book[0].id;
this.tname = book[0].name;
this.flag = true;
},
deletedata: function (id) {
// //根据ID查找数据索引
// var index=this.books.findIndex(function(item){
// return item.id==id;
// });
// //根据索引删除数据
// this.books.splice(index,1);
//方法二
this.books = this.books.filter(function (item) {
return item.id != id;
})
}
},
watch: {
tname: function (val) {
//验证书名是否存在,返回true/false
this.submitflag = this.books.some(function (item) {
return item.name == val;
})
},
tid: function (val) {
this.submitflag = this.books.some(function (item) {
return item.id == val;
})
}
},
computed: {
total: function () {
return this.books.length;
}
},
mounted: function () {
//该生命周期钩子函数被触发的时候,模板已经可以使用
//一般此时用于获取后台数据,然后把数据填充到模板
var data = [{
id: 1,
name: '红楼梦',
date: new Date()
},
{
id: 2,
name: '水浒传',
date: new Date()
},
{
id: 3,
name: '西游记',
date: new Date()
}
];
this.books = data;
},
})
script>
body>
html>
Vue.component(组件名称,{
data:组件数据,
template:组件模板内容
})
<div id="app">
<组件名称>组件名称>
div>
<body>
<div id="app">
<button-counter>button-counter>
<button-counter>button-counter>
<button-counter>button-counter>
div>
<script src="./js/vue.js">script>
<script>
// 组件注册
Vue.component('button-counter',{
data:function(){
return{
count:0
}
},
template:'',
methods:{
handle:function(){
this.count++;
}
}
})
var vm=new Vue({
el:'#app',
data:{
},
methods: {
},
})
script>
body>
短横线方式(适用于组件和标签模板中)
Vue.component('my-component',{
**********})
驼峰方式(适用于组件中,若要在标签模板中使用需将标签名改为)
Vue.component('MyComponent',{
**********})
var HelloTom={
/******/}
var vm=new Vue({
el:'#app',
components:{
'hello-tom':HelloTom
}
})
<body>
<div id="app">
<hello-world>hello-world>
<hello-tom>hello-tom>
div>
<script src="./js/vue.js">script>
<script>
// 局部组件注册,只能在父组件中使用
var HelloWorld={
data:function(){
return {
msg:'helloword'
}
},
template:'{
{msg}}'
};
var HelloTom={
data:function(){
return {
msg:'hellotom'
}
},
template: '{
{msg}}'
}
var vm=new Vue({
el:'#app',
data:{
},
components:{
'hello-world':HelloWorld,
'hello-tom':HelloTom
}
})
script>
body>
下载vue调试工具,在浏览器中加入此扩展程序。
Vue.component('menu-item',{
props:['title'],
template:`{
{title}}`
})
<menu-item title="来自父组件的数据">menu-item>
<menu-item :title="title">menu-item>
Vue.component('menu-item',{
//在javasvript中是驼峰式的
props:['menuTitle'],
template:'{
{menuTitle}}'
})
<!-- 在html中是短横线中没有这个限制 -->
<menu-item menu-title="nihao"></menu-item>
<body>
<div id="app">
<div>{
{pmsg}}div>
<menu-item title="来自父组件">menu-item>
<menu-item :title="ptitle">menu-item>
div>
<script src="./js/vue.js">script>
<script type="text/javascript">
Vue.component('menu-item',{
props:['title'],
data:function(){
return {
msg:'子组件本身的数据'
}
},
template:'{
{msg+"---"+title}}'
})
var vm=new Vue({
el:'#app',
data:{
pmsg:'父组件',
ptitle:'父组件动态绑定'
}
})
script>
body>
props传递数据原则:单向数据流,只允许父组件向子组件传递数据而不允许子组件向父组件传递数据
<button @click='$emit("enlarge-text")'>扩大字体button>
<menu-item @enlarge-text='fontSize+=0.1'>menu-item>
<button @click='$emit("enlarge-text",0.1)'>扩大字体button>
<menu-item @enlarge-text='fontSize+=$event'>menu-item>
<body>
<div id="app">
<div >{
{pmsg}}div>
<menu-item title="来自父组件" @large-text='handle($event)' :style='{
fontSize:fontsize+"px"}'>menu-item>
div>
<script src="./js/vue.js">script>
<script type="text/javascript">
Vue.component('menu-item', {
props: ['title'],
data: function () {
return {
msg: '子组件本身的数据'
}
},
template: `
{
{title+"-----"+msg}}
`
})
var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件',
ptitle: '父组件动态绑定',
fontsize: 5
},
methods: {
handle: function (val) {
this.fontsize += val;
}
},
})
script>
body>
var eventHub=new Vue()
eventHub.$on('add-todo',addTodo)//监听事件,第一个是事件名称,第二个是事件函数
eventHub.$off('add-todo')//销毁事件
eventHub.$emit('add-todo',id)//第一个是事件名称,第二个是携带参数
<body>
<div id="app">
<div>父组件div>
<div>
<button @click='handle'>销毁事件button>
div>
<bother-tom>bother-tom>
<bother-han>bother-han>
div>
<script type="text/javascript" src="./js/vue.js">script>
<script type="text/javascript">
//事件中心
var hub = new Vue();
Vue.component('bother-tom', {
data: function () {
return {
num: 0
}
},
template: `
tom:{
{num}}
`,
methods: {
handle: function () {
hub.$emit('han-event', 1);
}
},
mounted: function () {
hub.$on('tom-event', (val) => {
this.num += val;
})
}
})
Vue.component('bother-han', {
data: function () {
return {
num: 0
}
},
template: `
han:{
{num}}
`,
methods: {
handle: function () {
hub.$emit('tom-event', 2);
}
},
mounted: function () {
hub.$on('han-event', (val) => {
this.num += val;
})
}
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
handle: function () {
hub.$off('han-event');
hub.$off('tom-event');
}
},
})
script>
body>
插槽的标签
父组件向子组件传递内容
1、插槽位置
Vue.component('alert-box',{
template:`
error:
`
})
2、插槽内容(即父组件标签里的内容)
<alert-box>some things happenedalert-box>
<body>
<div id="app">
<alert-tab>warningalert-tab>
<alert-tab>bugalert-tab>
div>
<script type="text/javascript" src="./js/vue.js">script>
<script type="text/javascript">
Vue.component('alert-tab', {
data: function () {
return {
}
},
template: `
error:
`
})
var vm=new Vue({
el:'#app'
})
script>
body>
<div class="cintainer">
<header>
<slot name="header">slot>
header>
<main>
<slot>slot>
main>
<footer>
<slot name="footer">slot>
footer>
div>
<base-layout>
<h1 slot="header">
标题内容
h1>
<p>
主要内容
p>
<p slot="footer">
底部内容
p>
base-layout>
<body>
<div id="app">
<best-lay>
<template slot="header">
<p>hanp>
<p>xinp>
template>
<template>
<p>lalalap>
template>
<template slot="footer">
<p>hanp>
<p>xinp>
template>
best-lay>
div>
<script type="text/javascript" src="./js/vue.js">script>
<script type="text/javascript">
Vue.component('best-lay', {
template: `
`
})
var vm=new Vue({
el:'#app',
data:{
},
})
script>
body>
<ul>
<li v-for='item in list' v-bind:key='item.id'>
<slot v-bind:item="item">
{
{item.name}}
slot>
li>
ul>
<fruit-list :list='list'>
<template slot-scope='slotProps'>
<strong v-if='slotProps.item.current'>
{
{slotProps.item.text}}
strong>
template>
fruit-list>
<body>
<div id="app">
<fruit-list :list='list'>
<template slot-scope="slotProps">
<strong v-if="slotProps.info.id==2" >{
{slotProps.info.name}}strong>
<span v-else>{
{slotProps.info.name}}span>
template>
fruit-list>
div>
<script type="text/javascript" src="./js/vue.js">script>
<script type="text/javascript">
Vue.component('fruit-list',{
props:['list'],
template:`
{
{item.name}}
`
});
var vm=new Vue({
el:'#app',
data:{
list:[
{
id:1,
name:'apple'
},{
id:2,
name:'orange'
},{
id:3,
name:'banana'
}
]
}
})
script>
body>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
.cart {
position: absolute;
right: 700px;
width: 500px;
height: 0px;
background: white;
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.5);
transition: 1s;
}
.cart .title {
width: 500px;
height: 30px;
border: 1px solid gray;
background-color: rgb(241, 172, 42);
/*flex 布局*/
display: flex;
/*实现垂直居中*/
align-items: center;
/*实现水平居中*/
justify-content: center;
color: white;
}
.cart .total {
width: 500px;
height: 30px;
border: 1px solid gray;
background-color: rgb(241, 172, 42);
border: solid 1px gray;
color: white;
}
.cart .total button {
width: 40px;
height: 100%;
background-color: rgb(226, 223, 223);
display: flex;
padding: 0px;
margin: 0px auto;
border: 1px solid gray;
float: right;
}
.cart .total span {
width: 100px;
height: 100%;
color: white;
padding: 0px;
margin: 0px;
border: 0px;
position: relative;
left: 350px;
/* display: flex;
align-items: center;
justify-content: right; */
}
.item {
margin: 0px auto;
width: 100%;
height: 50px;
border: 1px solid gray;
/* margin:10px 5px 15px 20px; */
display: flex;
/*实现垂直居中*/
align-items: center;
/*实现水平居中*/
justify-content: center;
}
.item img {
width: 50px;
height: 50px;
float: left;
position: relative;
margin-right: 10px;
margin-left: 10px;
}
.item .name {
width: 25%;
height: 50px;
float: left;
position: relative;
/*flex 布局*/
display: flex;
/*实现垂直居中*/
align-items: center;
/*实现水平居中*/
justify-content: center;
border-bottom: 1px solid gray;
border-left: 1px solid gray;
border-right: 1px solid gray;
}
.item .change {
display: table;
width: 25%;
height: 50px;
float: left;
position: relative;
/* left: 50px; */
/*flex 布局*/
display: flex;
/*实现垂直居中*/
align-items: center;
/*实现水平居中*/
justify-content: center;
border-bottom: 1px solid gray;
border-right: 1px solid gray;
}
.item .change a {
width: 20px;
height: 20px;
background-color: rgb(179, 177, 177);
display: table-cell;
vertical-align: middle;
font-size: 30px;
text-decoration: none;
/* padding: 10px; */
/*flex 布局*/
display: flex;
/*实现垂直居中*/
align-items: center;
/*实现水平居中*/
justify-content: center;
}
.item .change a:active {
color: red;
}
.item .change input {
display: table-cell;
vertical-align: middle;
width: 30px;
}
.item .del {
width: 50px;
height: 30px;
float: left;
position: relative;
/* left: 50px; */
margin: 0px auto;
text-align: center;
/*flex 布局*/
display: flex;
/*实现垂直居中*/
align-items: center;
/*实现水平居中*/
justify-content: center;
color: white;
background-color: palevioletred;
cursor: pointer;
}
.item .active {
background-color: red;
}
style>
head>
<body>
<div id="app">
<div class="container">
<my-cart>my-cart>
div>
div>
<script type="text/javascript" src="./js/vue.js">script>
<script type="text/javascript">
var cartTitle = {
props: ['uname'],
data: function () {
return {
}
},
template: `
{
{uname}}的商品
`
}
var cartList = {
props: ['list'],
data: function () {
return {
}
},
template: `
`,
methods: {
handledel: function (id) {
//将ID传给父组件
this.$emit('cart-del', id);
},
decress: function (id) {
this.$emit('change-num', {
id: id,
type: 'dec'
});
},
plus: function (id) {
this.$emit('change-num', {
id: id,
type: 'plus'
});
},
changNum: function (id, event) {
this.$emit('change-num', {
id: id,
type: 'change',
num: event.target.value
})
},
mouseOver: function (event) {
event.currentTarget.className = 'del active';
},
mouseLeave: function (event) {
event.currentTarget.className = 'del';
}
}
}
var cartTotal = {
props: ['list'],
data: function () {
return {
}
},
template: `
总价:{
{total}}
`,
computed: {
total: function () {
var t = 0;
this.list.forEach(item => {
t += item.price * item.num;
})
return t;
},
},
}
Vue.component('my-cart', {
props: [],
data: function () {
return {
uname: '韩鑫',
list: [{
id: 1,
name: '冰箱',
price: 100,
num: 1,
img: './img/海.jpg'
}, {
id: 2,
name: '空调',
price: 300,
num: 1,
img: './img/海.jpg'
}, {
id: 3,
name: '电视',
price: 500,
num: 1,
img: './img/海.jpg'
}]
}
},
template: `
`,
components: {
'cart-title': cartTitle,
'cart-list': cartList,
'cart-total': cartTotal
},
methods: {
delcart: function (id) {
//根据Id删除list中的数据
//找到id对应的数据索引
var index = this.list.findIndex(item => {
return item.id == id;
});
//根据索引删除对应数据
this.list.splice(index, 1);
},
changNum: function (obj) {
if (obj.type == 'change') {
this.list.forEach(item => {
if (item.id == obj.id) {
item.num = obj.num;
return true;
}
})
} else if (obj.type == 'dec') {
// console.log(obj.type);
this.list.some(item => {
if (item.id == obj.id && item.num > 0) {
item.num--;
return true;
}
});
} else if (obj.type == 'plus') {
this.list.some(item => {
if (item.id == obj.id) {
item.num++;
return true;
}
});
}
}
}
})
var vm = new Vue({
el: '#app',
data: {
},
methods: {
},
})
script>
body>
html>
promise是异步编程的一种解决方案,从语法上讲,Promise是一个对象,从它可以获取异步操作的消息。
只用Promise主要有以下好处:
var p=new Promise(function(resolve,reject){
//成功时调用
resolve();
//失败时调用
reject();
});
p.then(function(ret){
//从resolve得到的正常结果
},function(ret){
//从reject得到的错误信息
})
function queryData(){
return new Promise(function(resolve,reject){
var xhr=new XMLHttoRequest();
xhr.onreadystatechange=function(){
if(xhr.readyState !=4) return;
if(xhr.status==200){
resolve(xhr.responseText)
}else{
reject('出错了');
}
}
xhr.open('get','/data');
xhr.send(null);
})
}
queryData()
.then(function(data){
//处理函数
......
return queryData();
})
.then(function(data){
//处理函数
......
return queryData();
})
.then(function(data){
//处理函数
......
return queryData();
});
Promise.all(p1,p2,p3).then((result)=>{
console.log(result);//返回的result是一个包含所有结果值的数组
})
Promise.race([p1,p2,p3]).then((result)=>{
console.log(result);//返回 的result是最快完成的任务的结果
})
fetch(url).then(fn2)
.then(fn3)
...
.then(fn)
fetch('/abc').then(data=>{
//text()方法属于fetch的一部分,返回一个Promise对象,用于获取后台返回的数据
return data.text();//.text()是固定用法
}).then(ret=>{
//注意这里得到的才是最终的数据
console.log(ret);
})
fetch('/abc',{
method:'get'
}).then(data=>{
return data.text();
}).then(ret=>{
//注意这里得到的才是最终的数据
console.log(ret);
})
fetch('/abc?id=123').then(data=>{
return data.text();
}).then(ret=>{
//注意这里得到的才是最终的数据
console.log(ret);
})
fetch('abc/123',{
method:'get'
}).then(data=>{
return data.text();
}).then(ret=>{
//注意这里得到的才是最终的数据
console.log(ret);
})
fetch('/abc/123',{
method:'delete'
}).then(data=>{
return data.text();
}).then(ret=>{
//注意这里得到的才是最终的数据
console.log(ret);
})
fetch('/books',{
method:'post',
body:'uname=lise&pwd=123',
headers:{
'Content-Type':'application/x-www-form-urlencoded'
}
}).then(data=>{
return data.text();
}).then(ret=>{
console.log(ret);
})
//===========================================================
fetch('/books',{
method:'post',
body:json.stringify({
uname:'lisi',
pwd:'123'
}),
headers:{
'Content-Type':'application/json'
}
}).then(data=>{
return data.text();
}).then(ret=>{
console.log(ret);
})
fetch('/books',{
method:'put',
body:json.stringify({
uname:'lisi',
pwd:'123'
}),
headers:{
'Content-Type':'application/json'
}
}).then(data=>{
return data.text();
}).then(ret=>{
console.log(ret);
})
//=========================================
fetch('/books',{
method:'post',
body:'uname=lise&pwd=123',
headers:{
'Content-Type':'application/x-www-form-urlencoded'
}
}).then(data=>{
return data.text();
}).then(ret=>{
console.log(ret);
})
fetch('/abc'). then(data=>{
return data.text()
}).then(ret=>{
console.log(ret);
})
//==========================
fetch('/abc'). then(data=>{
return data.json()
}).then(ret=>{
console.log(ret);
})
axios是一个基于Promise用于浏览器和node.js的HTTP客户端。
它具有以下特征:
axios.get('/adata')
.then(ret=>{
//data属性名称是固定的,用于获取后台响应的数据
console.log(ret.data)
})
//通过URL传递参数
axios.get('/adata?id=123')
.then(ret=>{
console.log(ret.data);
})
//==============================
axios.get('/adata/123')
.then(ret=>{
console.log(ret.data);
})
//通过params选项传递参数
axios.get('/adata',{
params:{
id:123
}
})
.then(ret=>{
console.log(ret.data);
})
axios.delete('/adata?id=123')
.then(ret=>{
console.log(ret.data);
})
//================================
axios.delete('/adata/123')
.then(ret=>{
console.log(ret.data);
})
//==================================
axios.delete('/adata',{
params:{
id:123
}
})
.then(ret=>{
console.log(ret.data);
})
axios.post('/adara',{
uname:'tom',
pwd:123
}).then(ret=>{
console.log(ret.data)
})
const params=new URLSearchParams();
params.apend('param1','value1');
params.apend('param2','value2');
axios.post('/api/test',params).then(ret=>{
console.log(ret.data);
})
axios.put('/adara',{
uname:'tom',
pwd:123
}).then(ret=>{
console.log(ret.data)
})
//========================
const params=new URLSearchParams();
params.apend('param1','value1');
params.apend('param2','value2');
axios.put('/api/test',params).then(ret=>{
console.log(ret.data);
})
axios.post('/axios-json').then(ret=>{
console.log(ret);//返回的ret是一个对象,ret.data是实际响应回来的数据
})
在请求发出之前设置一些信息
//添加一个请求拦截器
axios.interceptors.request.use(function(config){
//在请求发出之前进行一些信息设置
console.log(config.url);
config.headers.mytoken='nihao';
return config;
},function(err){
//处理响应的错误信息
console.log(err);
});
在获取数据之前对数据做一些加工处理
//添加一个响应拦截器
axios.interceptors.response.use(function(res){
//在响应之前对数据进行一些处理
console.log(res.data);
return res;
},function(err){
//处理响应的错误信息
console.log(err);
});
async/await是es7引入的新语法,可以更加方便的进行异步操作
async关键字用在函数上(async函数的返回值是Promise实例对象)
await关键字用于async函数当中(await可以得到异步的结果)
async function queryData(id){
const ret = await axios.get('/data');
return ret;
}
queryData.then(ret=>{
console.log(ret);
})
多个异步请求的场景
async function queryData(id){
const info=await axios.get('/async1');
const ret=await axios.get('async2?info='+info.data);
return ret;
}
queryData.then(ret=>{
console.log(ret);
})
#### 4.3.3 POST传递参数
* 通过选项传递参数==(默认传递的是JSON格式的数据)==
```javascript
axios.post('/adara',{
uname:'tom',
pwd:123
}).then(ret=>{
console.log(ret.data)
})
const params=new URLSearchParams();
params.apend('param1','value1');
params.apend('param2','value2');
axios.post('/api/test',params).then(ret=>{
console.log(ret.data);
})
axios.put('/adara',{
uname:'tom',
pwd:123
}).then(ret=>{
console.log(ret.data)
})
//========================
const params=new URLSearchParams();
params.apend('param1','value1');
params.apend('param2','value2');
axios.put('/api/test',params).then(ret=>{
console.log(ret.data);
})
axios.post('/axios-json').then(ret=>{
console.log(ret);//返回的ret是一个对象,ret.data是实际响应回来的数据
})
在请求发出之前设置一些信息
//添加一个请求拦截器
axios.interceptors.request.use(function(config){
//在请求发出之前进行一些信息设置
console.log(config.url);
config.headers.mytoken='nihao';
return config;
},function(err){
//处理响应的错误信息
console.log(err);
});
在获取数据之前对数据做一些加工处理
//添加一个响应拦截器
axios.interceptors.response.use(function(res){
//在响应之前对数据进行一些处理
console.log(res.data);
return res;
},function(err){
//处理响应的错误信息
console.log(err);
});
async/await是es7引入的新语法,可以更加方便的进行异步操作
async关键字用在函数上(async函数的返回值是Promise实例对象)
await关键字用于async函数当中(await可以得到异步的结果)
async function queryData(id){
const ret = await axios.get('/data');
return ret;
}
queryData.then(ret=>{
console.log(ret);
})
多个异步请求的场景
async function queryData(id){
const info=await axios.get('/async1');
const ret=await axios.get('async2?info='+info.data);
return ret;
}
queryData.then(ret=>{
console.log(ret);
})