当创建新的vue项目时,遇到无法加载文件 E:\node\node_global\vue.ps1,因为在此系统上禁止运行脚本的错误,以下为解决办法。

vue中文文档
菜鸟教程:Vue.js
该笔记只是我看视频和参考以上资料的vue学习基础笔记,还没有包含vue脚手架的学习(重点),所以想快速上手项目的话还是随便看看这个再重点看vue cli的学习吧。
一、Vue框架的简介
1、从MVC模型到MVVM模型
前端MVC、MVVM的简单实现(转载)

MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。(一种设计模式,前后端都有)

M->model->模型->数据
V->View->视图->用户所见界面
C->Control->控制器->事件交互->如何根据视图与用户交互后改变数据(比如表单提交和点击监听)

MVVM模型如图下所示。

2、Vue的特点
在Vue中一个核心的概念就是:数据驱动,避免手动操作DOM元素。这样的话,可以让前端程序员可以更多的时间关注数据业务逻辑,而不是关注DOM如何渲染了。(能够帮助我们减少不必要的DOM操作(虚拟DOM);提高渲染效率;双向数据绑定)

双向数据绑定:指的是vue实例中的data与其渲染的DOM元素的内容保持一致,无论谁被改变,另一方会相应的更新为相同的数据。这是通过设置属性访问器实现的。如下图所示,可以直接在console中改变数据。

双向绑定原理(转载)
Vue数据绑定以及双向绑定原理分析(转载)
浅谈Vue的单向绑定和双向绑定(转载)

什么是虚拟DOM:在js的内存里构建类似于DOM的对象,去拼装数据,拼装完整后,把数据整体解析,一次性插入html里去,这就形成了虚拟DOM。

一个简单的vue例子:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body><!--VIEW--><div id="app">{{title}}<h1>{{msg}}</h1></div><script type="text/javascript">console.log(Vue)//实例化VUE对象let app=new Vue({el:'#app',//el是元素的意思//Modeldata:{title:'hello Vue!',msg:'前端VUE'}})</script>
</body>
</html>

二、Vue基本操作
vue中template的作用及使用(转载)
1、条件渲染
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。

v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script><style type="text/css">#pane {width:200px;height: 200px;background-color: aquamarine;}</style>
</head>
<body><!--条件渲染--><!--VIEW--><div id="app"><h1>用户名:{{username}}</h1><h3 v-if="isVIP">用户类型:VIP</h3><!--注意v-if和v-else中间不能有其他元素--><h3 v-else>用户类型:普通用户</h3><hr><h1>用户允许登录时间</h1><h3 v-if="age>18">允许24小时登录</h3><h3 v-else-if="age>14">允许登录8小时</h3><h3 v-else>允许登录4小时</h3><hr><div v-show="isShow" id="pane">HelloVue</div><button @click="showBtn">切换显示内容</button></div><script type="text/javascript">let app=new Vue({el:"#app",data:{username:"小明",isVIP:true,age:24,isShow:true},methods:{showBtn:function(e){//触发事件econsole.log(e);app.isShow=!app.isShow;}}})/*v-if:不显示时,第一次直接不渲染,如果内容已经显示将其内容改为不显示,内容直接从DOM去除。只是渲染一次内容用v-if.v-show:不显示时,就会改为display:none,但是会渲染在DOM上。反复需要切换内容,使用v-show。*/</script>
</body>
</html>

  • 一个小例子(点击按钮切换标题):

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body><!--tab切换--><!--VIEW--><div id="app"><h3 v-if="tab==1">首页</h3><h3 v-else-if="tab==2">新闻页</h3><h3 v-else>个人中心</h3><!--<h3 v-show="tab==1">首页</h3><h3 v-show="tab==2">新闻页</h3><h3 v-show="tab==3">个人中心</h3>--><button @click="tabChange" data-id="1">首页</button><button @click="tabChange" data-id="2">新闻</button><button @click="tabChange" data-id="3"> 个人中心</button></div><script type="text/javascript">let app=new Vue({el:"#app",data:{tab:1},methods:{tabChange:function(e){//console.log(e);let tabid=e.target.dataset.id;//console.log(this);//app.tab=tabid跟this.tab=tabid等同this.tab=tabid;}}})</script>
</body>
</html>

2、列表渲染
我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。

key的作用:Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。加上key属性后表示“这两个元素是完全独立的,不要复用它们”,从而会重新渲染。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body><div id="app"><h3>明星列表</h3><ul><li v-for="item in stars">{{item}}</li></ul><h3>学生列表</h3><ul><li v-for="item in student"><h4>{{item.studentName}}</h4><p>年龄:{{item.age}}--------学校:{{item.school}}</p></li></ul><h3>学生列表(带索引值)</h3><ul><li v-for="item,key in student"><h4>索引值:{{key}}----{{item.studentName}}</h4><p>年龄:{{item.age}}--------学校:{{item.school}}</p></li></ul><h3>循环对象</h3><ul><li v-for="item,key in student[0]"><!--item,key顺序不能改-->key:{{key}}-----value:{{item}}</li></ul><img :src="student[0].imheader"><h3>条件+循环渲染(将偶数年龄的学生渲染出来):先循环再判断</h3><ol><li v-for="item,index in student" v-if="item.age%2==0" :key="index"><!--如果“”中是变量则key需要加冒号,如果是字符串数字等则不需要--><h4>索引值:{{index}}----{{item.studentName}}</h4><p>年龄:{{item.age}}--------学校:{{item.school}}</p></li></ol></div><script type="text/javascript">var app=new Vue({el:"#app",data:{stars:['周杰伦','陈奕迅','陈信宏','林俊杰'],student:[{studentName:"贺朝",age:17,school:"清华大学",imheader:"https://static.runoob.com/images/mix/searchicon.png"},{studentName:"谢俞",age:18,school:"北京大学"},{studentName:"蒋丞",age:19,school:"中国人民大学"},{studentName:"顾飞",age:20,school:"浙江大学"}]}})</script>
</body>
</html>

3、模板语法

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script><style type="text/css">#login{background-color: aquamarine;}#register{background-color: pink;}</style>
</head>
<body><div id="app"><h1>{{msg}}</h1><!--一次性插入,不再修改--><h1 v-once>{{msg}}</h1><!--插入html内容--><h1>{{htmlTxt}}</h1><h1 v-html="htmlTxt"></h1><!--修改属性内容--><!--绑定动态属性,全写--><div v-bind:id="idname"><h1>登录</h1></div><!--绑定动态属性,省略--><div :id="idname"><h1>登录</h1></div><!--模板语言的表达式应用--><div>{{firstname+lastname}}</div><!--三元运算符--><div>{{isVIP?"欢迎VIP用户回来!":"普通用户请充值"}}</div><!--事件的绑定--><button v-on:click="changeBtn">改变背景</button><button @click="changeBtn">改变背景</button></div><script>var app=new Vue({el:"#app",data:{msg:"hello Vue",htmlTxt:'<span>hello</span>',idname:"login",firstname:"张",lastname:"三",isVIP:true},methods:{changeBtn:function(){document.body.style.background="skyblue";}}})</script>
</body>
</html>

4、计算属性和侦听器
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。这时就用到了计算属性,它可以简化模板逻辑,又可以将计算的结果进行缓存,不用重新渲染,提高了性能。
计算属性与方法的区别

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body><div id="app"><!--一般情况下写法--><h1>{{firstname+lastname}}</h1><!--计算属性--><h1>{{fullname}}</h1><!--一般情况下单词逆序--><h1>{{word.split("").reverse().join("")}}</h1><!--计算属性--><h1>{{reverseword}}</h1><!--计算属性,显示年龄为偶数的学生信息--><ul><li v-for="item,index in evenstudent"><h3>{{item.studentName}}</h3><h4>{{item.age}}-----{{item.school}}</h4></li></ul></div><script type="text/javascript">var app=new Vue({el:"#app",data:{firstname:"张",lastname:"三",word:"english",student:[{studentName:"贺朝",age:17,school:"清华大学",imheader:"https://static.runoob.com/images/mix/searchicon.png"},{studentName:"谢俞",age:18,school:"北京大学"},{studentName:"蒋丞",age:19,school:"中国人民大学"},{studentName:"顾飞",age:20,school:"浙江大学"}]},computed:{fullname:function(){//会将计算的结果进行缓存,只要this.firstname和lastname变量的内容不改变,就不会重新计算return this.firstname+this.lastname;},reverseword:function(){return this.word.split("").reverse().join("");},evenstudent:function(){let result=this.student.filter(function(item){return item.age%2==0});return result;}}})</script>
</body>
</html>

待补充侦听器和set,get方法

5、Class 与 Style 绑定

  • 绑定 HTML Class
  • 绑定内联样式
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script><style>.page{background-color: orange;width: 200px;height: 200px;display: none;}.active{display: block;}</style>
</head>
<body><div id="app"><!--通过对象方式决定是否存在某个类--><div class="page" :class="{active:isTrue}"></div><!--直接放置对象--><div class="page" :class="styleObj"></div><!--放置数组--><div class="page" :class="styleAr"></div><!--放置字符串--><div class="page" :class="styleSt"></div><!--数组和对象混合使用--><div class="page" :class="styleArrObj"></div><!--css内联样式变量拼接--><div style="width: 100px;height: 100px;background-color: skyblue;" :style="{border:boderWidth+'px solid red',padding:paddingWidth+'px'}"></div><!--css内联样式放置对象--><div :style="styleObjcss"></div><!--css数组的方式拼接--><div :style="styleObjArrcss"></div></div><script>var app=new Vue({el:"#app",data:{isTrue:true,styleObj:{active:true,laochen:true,"col-lg-6":true},//可直接用数组的方式进行添加与删除比如app.styleAr.push("...")/popstyleAr:['col-xs-12','red-bg'],styleSt:"abc def qwer",styleArrObj:['abc',{active:true}],boderWidth:50,paddingWidth:10,styleObjcss:{width:"100px",height:"100px",padding:"50px",'background-color':'skyblue'},styleObjArrcss:[{width:"100px",height:"100px",padding:"50px",'background-color':'skyblue'},{border:"10px solid red"}]}})</script>
</body>
</html>

一个小例子(侧边栏的显示):

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script><style>*{margin: 0;padding: 0;box-sizing: border-box;}.page{width: 100vw;height: 100vh;background-color: skyblue;position: fixed;left: 0;top: 0;}.r1Menu{width: 50vw;height: 100vw;background-color: slateblue;position: fixed;top: 0;left: 0;transform: translateX(100vw);transition: transform 0.5s;}.r2Menu{width: 50vw;height: 100vw;background-color:palegoldenrod;position: fixed;top: 0;left: 0;transform: translateX(100vw);transition: transform 0.5s;}.active{transform: translateX(50vw);}</style>
</head>
<!--菜单栏与侧边栏的切换-->
<body><div id="app"><div class="page">首页<button @click="changeMenu" type="button">切换侧边栏</button></div><div class="r1Menu" :class="{active:isShow}" >侧边栏1</div><div class="r2Menu" :style="{transform:'translateX('+rmenuWidth+'vw)'}">侧边栏2</div></div><script>var app=new Vue({el:"#app",data:{isShow:false,rmenuWidth:100},methods:{changeMenu:function(){this.isShow=!this.isShow;if(this.rmenuWidth==100){this.rmenuWidth=70;}else{this.rmenuWidth=100;}}}})</script>
</body>
</html>

6、事件处理

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body><div id="app"><h1>点击次数:{{count}}</h1><!--某个事件中可以放方法名也可以放表达式--><!--可以使用表达式完成事件操作--><button @click="count+=1" type="button">点击1</button><!--获取事件对象--><button @click="clickEvent" type="button">点击2</button><!--有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法--><ul><li v-for="item,index in stars" @click="clickEvent(index,item,$event)">索引值-----{{index}}----名字:{{item}}</li></ul><!--事件修饰符--><!--stop修饰符:阻止冒泡事件向上传递(因为点击按钮会出发clickChild、clickParent两个事件,加上stop后只触发clickChild)--><div class="btnParent" @click="clickParent"><button @click.stop="clickChild">按钮</button></div><form action="" method="POST"><!--绑定输入框回车事件--><input type="text" @keydown.enter.f1="searchWeather" name="username" v-model="city"/><!--prevent修饰符:阻止默认事件--><input @click.prevent="searchWeather" type="submit" value="提交"/></form><!--once修饰符表示只触发一次--><div id="weather"><h1>{{tmp}}</h1><h1>{{brief}}</h1></div></div><script>//自定义按键修饰符,这里定义了f1Vue.config.keyCodes.f1 = 112var app=new Vue({el:"#app",data:{count:0,stars:['周杰伦','陈奕迅','林俊杰','阿信'],city:"广州",tmp:"",brief:""},methods:{clickEvent:function(index,value,event){console.log(event);console.log(this);console.log(index);console.log(value);this.count+=1;},clickParent:function(){console.log("clickParent");},clickChild:function(){console.log("clickChild");},searchWeather:async function(){                   console.log("searchWeather");console.log(this.city);let httpUrl=`https://free-api.heweather.net/s6/weather/now?location=${this.city}&key=6731996e93b2412e8778a99d53b07a89`;let res=await fetch(httpUrl);let result=await res.json();console.log(result);let now=result.HeWeather6[0].now;this.tmp=now.tmp;this.brief=now.cond_txt;}}})</script>
</body>
</html>

七、表单输入绑定
我们可以用 v-model 指令在表单 <input><textarea><select>元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body><div id="app"><h1>单行文本输入框</h1><p>{{username}}</p><!--.lazy表示等文本框输入完后双向绑定数据才进行改变,.trim表示自动忽略空格--><input type="text" name="username" v-model.lazy.trim="username"/><h1>多行文本输入框</h1><p>{{username}}</p><textarea v-model="username"></textarea><h2>复选框</h2><span v-for="item in fruits">{{item}}<input type="checkbox" v-model="checkFruits" :value="item"/></span><h2>{{checkFruits}}</h2><h2>单选框</h2><span v-for="item in fruits">{{item}}<input type="radio" v-model="radioFruits" :value="item"/></span><h2>{{radioFruits}}</h2><h2>选项框:选择你居住的城市</h2><select v-model="chooseCity"><option v-for="item in city" :value="item">{{item}}</option></select><p>{{chooseCity}}</p><h2>选项框(多选):选择你喜欢的城市</h2><select v-model="moreCity" multiple="multiple"><!--多选时需要按住ctrl键--><option v-for="item in city" :value="item">{{item}}</option></select><p>{{moreCity}}</p><h1>将字符串变为数字</h1><input type="text" name="age" v-model.number="age" /></div><script>let app=new Vue({el:"#app",data:{username:"xiaoming",fruits:['apple','banana','orange'],checkFruits:[],radioFruits:[],city:['shanghai','guangzhou','hangzhou'],chooseCity:"",moreCity:[],age:16}})</script>
</body>
</html>

八、过渡动画

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><style>.content{width: 200px;height: 200px;background-color: skyblue;}.fade-enter-active, .fade-leave-active {transition: opacity .5s;}.fade-enter, .fade-leave-to  {opacity: 0;}/*v-enter-active 和 v-leave-active 可以控制进入/离开过渡的过程时间,延迟和曲线函数*/.slide-enter-active, .slide-leave-active {transition: all 5s;}/*定义进入过渡的开始状态和离开过渡的开始状态*/.slide-enter, .slide-leave-to  {transform:translateX(500px);opacity: 0;}</style>
</head>
<!--过渡动画-->
<body><div id="app"><transition name="slide"><div v-if="isShow" class="content"></div></transition><button @click="changeEvent">切换内容</button></div><script>let app=new Vue({el:"#app",data:{isShow:true},methods:{changeEvent:function(){this.isShow=!this.isShow;}}})</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"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script><style>*{margin: 0;padding: 0;box-sizing: border-box;}.page{width: 100vw;height: 100vh;background-color: skyblue;position: fixed;left: 0;top: 0;}.r1Menu{width: 50vw;height: 100vw;background-color: slateblue;position: fixed;top: 0;left: 0;transform: translateX(50vw);}/*自动追加类名*/.slideRight-enter-active,.slideRight-leave-active{transition:all 5s;}.slideRight-enter,.slideRight-leave-to{transform: translateX(100vw);}</style>
</head>
<!--菜单栏与侧边栏的切换-->
<body><div id="app"><div class="page">首页<button @click="changeMenu" type="button">切换侧边栏</button></div><transition name="slideRight"><div class="r1Menu" v-if="isShow" >侧边栏1</div></transition><script>var app=new Vue({el:"#app",data:{isShow:false,               },methods:{changeMenu:function(){this.isShow=!this.isShow;}}})</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"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body><div id="app"><h1>{{msg}}</h1><h1 :class="className">类名绑定</h1></div><script>let app=new Vue({el:"#app",data:{msg:"helloVue",className:"rubg"},beforeCreate(){console.log('beforeCreate')console.log(this)console.log(this.msg)console.log(this.clickEvent)//此时数据data和事件方法methods还未绑定到app对象上},created(){//此时数据data和事件方法methods绑定到应用对象app上console.log('created')},beforeMount(){//渲染之前,根据数据生成的DOM对象是获取不到的console.log('beforeMount')let dom=document.querySelector(".rubg")console.log(dom)},mounted(){//渲染之后,可以获取数据生成的DOM对象console.log('mounted')let dom=document.querySelector(".rubg")console.log(dom)},methods:{clickEvent:function(){}},beforeUpdate(){//数据更改,但内容未更改之前console.log('beforeUpdate')},updated(){//内容已更新完成console.log('updated')},beforeDestroy(){//应用销毁之前console.log('beforeDestroy')},destroyed(){//应用销毁之后console.log('destroy')}})</script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body><div id="app"><hello-com v-if="isShow"></hello-com><!--v-show当isShow为false时,不会销毁组件,而是让display:none--><hello-com v-show="isShow"></hello-com></div><script>Vue.component('hello-com',{template:'<div><h1>{{name}}</h1><button @click="changeData">修改数据</button></div>',data:function(){return {name:"hello ty"}},methods:{changeData:function(){this.name="hello jay"}},beforeCreate(){console.log('beforeCreate')//此时数据data和事件方法methods还未绑定到app对象上},created(){//此时数据data和事件方法methods绑定到应用对象app上console.log('created')},beforeMount(){//渲染之前,根据数据生成的DOM对象是获取不到的console.log('beforeMount')},mounted(){//渲染之后,可以获取数据生成的DOM对象console.log('mounted')},beforeUpdate(){//数据更改,但内容未更改之前console.log('beforeUpdate')},updated(){//内容已更新完成console.log('updated')},beforeDestroy(){//应用销毁之前console.log('beforeDestroy')},destroyed(){//应用销毁之后console.log('destroy')}})let app=new Vue({el:"#app",data:{isShow:true},})</script>
</body>
</html>

十、组件基础
1、全局组件or局部组件
全局组件(先注册组件再实例化)

<!--全局变量-->
<div id="app"><runoob></runoob>
</div><script>
// 注册
Vue.component('runoob', {template: '<h1>自定义组件!</h1>'
})
// 创建根实例
new Vue({el: '#app'
})
</script>

局部组件:这样组件只能在这个实例中使用

<div id="app"><runoob></runoob>
</div><script>
var Child = {template: '<h1>自定义组件!</h1>'
}// 创建根实例
new Vue({el: '#app',components: {// <runoob> 将只在父模板可用'runoob': Child}
})
</script>

2、组件间的传值

  • 从父组件传到子组件(传数据):利用 props和v-bind。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<!--组件之间的传值:从父组件传到子组件-->
<body><div id="app"><ul><!--从父组件传值到子组件--><!--静态属性--><school school-name="清华北大"></school><!--动态属性--><school v-bind:school-name="'上海师大'"></school><!--动态属性--><school v-bind:school-name="schoolList[0]"></school><!--循环传值组件--><school v-for="item,index in schoolList" :key="'abc'+index" :index='index' :school-name="item"></school></ul></div><script>//学校组件Vue.component("school",{props:['schoolName','index'],template:`<li><h3>{{index}}学校名称:{{schoolName}}</h3></li>`,})//根组件let app=new Vue({el:"#app",data:{schoolList:['qinghua','beida','hangdian','xiamen']}})</script>
</body>
</html>
  • 从子组件传到父组件(传数据):注意每个组件都有各自的触发方法在methods中,通过在子组件触发方法中写this.$emit(绑定的父组件触发事件名,参数)进行传输数据。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<!--组件之间的传值:从子组件传到父组件-->
<body><div id="app"><ul><!--循环传值组件--><school v-for="item,index in schoolList" @childparent='changeEvent' :key="'abc'+index" :index='index' :schoolname="item"></school></ul><h2>选中的学校是:{{chooseSchool}}</h2></div><script>//学校组件Vue.component("school",{props:['schoolname','index'],template:`<li><h3>{{index}}学校名称:{{schoolname}}</h3><button @click="chooseEvent(schoolname)">选择学校</button></li>`,methods:{chooseEvent:function (schoolname) {console.log(schoolname)//想要将子元素的数据传递给父元素,需要自定义触发事件实现数据传值//触发一个事件名称叫做child-parent的事件this.$emit('childparent',schoolname)}}})//根组件let app=new Vue({el:"#app",data:{schoolList:['qinghua','beida','hangdian','xiamen'],chooseSchool:""},methods:{changeEvent:function (data) {console.log("触发学校选择事件"),this.chooseSchool=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"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<!--组件之间的传值:将父元素方法传值给子元素-->
<body><div id="app"><ul><!--从父组件传值到子组件--><!--循环传值组件--><!--因为因为父元素的方法可以直接修改父元素的数据所以将父元素的方法传递给子元素然后由子元素进行调用,从而修改父元素的数据--><school v-for="item,index in schoolList" :action='changeEvent' :key="'abc'+index" :index='index' :schoolname="item"></school></ul><h2>选中的学校是:{{chooseSchool}}</h2></div><script>//学校组件Vue.component("school",{props:['schoolname','index','action'],template:`<li><h3>{{index}}学校名称:{{schoolname}}</h3><button @click="chooseEvent(schoolname)">选择学校</button></li>`,methods:{chooseEvent:function (schoolname) {console.log(schoolname)//console.log(this.action)this.action(schoolname)}}})//根组件let app=new Vue({el:"#app",data:{schoolList:['qinghua','beida','hangdian','xiamen'],chooseSchool:""},methods:{changeEvent:function (data) {//console.log("触发学校选择事件")this.chooseSchool=data}}})</script>
</body>
</html>
  • 直接通过$parent属性找到父元素的vue对象(不建议用,因为通常我们是想让组件之间是低耦合的状态)
    当在子组件的方法中console.log(this)中后会得到下面的输出,可以看到在$parent属性下有根组件的所有内容。所以我们可以利用该属性找到父元素的vue对象。$root是最外层的根组件属性。$children是子属性。
//子组件
Vue.component("school",{props:['schoolname','index','action'],template:`<li><h3>{{index}}学校名称:{{schoolname}}</h3><!--2、在视图直接调用父元素方法--><button @click="$parent.changeEvent(schoolname)">选择学校</button><!--3、在视图直接修改父元素中的值--><button @click="$parent.chooseSchool=schoolname">选择学校</button></li>`,methods:{chooseEvent:function (schoolname) {//console.log(schoolname)//console.log(this)//1、组件可以通过$parent属性找到父元素的vue对象//this.$parent.changeEvent(schoolname)}}})//根组件let app=new Vue({el:"#app",data:{schoolList:['qinghua','beida','hangdian','xiamen'],chooseSchool:""},methods:{changeEvent:function (data) {//console.log("触发学校选择事件")//console.log(this)this.chooseSchool=data}}})

3、一点补充(补充前面出现的属性)
prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 “prop”:

  • 动态 Prop
<div id="app"><div><input v-model="parentMsg"><br><child v-bind:message="parentMsg"></child></div>
</div><script>
// 注册
Vue.component('child', {// 声明 propsprops: ['message'],// 同样也可以在 vm 实例中像 "this.message" 这样使用template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({el: '#app',data: {parentMsg: '父组件内容'}
})
</script>
  • 使用 v-bind 指令将 todo 传到每一个重复的组件中
<div id="app"><ol><todo-item v-for="item in sites" v-bind:todo="item"></todo-item></ol>
</div><script>
Vue.component('todo-item', {props: ['todo'],template: '<li>{{ todo.text }}</li>'
})
new Vue({el: '#app',data: {sites: [{ text: 'Runoob' },{ text: 'Google' },{ text: 'Taobao' }]}
})
</script>

prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。

  • Vue.js 组件 - 自定义事件
    父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
    我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:

–使用 $on(eventName) 监听事件
– 使用 $emit(eventName) 触发事件

另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

  • 一个小例子(计数器)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例 - 菜鸟教程(runoob.com)</title>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app"><div id="counter-event-example">// 6. 页面上更新total的值<p>{{ total }}</p> // 4. 这里的自定义事件再次触发局域方法incrementTotal<button-counter v-on:increment="incrementTotal"></button-counter><button-counter v-on:increment="incrementTotal"></button-counter></div>
</div><script>
// 1. 注册全局组件
Vue.component('button-counter', {//  2. button绑定点击事件incrementHandler template: '<button v-on:click="incrementHandler">{{ counter }}</button>',data: function () {//data 必须是一个函数return {counter: 0}},methods: {// 3. 点击事件触发后,再次触发自定义事件incrementincrementHandler: function () {this.counter += 1this.$emit('increment')}},
})
new Vue({el: '#counter-event-example',data: {total: 0},methods: {// 5. 局域方法执行了total+1incrementTotal: function () {this.total += 1}}
})
</script>
</body>
</html>

  • Vue组件中的data是函数的原因
    为什么Vue组件中的data是一个函数原理(转载)

4、 v-model与插槽

  • v-model
<!--v-model的作用相当于下面语句的作用-->
<input type="text" v-model="username"/>
<input type="text" @input="username=$event.target.value" :value="username"/>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<!--原始的数据绑定
<body><input type="text" id="username"/><h1></h1><script>let inputDom=document.querySelector("#username")inputDom.οninput=function(){document.querySelector("h1").innerHTML=inputDom.value}</script>
</body>
--><!--v-model-->
<body><div id="app"><!--这里的input事件是在模板里emit后定义的名字为input,这里的三个input都相互等价--><input-com :username1="username" @input="changeEvent"></input-com><input-com :username1="username" @input="username1=$event"></input-com><input-com v-model="username"></input-com><h3>{{username}}</h3></div><script>Vue.component('input-com',{props:['username1'],template:`<input type="text" @input="$emit('input',$event.target.value)" :value="username1"/>`,data:function(){return{}}})let app=new Vue({el:"#app",data:{username:""},methods:{changeEvent:function(data){this.username=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"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body><div id="app"><alert-com :html='content'></alert-com><!--slot里面的内容变量只跟父元素有关--><alert-com1 ><p>注意安全,{{content}}</p></alert-com1></div><script>Vue.component('alert-com',{props:['html'],template:`<div class="alert"><h1>温馨提示</h1><div class="content">{{html}}</div></div>`})Vue.component('alert-com1',{template:`<div class="alert"><h1>温馨提示</h1><div class="content"><slot></slot></div></div>`,data:function(){return{}}})let app=new Vue({el:"#app",data:{content:'天干物燥,小心火烛'}})</script>
</body>
</html>

5、动态组件
利用component标签中的is属性动态选择组件。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body><div id="app"><div id="content"><!--动态组件:利用component标签中的is属性选择组件--><component :is="com"></component></div><button @click="chooseContent(1)">首页</button><button @click="chooseContent(2)">列表</button><button @click="chooseContent(3)">新闻</button><button @click="chooseContent(4)">个人</button></div><script>let com1=Vue.component('index-com',{template:'<h1>首页内容</h1>'})let com2=Vue.component('list-com',{template:'<h1>列表内容</h1>'})let com3=Vue.component('news-com',{template:'<h1>新闻内容</h1>'})let com4=Vue.component('me-com',{template:'<h1>个人内容</h1>'})let app=new Vue({el:"#app",data:{com:com1},methods:{chooseContent:function(id){console.log(id)console.log(this)//通过获取id,选择注册好的组件this.com=this.$options.component['com'+id]}},component:{com1,com2,com3,com4}})</script>
</body>
</html>

一个非常有用的网站:vant官网

Vue框架的入门基础学习相关推荐

  1. python3.8学习_python3.8.1 入门基础学习 之 【字典】 学习

    python3.8.1 入门基础学习 之 [字典] 学习字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整 ...

  2. java入门基础学习(三)

    文章目录 (一)有返回值的方法 (二)方法重载 习题 (一)有返回值的方法 格式:public static 返回值数据类型 方法名(参数){方法体return 数据;} 注意:1.返回值数据类型非v ...

  3. PS合成图片#ps抠图#ps视频教程入门基础学习课程小白

    PS合成图片#ps抠图#ps视频教程入门基础学习课程小白

  4. [Vue.js 1] 入门基础知识与开发

    最近接触的几个项目框架全部用到了Vue.js技术,没办法只能对vuejs进行深入学习,不过可喜的是Vue.js学习路线非常快,上手也是非常快的,所以对于前端开发也是主流的开发框架了.不过其中的js部分 ...

  5. Python编程入门基础学习

    编程语言 1.脚本编程语言 ★脚本编程语言 如php,perl,python,java等为脚本编程语言,通常需要通过解释器解释运行. ★python(java)程序的执行过程 source code( ...

  6. 音视频怎样入门?带你入门基础+学习思路

    Android开发的路越走越难,难道真的没有其他出路了? 并没有,一个行业的下降趋势也会带起新的行业,他的本质不会变,技术会稍有改变,本篇我们就来说说音视频行业. 音视频行情分析 1.市场 市场是一个 ...

  7. python创建对象的格式为_Python入门基础学习(面向对象)

    python基础学习笔记(四) 面向对象的三个基本特征: 封装:把客观事物抽象并封装成对象,即将属性,方法和事件等集合在一个整体内 继承:允许使用现有类的功能并在无须重新改写原来的类情况下,对这些功能 ...

  8. 人工智能门槛太高?用这个框架轻松入门深度学习!

    想学学深度学习,真的就那么难,门槛那么高吗? 先放一张关于深度学习的图. 门外汉觉得我在造终结者,其他程序员觉得我是土豪,我自己也觉得自己要上天.可是实际上,我只是在 import keras 然后 ...

  9. Vue的快速入门通俗易懂(学习笔记)

    本文是观看"[狂神说Java]Vue最新快速上手教程通俗易懂 "所记录的笔记,读者结合视频阅读更佳,文章包含了个人对相关知识点的粗略理解,借此进行分享,文中代码结构理解有误的地方, ...

最新文章

  1. 【转载】详解 Spring 3.0 基于 Annotation 的依赖注入实现
  2. 通信模式与网络协议之间的对应关系
  3. 微服务之:从零搭建ocelot网关和consul集群
  4. java类同步_Java中方法,对象,类的同步
  5. Android wifi驱动的移植 realtek 8188
  6. 关于juniper配速小记
  7. python并列语句_Python基础_控制语句
  8. 支持向量机(SVM)-文本分类 (1)
  9. 蓝桥杯2017年第八届C/C++省赛C组第一题-贪吃蛇长度
  10. 论文英文参考文献[10]的时候后面多空格_毕业生必看论文查重修改技巧
  11. Java中对数组的操作
  12. CSS 中文字体的英文名称 (simhei, simsun) 宋体 微软雅黑
  13. 【时间序列】多变量时间序列异常检测数据集整理及标准化处理代码合集
  14. ETERM航班销售控制指令
  15. cmd文件和bat文件的区别+一个的bat脚本+bat基础知识
  16. 使用 LDAP Browser 登入ad域控提示 Root error: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903C5, commen
  17. leetcode题解(含解题思路)(持续更新中)
  18. Asp.net Core使用Microsoft.Office.Interop.Word转换文档
  19. 7-3 试试多线程 (10 分)
  20. Android开发——进程间通信之Bundle和文件

热门文章

  1. Html文本学习内容-2
  2. NRFL2401学习
  3. 关于在Linux下无法查看caj文档的解决方案
  4. 卷积神经网络(LeNet)——【torch学习笔记】
  5. Java面试总结,Java实习面试经验汇总
  6. 复现计算机论文模型,深度学习模型复现难?看看这篇句子对模型的复现论文
  7. EXPDP预估导出空间estimate,estimate_only
  8. 《重新定义公司:谷歌是如何运营的》读书笔记
  9. 如何按要求比较两个数的大小(不使用大于、小于以及if语句)
  10. c语言 /= 和 *= 是什么意思?