哈尔滨优化调整人员流动管理,wordpress 自带seo,如何做电影网站资源,深圳建设局网站投诉电话1.认识Vue
官网地址#xff1a;https://v2.cn.vuejs.org/v2/guide/
Vue.js 是一套构建用户界面的渐进式框架。
Vue 2 是在2016年发布使用#xff0c;2020是 vue3 才刚发布#xff0c;时隔一年左右就已经将 vue3 作为了默认版本 尤雨溪#xff0c;Vue.js和Vite的作者https://v2.cn.vuejs.org/v2/guide/
Vue.js 是一套构建用户界面的渐进式框架。
Vue 2 是在2016年发布使用2020是 vue3 才刚发布时隔一年左右就已经将 vue3 作为了默认版本 尤雨溪Vue.js和Vite的作者HTML5版Clear的打造人独立开源开发者。 曾就职于Google Creative Labs和Meteor Development Group。 由于工作中大量接触开源的JavaScript项目最后自己也走上了开源之路现全职开发和维护Vue.js。 尤雨溪毕业于上海复旦附中在美国完成大学学业 尤雨溪大学专业并非是计算机专业在大学期间他学习专业是室内艺术和艺术史 引入VUEscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/script最好下载下来以文件路径引入会受到网络因素的影响。
为什么要使用vue
DOM操作比较耗费性能是前端的性能瓶颈而vue几乎没有DOM操作
虚拟DOM 性能高 数据驱动视图在html中操作变量。找真实DOM和虚拟DOM之间的差别只更新有差别的地方使用diff算法比较很快不怎么耗费性能而不是全部做修改 组件化作用域彼此独立组件化便于复用数据与视图分离
2.基本语法
div idapp{{ message }} {{info}}
/divscriptlet app new Vue({//配置项el: #app,//挂载点data: {message: Hello,info:vue}})
/script
el挂载点使用div作为vue挂载点将来的vue项目要渲染到哪里。
data以对象的形式存储数据
在html中写的是变量相应的数据存在data中之后如果需要修改数据不需要做DOM操作只需要修改变量即可。
双大括号插值表达式双大括号其实提供了一个js执行环境可以写任意js表达式不能写语句不识别html结构。
一个元素中可以有多个插值表达式
数据统一存放在data中
3.指令
注意所有指令后面的引号是提供一个js执行环境的不是字符串的引号。 不带标签的只有内容的用双大括号插值表达式{{}};不用v-text内容带标签的用v-html;绑定属性属性是变化的注意class和style的特殊性绑定事件v-if v-else 条件渲染 频繁创建与删除元素v-show 显示与隐藏 一开始就会创建出来元素再做显示隐藏的修改v-for 循环创建数目不定的元素 注意要用 :key“index”v-model 表单的双向绑定 v-bind:属性名数据
简写 :属性名属性值
如 :class{act:true}v-on:事件名函数名
简写 事件名函数名
如 clickchange在JQuery中的思想是先获取元素做DOM操作而在Vue中是直接操作数据。
v-html
把一段html结构渲染到它所绑定的元素里面
如果元素本身内部有内容会被指令中的内容覆盖掉
v-text
把一段文本内容渲染到它所绑定的元素中
v-bind
动态绑定属性所有写在开始标签里的都是属性。
v-bind:属性名数据
常用简写 :属性名数据div idappdiv :ida :classb{{msg}}/div/divscriptlet appnew Vue({el:#app,data:{a:box,b:title,msg:Hello,info:h1world/h1}})
/script
v-bind的特殊情况
class !-- 方式一绑定字符串 一个class名 --
div idapph1 :classmyClass{{msg}}/h1/divscriptlet app new Vue({el: #app,data: {myClass: title,msg: hello,}})
/script!-- 方式二同方式三直接绑定对象内容 多个class名 --
div idapph1 :class{aa:flag,bb:false,cc:true,dd:false}{{msg}}/h1/divscriptlet app new Vue({el: #app,data: {myClass: title,flag: true,msg: hello,}})
/script!-- 方式三绑定对象 多个class名 --
div idapph1 :classobj{{msg}}/h1/divscriptlet app new Vue({el: #app,data: {myClass: title,flag: true,msg: hello,obj: { aa: true, bb: false, cc: true, dd: false }}})
/script!-- 方式四绑定数组 多个class名 --
div idapph1 :class[aa,bb,myClass]!-- 或者 h1 :class[obj,obj2] h1 :classarr h1 :classarr2 --{{msg}}/h1/divscriptlet app new Vue({el: #app,data: {myClass: title,flag: true,msg: hello,obj: { aa: true, bb: false, cc: true, dd: false },obj2: { ee: true },arr: [aa, bb],arr2:[ { aa: true, bb: false, cc: true, dd: false },{ ee: true },]}})
/script
- 可以绑定一个字符串字符串名就是class名
- 可以绑定一个对象对象的属性名就是class名对象的属性值是布尔代表是否有这个class
- 可以绑定一个数组数组里是变量名变量值就是class名字style在DOM操作中得到的样式就是一个对象注意:写样式的时候样式的属性值要加引号并且属性名是有多个单词组成的要写成驼峰式。
!-- 方式一同方式二直接绑定对象内容 一个样式 --
div idapph1 :style{width:200px,height:200px,backgroundColor:bgColor}{{msg}}/h1/divscriptlet appnew Vue({el:#app,data:{msg:hello,bgColor:red}})
/script!-- 方式二绑定对象一个样式 --
div idapph1 :stylecssStyle{{msg}}/h1/divscriptlet appnew Vue({el:#app,data:{msg:hello,cssStyle:{width:200px,height:200px,backgroundColor:red}}})
/script!-- 方式三绑定数组多个样式 --
div idapph1 :style[cssStyle,cssStyle2]!-- 或者 h1 :stylecssStyle3 --{{msg}}/h1/divscriptlet appnew Vue({el:#app,data:{msg:hello,cssStyle:{width:200px,height:200px,backgroundColor:red},cssStyle2:{color:blue,fontSize:35px},cssStyle3:[{width:200px,height:200px,backgroundColor:red},{color:blue,fontSize:35px}]}})
/script
- 绑定到一个对象对象就是样式对象
- 绑定到一个数组就是绑定到多个样式对象v-on
v-on:事件名函数名
缩写为 事件名“函数”函数不放在data中放在另一个配置项methods中。
函数如果有参数在指令里面直接加括号写参数就行了没有参数就不需要加括号。
关于事件对象想要既拿到事件对象又要自己的参数只有事件触发的时候才会有事件对象用匿名函数再包一层在匿名函数里面执行。
事件名(e){fn(e,实参)}!-- 使用例子 --
div idapp!-- button clickfn按钮/button 输出2--!-- button clickfn2(你好)按钮/button 输出你好 --button click(e){fn3(e,hello)}按钮/button!-- 输出事件对象 hello --
/divscriptnew Vue({el: #app,data: {msg: 这是我的第一个vue程序},methods: {fn() {console.log(2)},fn2(m) {//输出传的参数console.log(m)},fn3(e, m) {//输出带有事件对象的参数console.log(e, m)}}})
/script
案例1点击按钮更改h1的内容。 !-- 点击按钮h1的内容发生更换 --
div idapph1{{msg}}/h1button clickfn按钮/button/divscriptnew Vue({el: #app,data: {msg: 这是我的第一个vue程序,},methods: {fn() {this.msg 我是新的数据。}}})
/script
案例2点击按钮控制数据的显示与隐藏。
style#title {width: 200px;height: 200px;background-color: red;}
/stylediv idappdiv idtitle :style{display:show}/divbutton clicktoggle切换/button/divscriptnew Vue({el: #app,data: {show: block},methods: {toggle() {//使用三目运算符 判断show的值this.show (this.show block ? none : block)}}})
/script
按键修饰符常用在表单input中。
在监听键盘事件时我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键
input keyup.entersubmit
input keyup.downonPageDown为了在必要的情况下支持旧浏览器Vue 提供了绝大多数常用的按键码的别名
.enter.tab.delete (捕获“删除”和“退格”键).esc.space.up.down.left.right
v-if v-else v-else-if
类似于JQuery中的show()和hide()
控制整个元素是否渲染不是基于样式的 是真正的条件渲染满足条件就创建出来不满足条件就删掉。 h1 v-if gradesA 优秀/h1h1 v-else-ifgradesB良好/h1h1 v-else-ifgradesC及格/h1h1 v-else不及格/h1
注意使用v-if的时候
v-if的元素是和v-else必须是同级v-if的元素和v-else的元素必须紧挨着中间不允许夹杂其他元素适合用于多选一的情况
v-show显示与隐藏
基于样式的切换而并不是把元素删掉了。
案例2点击按钮控制数据的显示与隐藏。
div idappdiv idtitle v-showshow/divbutton clicktoggle切换/button/divscriptnew Vue({el: #app,data: {show: true},methods: {toggle() {this.show !this.show}}})
/script
v-if 与 v-show的性能对比 v-if 是“真正”的条件渲染因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。 v-if 也是惰性的如果在初始渲染时条件为假则什么也不做——直到条件第一次变为真时才会开始渲染条件块。 相比之下v-show 就简单得多——不管初始条件是什么元素总是会被渲染并且只是简单地基于 CSS 进行切换。 一般来说v-if 有更高的切换开销需要频繁的创建与删除元素而 v-show 有更高的初始渲染开销不管是否需要显示都先创建出来再改样式这样在大量数据需要处理的时候就回产生巨大的开销。因此如果需要非常频繁地切换则使用 v-show 较好不需要反复的删除和创建元素如果在运行时条件很少改变则使用 v-if 较好。 v-for 元素个数是变量
1.基本用法
将v-for放在元素的开始标签中代表的是循环创建多个该元素删除和创建元素时就变为了修改数组和对象的内容。
可以循环数组 (value,index)可以循环对象 (value,key,index)可以循环整数 item
!-- v-for使用方法 --
div idapp!-- 1 循环数组 --selectoption v-for(item,index) in provinces{{index}} {{item}}!-- item值 index角标 --/option/select!-- 2 循环对象 --selectoption v-for(item,key,index) in obj{{index}} {{key}}:{{item}}!-- item值 key属性名 index循环次数 --/option/select!-- 循环整数 --div v-for(item,index) in 10 :keyindex{{item}}!-- 输出1-10的整数 --/div/divscriptnew Vue({el: #app,data: {provinces: [山东省, 河北省, 河南省, 山西省],obj: { name: 张三, age: 18, gender: boy }},})
/script 建议尽可能在使用 v-for 时提供 key attribute 除非遍历输出的 DOM 内容非常简单或者是刻意依赖默认行为以获取性能上的提升。 注意v-if和v-for尽量避免同时使用可以将v-if套在v-for的外层使用因为v-for的优先级比v-if更高当v-if为false时会先执行v-for创建元素再判断v-if为false删除元素。
template/template标签也是一个容器 在需要的时候可以发挥作用但在编译时不存在了可以在需要一个容器但是与页面结构无关的时候使用。
div idapptemplate v-showshowdiv v-fori in 9{{i}}/div/template!-- 这里使用template/template标签是因为如果使用div标签会产生一个与页面结构无关的标签 --
/divscriptnew Vue({el:#app,data:{show:true}})
/script
key的作用
为什么需要key div idappinput typetext v-ifsee keya/input typepassword v-else keyb/button clickchange更改/button!-- button clicksee!see更改/button --
/divscript
new Vue({el: #app,data: {see:true},methods:{change(){this.seefalse}}
})
/script!-- 实现效果先显示typetext的输入框点击更改后显示为typepassword的输入框但是原来text中的内容还会在password中因为vue是只更改不一样的部分二者都是输入框只是类型不一样vue只做了更改类型的操作 这时就可以给两个input不一样的key属性当发现key不一样时会做删除添加元素而不进行复用。
--尽量不要使用索引值index作key值一定要用唯一标识的值如id等。因为若用数组索引index为key当向数组中指定位置插入一个新元素后因为这时候会重新更新index索引对应着后面的虚拟DOM的key值全部更新了这个时候还是会做不必要的更新就像没有加key一样因此index虽然能够解决key不冲突的问题但是并不能解决复用的情况。如果是静态数据用索引号index做key值是没有问题的。 响应式原理
由于 JavaScript 的限制Vue 不能检测数组和对象的变化 。
在实际工作中使用的Vue.set()只更新一个的情况很少一般都是直接将数组和对象整体进行替换。
对于对象来说:
property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的只能做修改不能添加。
对于已经创建的实例Vue 不允许动态添加根级别的响应式 property。
//想要响应式的添加属性可以使用如下方法嵌套对象添加响应式 property
Vue.set(object, propertyName, value)
//哪个对象 想要增加哪个属性名 属性值this.obj.age 58//age属性已经存在 修改属性值Vue.set(this.obj, salary, 2500)//salary属性不存在添加属性对于数组来说:
直接通过角标赋值是无法设置为响应式的。
直接修改长度也是无法设置为响应式的。
方法一需要修改数组的某一项时不是仅替换该项而是将整个数组替换掉需要使用深复制的方法(扩展运算符简单)。该方法需要解决深复制的问题不如方法二简单 //search是数组变量let arr [...this.search]arr[2] 8this.search arr方法二 只修改数组的某一项比方法一更简单不用深复制。
//只想修改数组的某一项可以使用如下方法为数组添加响应式 property
Vue.set(vm.items, indexOfItem, newValue)
//哪个数组 数组的第几项 新值Vue.set(this.search,1,8);总结
数组法一完整替换 法二深复制.let narr[...arr]
narr[0]w
state.arrnarr法三set().对象法一完整替换 法二深复制相同属性名后面的属性值覆盖前面的属性值。state.person{...person,salary:8000}法三set()数组更新检测
Vue 将被侦听的数组的变更方法进行了包裹所以它们也将会触发视图更新。这些被包裹过的方法包括
push()pop()shift()unshift()splice() 删除或添加数组的某一项sort()reverse()
v-model 表单双向绑定
基本使用
其他的vue都是数据驱动视图双向绑定既可以数据驱动视图又可以视图驱动数据这样在vue中想要拿到表单的value值只需要取变量即可不像之前的js中还得等到用户有输入onblur了才能拿到值在vue中直接随时就可以拿到。变量的初始值可以设置为。
表单的双向绑定v-model默认绑定到表单的value属性。
输入框input直接绑定到值value变量初始值可以设置为.多选框checkbox 单个多选框绑定到布尔值若变量初始值设置为true则默认勾选了多个复选框绑定的是value的数组变量的初始值可以设置为[]若变量中的初始值有一个默认的值[“打篮球”]那么该value值对应的多选框会被默认选中。单个多选框常用于注册时的确认协议直接获取绑定的变量值是否为true/flase来判断是否选中.多个多选框判断绑定的变量值中是否有某个值来判断是否选中了该项。单选框radio直接绑定到值value。若将变量的初始值设置为某个值则显示出来的是默认选中该项。下拉选择框select直接绑定到值value.双向绑定也可以绑定到数组的某一项或者对象的某一项让该项的内容给到表单的value.
案例1todolist待办事项。 !-- 1.在工作中只要遇见了表单一定会加双向绑定的。2.给每个li绑定点击事件点谁谁删除.splice删除哪一项时index刚好与之对应想要在方法中使用index可以将index作为参数在函数中传递--
div idappinput typetext placeholder请输入您的待办事项 v-modeltodo keyup.enteraddbutton clickadd添加/buttondivulli v-for(item,index) in list :keyindex clickremove(index){{item}}/li/ul/div/divscriptnew Vue({el: #app,data: {todo: ,list: [],},methods: {add() {this.list.push(this.todo)this.todo },remove(index) {this.list.splice(index, 1)}}})
/script
案例2使用vue实现导航条高亮效果 style* {padding: 0;margin: 0;}.clear {clear: both;}.tab {float: left;width: 60px;height: 30px;line-height: 30px;text-align: center;margin-right: 15px;background-color: gray;color: white;}.active {background-color: pink;color: blue;}
/stylebody!-- 作业导航条导航条的内容是通过列表动态渲染的 list:[首页,特惠,资讯,游记,地区]点谁谁高亮 背景色和文字颜色 其余的的恢复默认思路我自己不知道怎么只选中一个div是否应该存在.act 使用一个变量flag其初始值为0默认选中第一个导航条当点击时就将index赋值给flag判断flag与index是否相等来决定是否要有.act--div idappdiv classtab v-for(item,index) in list :keyindex clickchange(index) :class{active:indexflag}!-- 注意这里的类名要加上引号 change()传递index参数--{{item}}/divdiv classclear/div/divscriptnew Vue({el: #app,data: {list: [首页, 特惠, 资讯, 游记, 地区],flag: 0, //当前点的项的序号},methods: {change(index) {this.flag index}}})/script/body
修饰符
!-- 在“change”时而非“input”时更新 在失去焦点时更新而不是每次都更新--
input v-model.lazymsg
!--表单的数据默认是字符串类型的如果想自动将用户的输入值转为数值类型可以给 v-model 添加 number 修饰符--
input v-model.numbernum
!--如果要自动过滤用户输入的首尾空白字符可以给 v-model 添加 trim 修饰符--
input v-model.trimmsg4.methods 配置项
方法的集合鼓励使用es6的形式。
5.computed 计算属性 配置项
在后端一般不存储字符串而是存储数字占内存小使用数字代表其中字符串的含义如1代表男2代表女这样从后端拿回到的数据就是1 2而我们要渲染到页面中的是字符串这时我们就需要将数数字转换成对应的字符串。
h1性别{{gender1?男:女}}/h1这样可以解决问题。但是不这么用因为这样会将大量的逻辑写在html中结构很乱影响页面的整洁性而且对于多步骤的运算实现不了。
h1性别{{sex()}}/h1 sex(){return gender1?男:女}这样将判断写在函数中调用函数也是可以实现的。但是也不这么用因为这样如果修改另一个与之不相关的数据内容而调用函数的数据并没有要改变但是方法还会再执行一次影响性能。vue是数据驱动视图的只要改了数据视图就需要重新渲染方法就需要重新调用 !--计算属性的用法--
div idapph1{{sex}}/h1!-- 这里调用计算属性不加括号是属性不是函数 --
/divscriptnew Vue({el: #app,data: {gender: 2},computed: {sex() {return this.gender 1 ? 男 : 女}}})
/script
计算属性是个函数要求一定有返回值。不能和data中的数据重名。计算属性是基于缓存的只有在他计算依赖的项有变化的时候他才会重新运算否则不运算。 依赖此函数中用到的数据有变化那么计算属性都会重新运行。 计算属性最终的结果是个属性调用的时候不能加括号在vue内部自动帮忙调用了。计算属性也是可以传参的只需要让返回值是个函数即可最终用的是里层的函数 。计算属性中除了可以使用data中的数据也可以使用其他的计算属性和props的内容。
!-- 计算属性传参数return一个函数将操作写在return的函数中即可 --
h1{{order(2)}}/h1scriptnew Vue({el:data:methods:computed:{order(){return (status){console.log(status)}}}})
/script 计算属性跟函数的区别(面试题) 1.计算属性一定要返回值函数不一定。 2.函数需要主动调用才会执行计算属性依赖的项变化的时候才执行。 3.计算属性比函数性能高因为是基于缓存的不会像函数一样每次都调用只有依赖的项有变化的时候才执行。 6.watch监听器 配置项 监听某个数据只要该数据变了就会执行函数。 优先考虑用计算属性computed能否解决问题在实际工作中的watch用的还是比较少的滥用watch可能会导致性能问题 函数名必须是一个已存在的在data中的数据名函数名即是你所监听的数据名。首次加载不执行只有在后续数据变化的时候才会运行。检测的数据可以是data中的也可以是computed还可以是props属性 和 $route。接受两个参数第一个是最新的值第二个是变化之前的值。 computed和watch的异同点面试题 1.计算属性是返回一个值watch是监听一个值做某件事情的。 2.计算属性是值变化的时候重新运算返回一个新值watch值变化的时候执行函数值变化时做事。 3.都不需要主动调用都是基于值变化的。 7.组件
使用组件化的原因便于开发 便于复用多次使用时不用多次复制。
组件一段封装了html css js的代码。
组件的名字可以自定义一般看到的不认识的标签就是组件。
组件的两种注册方式
全局注册可以在任何vue实例中生效但基本用不到因为基本只用一个Vue实例。局部注册在组件内部注册在哪用就在注册用的很多。
注意1. 对象参数中template必须要有其他的可以没有html代码使用es6的字符串扩展来写。 2.组件标签只能有一个根节点最外层要由一个大的div包裹。3.组件名在js中是使用驼峰式在html中改为以横线 -连接的小写字母。4.组件中的data必须是函数并且必须要return一个对象就是我们的数据对象.这是为了每次调用的时候都是自己独立的数据而不是共享的。【根组件(vue实例)中的data是对象而data如果是对象的话组件复用时使用的data数据是共用的一份更改其中一个其他的也会受到影响。】//全局注册 没有挂载点 多了一个template属性
Vue.component(组件名,{template:html代码data(){return {数据 }},//data必须是函数返回一个对象保证每个组件使用的都是自己独立的值。methods:{},computed:{},watch:{}
})//局部注册 将配置项单独声明在哪用就在哪注册 在vue实例/其他组件中使用components:{组件名:组件配置项}注册
//也可以组件套组件 在配置项的template中使用另一个组件然后在里面使用components注册前提是要使用的另一个组件必须已经在前面定义好了//组件配置项之后大部分不会改了用const声明
head/headconst 组件配置项名/组件名 {template: html代码,data(){return {数据}},methods:{},computed{},watch:{}}new Vue({el: #app,data: {},components: {//组件名:组件配置项 一般将组件名和组件配置项写成一样head}})!-- 全局注册的使用在同一个html文件中 --
div idappmy-com/my-commy-com/my-com/divscript//全局注册Vue.component(myCom, {template: divh1 clickchange :styleobj{{msg}}/h1a :hrefurl{{info}}/a /div,data() {return {msg: 这是vue组件全局注册方式,url: http://www.baidu.com,info: 百度一下你就知道,obj: { color: red }}},methods: {change() {this.url http://jd.comthis.info 京东}!-- 两个组件之间的内容互不干预点谁改的就是谁的另一个组件内的内容不受影响 --}})
/script!-- 局部注册的使用 --
div idapp!-- mycom/mycom --mycom2/mycom2/divscript//局部组件的配置项const mycom {template: divh1{{msg}}/h1 h2{{gender}}/h2/div,data() {return {sex: 1,msg: 这是局部注册的第一个组件}},computed: {gender() {return this.sex 1 ? 男 : 女}}}const mycom2 {template: divh1{{msg}}/h1 h2{{gender}}/h2mycom/mycom/div,data() {return {sex: 1,msg: 这是局部注册的第二个组件}},computed: {gender() {return this.sex 1 ? 男 : 女}},components: {mycom}}new Vue({el: #app,data: {},components: {mycom2}})
/script
组件之间的传值–简单场景下 1.父 - 子 props 组件之间产生嵌套关系 如点击父组件让子组件的显示属性发生变化 把父组件的数据传给子组件让在子组件中显示 2.子 - 父 自定义事件 更改子组件的数据父组件的内容也发生了变化 3.同级先子给父再父给子 父-子、子-父传值这种方法只适用于简单情况复杂的子组件之间传值使用vuex来实现。 判断是不是父组件与子组件之间的关系父组件中要用到子组件的标签。 组件之间传值的三种情况
**1.父-子props(属性) **
注意子组件不允许直接修改父组件传入的属性如果需要更新(更改)这个属性只能让父组件重新传。
孙子级的组件想要使用根组件的数据要通过中间组件的传递中间组件既要接收数据又要传出数据。**用法**类似带形参的函数定义及调用的过程共有3步函数定义时的形参形参在函数中的使用调用函数时传递实参。
1.子组件内部要接收属性并规定属性的使用场景.
2.父组件中使用子组件要给属性传实际的数据. 父-子传值案例 div idapp my-com :amsg :bchange :carr/my-com/div script const myCom{props:[a,b,c],//在子组件中加props配置项其值为数组类似函数定义时的形参可以有多个template:divh1 clickb我是组件{{a}}/h1ulli v-foritem in c{{item}}/li /ul/div,//在子组件中使用定义的属性}new Vue({el:#app,data:{box:welcome,msg:我是父组件的数据,info:哈哈,arr:[1,2,3,4]},methods:{change(){console.log(this)//this指向还是父组件}},components:{//组件名:组件配置项myCom}})!-- 父-子案例孙子级组件使用根组件的数据 通过中间组件传递数据--
bodydiv idappmy-com :childmsg/my-com/divscriptconst myCom1 {props: [child],template: h2孙子级组件{{child}}/h2,}const myCom {props: [child],template: divh1子组件{{child}}/h1myCom1 :childchild/myCom1/div,components: { myCom1 }}new Vue({el: #app,data: {msg: 我是根组件的数据},components: { myCom }})/script/body
2.子-父自定义事件
vue是单向数据流只能从父-子但由于实际需要子-父因此解决方法时需要自定义事件。
在html中使用子组件时不能给子组件加类、id、样式和指令这些都是用于实际存在的标签的而我们自定义的组件并不是实际存在的编译后就换成了组件中的 template 中的内容因此不能给子组件加之前规定好的属性和指令。但是可以加自定义的属性和事件就像上面的在子组件中使用 props 接收自定义属性像下面的使用 $emit 主动触发自定义事件。
自定义事件需要使用$emit(自定义事件名,参与方法的参数)主动触发。this.$emit()用于主动触发绑定在本组件标签上的自定义事件。
子-父传值过程在子组件上标签绑定一个自定义事件自定义事件的函数值是定义在父组件的methods中的在函数里面是要有参数的将接受的参数赋给父组件的数据在子组件中需要$emit主动触发自定义事件给子组件中的内容绑定一个click事件在子组件的click事件函数中主动触发并把自己要传给父组件的数据作为参数传到父组件的自定义事件函数中。(子组件的自定义事件的函数是写在父组件的methods中的类比于h1 clickchange/h1的click事件。) 子父传值案例 div idapp h1 我是父组件{{msg}}/h1 child abcfn/child/div
scriptconst child{data(){return{info:我是子组件的数据}},template:h1 clickchange我是子组件/h1,methods:{change(){//$emit用于主动触发绑定在本组件标签上的自定义事件,其他组件标签上的自定义事件是无法触发的 //$emit(自定义事件名,参与方法的参数)this.$emit(abc,this.info)}}}new Vue({el:#app,data:{msg:},components:{child},methods:{fn(m){this.msgm}}})
/script 组件间传值小案例–对话框显示与关闭
点击【显示】按钮显示出来对话框再点击对话框中的【关闭】按钮关闭对话框。使用v-show来控制对话框的显示与隐藏。
由于是点击父组件中的【显示】按钮让子组件显示所以将控制对话框是否显示的变量定义在父组件中父-》子传值 props。
当子组件中的【关闭】按钮点击时需要让父组件重新把控制对话框是否显示的变量传过来子-》父传值 自定义事件。 div idappdiv classdialogbutton clickshowtrue显示/buttonmodal :visibleshow closeclose/modal/div/divscriptconst modal {props: [visible],template: div classmodal v-showvisiblebutton clickclose关闭/button /div,methods: {close(){this.$emit(close)}}}new Vue({el: #app,data: {show: false},components: {modal},methods:{close(){this.showfalse}}})/script
关于props
注意属性名在js中定义的时候如果由多个单词组成要采用驼峰式命名
在html 里使用的时候要改为短横线连接
例如: props:[myAttr]xu-button my-atrr属性我是按钮/xu-button 1.数组的形式 props:[type,round],2.对象的形式 限制属性值的类型 props: {//属性名:属性的类型 title: String,likes: Number,isPublished: Boolean,commentIds: Array,author: Object,callback: Function,time:Date,s:Symbol,contactsPromise: Promise // or any other constructor
}3.传入的是布尔值的情况 !--只传入属性名没有属性值说明传入的是布尔值true--
blog-post is-published/blog-post!--此时要求属性必须规定是布尔值类型--
props:{ isPublished:Boolean
}, 4.复杂写法 props:{//该属性有可能是多种类型propB: [String, Number],// 必填的字符串propC: {type: String,required:true}, // 带有默认值的数字propD: {type: Number,default: 100},
}8.插槽
插槽slot/slot其实就是给组件标签中的内容(可以是多个标签)预留的位置
普通插槽
对于普通插槽如果组件模板中有多个插槽那么组件中标签的内容将会复制插入到多个插槽中多个插槽中的内容都是一样的。 div idapp my-headh1hello/h1/my-head/divscriptvar head {template: divslot/sloth1 {{msg}}/h1/div,data: function () { return { msg: 我是头部 } },}new Vue({el:#app,//挂载点components:{myHead:head}})/script
具名插槽 v-slot
想要使用多个插槽让组件标签中的指定的内容对应到不同的插槽中去。在组件使用时的插槽模板中使用 v-slot:插槽名来区分不同的插槽然后在组件内部的模板中使用slot标签的name 属性 slot name插槽名/slot。
v-slot** 只能用于**组件或 template 上因此要将组件标签的内容使用template/template标签包起来。
v-slot 简写为#.
在普通插槽中也有name属性只是name属性默认为deafult.
bodydiv idapp my-head!-- v-slot只能用于组件或template上 --template v-slot:before !-- v-slot:可以缩写为# --h1hello/h1/templatetemplate #afterh1world/h1/template/my-head/divscriptvar head {template: divslot namebefore/sloth1{{msg}}/h1slot nameafter/slot/div,data: function () { return { msg: 我是头部 } },}new Vue({el:#app,//挂载点components:{myHead:head}})/script/body
编译作用域插槽 如果插槽模板(组件内标签的插槽模板)中想使用该子组件内部的数据在正常情况下使用的都是根组件中的数据如果想要使用子组件中的数据首先需要在组件模板的插槽中定义 :属性名属性值 或 v-bind:属性名属性值 然后在组件调用的地方插槽通过 #插槽名“props”接收属性 props代表所有属性的集合是一个对象。在插槽模板中使用的时候直接按照对象的格式调用即可props.属性名。 通过 #插槽名“props”接收属性的时候也可以直接解构赋值 #插槽名{属性名} bodydiv idappmycomtemplate #beforepropsh1{{props.abc}}/h1h2{{props.def}}/h2!-- 如果要使用组件中的数据不多的话也可以用解构赋值来做 --!-- template #before{abc,def}h1{{abc}}/h1h2{{def}}/h2 --/templatetemplate #afterp123456/p/templatetemplate #middleh3就是开心/h3/template/mycom/divscriptconst mycom {data(){return{msg:我是子组件的数据1,info:我是子组件的数据2}},//属性名是abc。属性值是变量msg的内容template: divh1我是组件/h1 slot namebefore :abcmsg :definfo/slotulslot namemiddle/slot li1/li li2/li /ul slot nameafter/slot /div}new Vue({el: #app,components: {mycom},data:{msg:我是父组件}})/script/body
9.组件的生命周期
生命周期组件从创建到销毁的完整过程。
生命周期(钩子)函数在特定的时间节点会自动触发的函数。 //只要是组件就有生命周期这些生命周期函数所在的地方与配置项同级beforeCreate(){console.log(组件创建之前)},created(){console.log(组件创建完毕)},beforeMount(){console.log(组件渲染前)},mounted(){//我们就能看到组件渲染在页面上了可以在页面上看到DOM结构了console.log(组件挂载完毕)},//1.页面重新渲染的时候触发页面视图中没有用到的数据发生更新时并不会触发组件更新的钩子函数因为vue是数据驱动视图的。//2.子组件用到的属性渲染到了视图中 //就以视图是否发生更新为依据判断是否触发了更新beforeUpdate(){//首次不执行数据更新可以算是组件更新了console.log(组件更新前)},updated(){//首次不执行console.log(组件更新后)},beforeDestroy(){//首次不执行console.log(组件销毁前)},destroyed(){//首次不执行console.log(组件销毁后)},//下面两个是被缓存的组件特有的生命周期activated(){//组件被kepp-alive缓存后被重新激活时使用即从详情页返回列表页时}deactivated(){//缓存组件失活时使用即从列表页转向详情页的时候}10.动态组件
基础知识
componet is组件名/component标签是vue自带的标签代表的是一个组件至于代表的是哪一个组件由它的属性is的值来决定的而is的值是可以以变量来变化的从而实现组件的切换。
div idappcomponent :istitle/componentbutton clickchange(2)按钮/button/divscriptvar coma {template: divh1我是第一个组件/h1/div,}var coma2 {template: divh1我是第二个组件/h1/div,}var coma3 {template: divh1我是第三个组件/h1/div,}var app new Vue({el: #app,data: {tab: mycom,title:mycom},components: {mycom: coma,mycom2: coma2,mycom3: coma3,},methods:{change(n){this.titlemycomn}}})/script
案例使用动态组件实现选项卡的切换
!-- 动态组件实现选项卡的切换 --
!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlescript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptstyle* {margin: 0;padding: 0;}.tab {float: left;width: 100px;height: 50px;background-color: gray;margin-right: 8px;line-height: 50px;text-align: center;color: #fff;}li {list-style: none;}.act {background-color: red;}.bgc {width: 424px;height: 200px;background-color: pink;}/style/headbody!-- 作业选项卡的内容用组件来表示 动态组件实现选项卡作业 --div idappdiv v-for(item,index) in list :idindex classtab clickchange(index) :class{act:numindex}{{item}}/divdiv styleclear: both;/divcomponent :ismycom/component/divscriptconst tem divul classbgcli v-for(item,index) in cont :idindex{{item}}/li/ul/divconst myCom1 {template: tem,data() {return {cont: [我是体育新闻1, 我是体育新闻2, 我是体育新闻3, 我是体育新闻4]}}}const myCom2 {template: tem,data() {return {cont: [我是科技新闻1, 我是科技新闻2]}}}const myCom3 {template: tem,data() {return {cont: [我是电影新闻1, 我是电影新闻2, 我是电影新闻3]}}}const myCom4 {template: tem,data() {return {cont: [我是娱乐新闻1, 我是娱乐新闻2, 我是娱乐新闻3, 我是娱乐新闻4, 我是娱乐新闻5]}}}new Vue({el: #app,data: {list: [体育新闻, 科技新闻, 电影新闻, 娱乐新闻],num: 0,mycom: myCom1,},methods: {change(index) {this.num indexindexthis.mycom myCom index}},components: {myCom1, myCom2, myCom3, myCom4}})/script/body/html
11.综合案例使用vue实现购物车
使用计算属性较多基本都是依赖于数组中的是否选中的状态来操作的写成计算属性这样只要依赖的数据发生了变化就会自动重新调用不用像写成函数那样每次都需要主动去调用了。 注意点 我们所需要的数据都是从后端返回的然后赋值给list的而不是我们直接在list中写的这些数据只要是我们需要的都可以从后端传过来。给数据list的每一项加上一个id符合实际项目。在给data中的变量定义时除了后端传过来的数据先尽量不要写其他的变量定义可以通过计算属性实现的就使用计算属性来实现。方法中需要的参数是依赖于data中的数据的而可以写成计算属性来实现。从后端传过来的数据中是否选中是布尔值的形式这样的情况时可以和后端交涉将其定为我们的圆圈图片的路径。如果还是布尔值的形式的话就采用计算属性判断是否选中的情况来定路径。计算属性中想要用传过来的参数则要return 函数在return的函数中写逻辑。直接在img的src中用三目运算符判断。需要知道操作的是哪个商品需要在函数中传参数尽量传index不要传item。已选数量取决于数组中selecetd的个数直接用计算属性来做即可不用单独再在data中加一个变量表示已选数量。使用过滤函数filter()返回的结果是一个满足条件的数组。 “已选(1)” 和 “全选” 使用es6的模板字符串 拼接字符变量用 ${变量名}表示。 计算总价写成计算属性不写成函数。因为总价是依赖于数组中的单价和数量的只要它们有所变化就会重新执行计算总价的函数。这样只需要在总价的地方执行计算属性如果写成函数其他像加减和选中圆圈会改变总价的情况时每次都得再去调用计算总价的函数。先写每个需要点击的基本功能就行其他的使用计算属性逐步基本能实现。全选按钮取决于数组中selected的数量还是使用计算属性来实现。使用every()每一项的selected都是true时是选中状态否则就是未选中状态。结算按钮的灰色状态使用some()函数只要数组中有selected是true的就变为正常。 11.该案例中使用计算属性比较多是因为数据之间的关联性较强基本都是取决于是否选中的状态。这些计算属性写成函数也能实现但是性能肯定是没有计算属性好的 。 如果我们要做的操作时想要改变data中的数据的值使用的时methods方法如果我们要做的操作所需要的值是依赖于data中的数据使用的是computed计算属性。 arr.filter((item){return 条件
})
//返回的是一个满足条件的新数组arr.every((item){return 条件
})
//返回的是布尔值数组中的每一项都满足条件时返回true否则返回false arr.some((item){return 条件
})
//返回的是布尔值只要数组中有满足条件的就返回true,否则返回flase老师写的计算属性依赖
!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlescript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptstyletable {width: 500px;margin: 0 auto;border-collapse: collapse;text-align: center;height: 50px;}td {border: 1px solid;}/style/headbodydiv idapptable!-- 表头行 --trtd选择/tdtd名称/tdtd价格/tdtd数量/tdtd操作/tdtd删除/td/tr!-- 商品行 --tr v-for(item,index) in list :keyitem.idtdimg :srccheck(item) clickselect(index)/tdtd{{item.name}}/tdtd{{item.price}}/tdtd{{item.count}}/tdtdbutton clickadd(index)/buttonbutton clicksub(index)-/button/tdtdimg srcimages/delete.png clickremove(index)/td/tr/tabletabletrtdimg :srctotalSelect clickselspan{{total}}/span/tdtd总计{{price}}元/tdtdbutton :disableddeal结算/button/td/tr/table/divscript// 要修改data中的数据用方法依赖data中的数据做之后的操作用计算属性new Vue({el: #app, data: {list: [{ id: 2001, name: iPhone14, price: 10000, count: 1, selected: false },{ id: 2002, name: 粉底液, price: 300, count: 1, selected: false },{ id: 2003, name: ps5, price: 5000, count: 1, selected: false },{ id: 2004, name: 键盘, price: 400, count: 1, selected: false }],},computed: {check() {return (item) {return item.selected ? images/selected.png : images/unselected.png}},//4 已选数量 依赖于数组中selected的数量 使用计算属性//使用filtet筛选函数 筛选出selected为true的项组成新数组total() {let len this.list.filter((item) {return item.selected true}).lengthreturn len this.list.length ? 全选 : 已选(${len})个},//5 全选圆圈按钮 是否切换成勾取决于selected的数量totalSelect() {return this.list.every((item {return item.selected true})) ? images/selected.png : images/unselected.png},//6 计算总价//使用filter函数过滤出elected为true的项组成新数组再对新数组的价格和数量做操作price() {let arr this.list.filter((item) {return item.selected true})let total 0;//总价for (let i 0; i arr.length; i) {total arr[i].price * arr[i].count}return total},//7 结算按钮 取决于selected的数量只要有selected为true的就改变属性否则不变deal() {return this.list.some((item {return item.selected true})) ? false : true}},methods: {//1 选择圆圈的切换select(index) {this.list[index].selected !this.list[index].selected},//2 加减按钮add(index) {this.list[index].count},sub(index) {if (this.list[index].count 1) {this.list[index].count--}},//3 删除按钮remove(index) {this.list.splice(index, 1)},//8 点击全选按钮 要改变数组中的selected值//先通过判断原来是否全选中如果是则改为全部未选中//否则改为全部选中//不能简单的将selected取反sel() {let len this.list.filter((item) {return item.selected}).lengthif (len this.list.length) {for (let i 0; i this.list.length; i) {this.list[i].selected false}} else {for (let i 0; i this.list.length; i) {this.list[i].selected true}}}}})/script/body/html
自己写的方法主动调用
!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlescript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptstyle#app {width: 800px;margin: 100px auto;}.product {border: 1px solid;padding: 20px;}.pro_name {font-weight: bold;}.pro_price {color: red;font-size: 20px;}.total {margin-top: 100px;}.deal {width: 80px;height: 30px;}/style/headbodydiv idappdiv v-for(item,index) in list :idindex classproductimg :srcproSelect(item) clickselect(item)span classpro_name{{item.name}}/spanspan classpro_price{{item.price}}/spanbutton clickdecCount(item)-/buttonspan{{item.count}}/spanbutton clickaddCount(item)/buttonimg srcimages/delete.png clickdeletePro(index)/divdiv classtotalimg :srctotalSrc clicktotalSelectspan{{allSelect}}/spanspan{{totalPrice}}/spanbutton classdeal :disableddis结算/button/div/divscriptnew Vue({el: #app,data: {list: [{ name: iPhone14, price: 10000, count: 1, selected: false },{ name: 粉底液, price: 300, count: 1, selected: false },{ name: ps5, price: 5000, count: 1, selected: false },{ name: 键盘, price: 400, count: 1, selected: false }],totalSrc: images/unselected.png,//全选圆圈totalCount: 0,//已选商品数量totalPrice: 0,//商品总价dis: true,//结算按钮不可用},methods: {//1 商品数量加减//如果该商品已选中点击加减按钮后商品数量、总价发生变化//如果该商品未选中点击加减按钮后商品数量发生变化。decCount(item) {if (item.count 1) {item.count--}if (item.selected) {this.price()}},addCount(item) {item.countif (item.selected) {this.price()}},//2 商品是否选中的圆圈//如果原来圆圈未选中点击之后选中按钮、已选数量、总价发生变化//如果原来的圆圈选中点击之后选中按钮、已选数量、总价发生变化//如果点击之后选中的圆圈数量等于商品数量全选按钮选中修改完善之后可以使用计算属性来实现//只要有商品选中结算按钮恢复状态select(item) {let proNum this.list.length;//商品数量item.selected ? this.totalCount-- : this.totalCountitem.selected !item.selectedthis.price()this.totalSrc this.totalCount proNum ? images/selected.png : images/unselected.pngif (this.totalCount 0) {this.dis false}},//3 计算总价:找到选中的商品总价单价*数量//计算总价的功能最好使用计算属性来实现。price() {let total 0;//总价for (let i 0; i this.list.length; i) {if (this.list[i].selected) {total this.list[i].count * this.list[i].price}}this.totalPrice total},//4 删除按钮//都要做的操作是删除该条商品记录//如果删除的是选中的商品这一条商品记录消失、已选商品数量、总价发生变化//如果删除的是未选中的商品这一条商品记录消失、判断是否是否全选了商品//注意删除操作和其他操作的执行顺序deletePro(index) {if (this.list[index].selected) {this.totalCount--}this.list.splice(index, 1)this.price()//判断删除后是否全选let proNum this.list.length;//商品数量this.totalSrc this.totalCount proNum ? images/selected.png : images/unselected.png},//5 全选按钮//先判断原来的选中状态的数量//如果原来就是全部选中全选按钮、商品选中按钮总价变为0已选数量结算按钮不可点击//如果原来不是全部选中全选按钮、商品选中按钮总价发生变化已选数量结算按钮可点击totalSelect() {let proNum this.list.length;//商品数量//原来已经全部选中if (this.totalCount proNum) {for (let i 0; i this.list.length; i) {this.list[i].selected false}this.totalSrc images/unselected.pngthis.totalPrice 0this.dis truethis.totalCount 0} else {for (let i 0; i this.list.length; i) {this.list[i].selected true}this.totalSrc images/selected.pngthis.price()this.dis falsethis.totalCount proNum}}},computed: {//计算属性后台传过来的是是否选中而我们需要渲染的是选中和未选中的图片proSelect() {return function (item) {return item.selected ? images/selected.png : images/unselected.png}},//全部选中时文本由“已选几个”变为“全选”allSelect() {let num this.list.length;//商品总数量return this.totalCount num ? 全选 : 已选( this.totalCount )}}})/script/body/html
12.Vue脚手架
下载node.jsvue/react是依赖于node环境的也能用于写后端。在官网上下载长期支持版本一直点击下一步安装即可。
检验node是否安装完成搜索cmd打开命令提示符输入node -v 能显示出版本号则表示安装成功。输入npm -v能显示出版本号则表示可以使用npm。
npm包管理工具想要下载什么包直接用npm下载不用再自己找了。包文件夹。
下载包的方法npm install 包名
不用再像以前一样引入vue文件了新建一个“脚手架”的文件夹在脚手架的文件夹里在上面的路径中输入cmd就直接跳转到了脚手架文件夹所在的路径的命令提示符输入npm install vue就会自动下载相应的包到脚手架的文件夹下。 什么是脚手架 Vue脚手架是Vue官方提供的标准化开发工具(开发平台),它提供命令行和UI界面,方便创建vue工程、配置第三方依赖、编译vue工程。 如果没有脚手架我们要如何搭建项目超级麻烦幸好我们现在可以使用脚手架直接安装搭建项目简单又方便 通过npm init初始化项目生成项目配置文件package.json包名cli其他的内容直接回车即可。安装webpack和脚手架 npm install webpack webpack-cli -D 配置ES6/7/8转ES5代码 npm install babel-loader babel/core babel/preset-env -D 创建webpack.config.js文件配置webpack安装html-webpack-plugin依赖 npm install html-webpack-plugin -D 安装vue-loader npm install vue-loader 安装 vue-template-compiler npm install vue-template-compiler 安装 cache-loader 用于缓存loader编译的结果 npm install cache-loader 安装less loader 安装sass-loader 安装style-loader file-loader url-loader postcss-loader autoprefixer安装webpack-dev-server安装 vue-router vuex axios配置webpack… 脚手架的安装在脚手架文件夹下的命令提示符中输入 npm install -g vue/cli -g 表示全局安装可以在任意文件夹下运行否则只能在当前文件夹下运行验证脚手架是否成功安装在脚手架文件夹下的cmd中输入vue/cli --version查看脚手架的版本号利用脚手架创建项目并进行配置方法在脚手架的文件夹下的cmd中输入以下 vue create 项目名字(用英文不要中文)手动选择风格Manually select features*代表选中上下键切换项空格切换*选中我们需要选中Babel(es6转码成es5)、Router、CSS Pre-processors、Linter/Formatter代码审查。(现在没装的之后还可以装)。
像TS(vue3用)、vuex(之后用)可以再用的时候再装方法之后再讲
之后安装的方法npm install vuex.
忘记之前是否已经安装过在package.json中查看依赖是否有。选择vue版本:2.xUser history mode for router?Y 默认使用的是Hash mode但我们现在要使用history模式比较好看。Pick a CSS pre-processor预处理器LessPick a linter/formatter config代码审查工具:ESLint with error prevention onlyPick additional lint features什么时候进行代码风格检查:Lint on saveWhere do you prefer placing config for Babel在哪个地方去存一下配置文件in package.jsonSave this as a preset for future project?N等待安装...直到 Successfully created project mypro-------------从下面是打开项目
Get started with the following commands:如果是紧跟着上面的步骤则使用下面的(1)进入mypro文件夹下否则直接打开mypro文件夹里在里面的地址栏输入cmd转到mypro文件夹下。
1cd mypro 转到mypro目录下或直接到mypro的目录中cmd
2等待安装...直到 Successfully created project mypro 运行服务器必须是在项目mypro的文件夹里生成地址
直接在浏览器中输入地址进入到项目中不要关闭命令行否则就会关闭服务器或者直接将我们的mypro文件夹拖动用vscode打开在终端中打开直接输入 npm run serve 项目文件解读 **node_modules:**项目依赖的核心模块该文件夹一定不要动且该文件夹很大一般传输项目时不压缩发送该文件夹。----------一定不要修改
**public**存放静态文件。-----------一般情况下也不需要修改
favicon.ico里面存放的是地址栏上面的图标。 index.html项目中唯一的html文件里面没有什么内容只是提供一个挂载点。vue是一个单页面应用SPA。
src最重要的文件我们要编写的代码基本都位于src目录下。
**main.js:**是项目的入口文件。之后的项目中就只有js文件了在项目中只需要引入这一个main.js文件就行了其他的js文件都会通过不同的渠道导入到main.js中来否则js文件就会不生效。该main.js文件在唯一的html文件中挂载没有在html文件中引入是底层自动实现的。----------一般是不需要更改的在该文件中有创建vue实例
import Vue from vue //引入我们的vue文件包,只要是没有./路径的引入的就是node_modules中的核心模块
import App from ./App.vue //引入App.vue组件 ./代表当前目录
import router from ./router //如果直接写的是文件夹的名字默认引入的是该文件夹下面的index.js文件 等同于import router from ./router/index.js
Vue.config.productionTip false //关闭生产环境的错误提示,不然在用户使用的时候发生Bug会出现提示
new Vue({router,render: h h(App)
}).$mount(#app)//该main.js文件在唯一的html文件中挂载没有在html文件中引入是底层自动实现的。与以往学习的vue实例的不同点1、没有使用el:#app挂载点$mount(#app)也是挂载点的写法二者的实现效果相同。区别原来是配置项的形式现在是主动方法可以主动调用。2、routervue路由路由也是vue的配置项之前也有只是没讲而已。router:router3、没有data、methods根实例只是用于创建实例不用于处理逻辑渲染数据写逻辑不在这写用组件。4、需要用到组件 App.vue但没有注册组件render函数接收App组件。关于render函数接收vue组件创建元素渲染到页面中 把App组件渲染出来App组件是项目中最大的组件。render: h h(App)的原理等同于 :hrender{return h(App)}等同于 render:function(h){return h(App)}等同于render:function(createElement){return createElement(App)}
**App.vue**单文件组件在里面可以写组件所需的html页面、样式和js逻辑。要记得默认导出否则main.js引入就失败了。安装了Vue VSCode Snippets插件之后快捷创建模块vbase-css
!-- 生成的模板 --
templatediv/div/templatescriptexport default{//这里是组件中的data、methods、computed等}
/scriptstyle scoped/style
assets文件夹一般用来放静态图片资源、css3字体等。components文件夹里面默认的.vue文件组件可以删除。一般用来存放公共布局组件像侧边栏、顶部导航、尾部等页面都有的。router文件夹一般用来存放路由相关的文件如果之前没有安装路由则该文件夹就不会存在了。views文件夹里面默认的.vue文件组件可以删除。创建的新页面一般都放在里面像经常切换的页面的功能组件
**.gitignore**git上传需要忽略的文件格式。编辑器带的配置不要上传到仓库。
**babel.config.js:**主要用于在当前和较旧的浏览器或环境中将ES6代码转化为向后兼容的版本。---------不需要更改
jsconfig.json: -jsconfig.json文件指定根目录和JavaScript服务提供的功能选项。
**package-lock.json:**锁定安装模块的版本号。在安装依赖的时候避免安装的是不同的版本导致的问题。
**package.json:**模块基本信息依赖的模块名称版本号。-----不用自己改
生产环境上线时的环境、开发环境程序员开发过程中的使用的、 测试环境测试用的。
生产依赖项目上线时还需要的东西、开发依赖开发过程中使用但在上线的时候就不用了
调试代码时不发node_modules文件夹直接在终端执行npm install 就会依据package.json安装相应的依赖安装的速度是很快的在网上或公司中拿到的项目基本都是没有node_modules文件夹需要自己安装的。
package.json文件中的 “scripts中定义了一系列的命令像下面中的serve如果改为了dev”则启动项目的命令就变为了 npm run dev实际上是让npm 帮助我们去运行vue-cli-service serve这个是可以根据公司做修改的。 **README.md:**对项目的主要信息进行描述使用说明。
**vue.config.js:**vue的其他配置与webpack相关的。关于请求代理的部分就写在这里。
//vue.config.js文件
const { defineConfig } require(vue/cli-service)
module.exports defineConfig({transpileDependencies: true,//跨域的解决方法请求代理的配置devServer: {proxy: {/api: {target: https://api.binstd.com/recipe/search, //每次需要更改的地方changeOrigin: true,//允许跨域pathRewrite: {^/api: //请求的时候使用这个api就可以}}}}// devServer请求本地/开发服务器// proxy/ˈprɒksi/ 代理// target存放用来想请求的路径地址// pathRewrite路径重写// ^/api ^代表以什么开头以/api开头重写为空因为在真正发送请求的时候路径中是不存在/api的// 用 /api来代替想要请求的地址
}) 13.单文件组件App.vue
单文件组件一个文件就是一个组件都是以.vue结尾的允许正常的编写html,支持模块化的样式。自动刷新
如果没有单文件组件的话
1.多个组件写在一个页面中乱
2.没有html提示没有语法高亮
3.样式的模块化很明显被遗漏了
views/pages视图文件夹里面一般用来存放创建的.vue新页面一–像经常切换的页面的功能组件components文件夹一般用来存放公共布局组件(像侧边栏、顶部导航、尾部等页面都有的router文件夹一般是存放路由相关的文件。 单文件组件使用的注意点 1、要记得默认导出。 2、在要使用的页面中要导入相同路径下要加./ 3、在导入的文件中要注册要使用的组件。 4、导入时的组件名和文件名都要求是多个单词组成的并且是大驼峰式的写法但是在html中使用组件时改为“-”。默认导出的文件在导入时的文件名可以是任意的。 5、样式组件化生效在style标签中加scopedstyle scoped/style表示样式只在当前组件中生效。 scoped是因为在不同的页面生成不同的随机值 使用过程步骤 导出/其他子组件1、多个单词的大驼峰式的命名2、默认导出(快捷键创建的模板中带有自动导出) APP.vue引入/在需要该子组件的组件中1、导入(由于是默认导出文件名可以是任意的多个单词组成的大驼峰式命名)注意①引入文件的路径的格式②当前路径下要加’./‘③文件名不加引号④导入多个组件时每次导入的语句后要加’;标点符号2、注册(组件名就是引入的文件名3、在html中使用子组件(字母之间用‘-’代替) !-- 子组件导出 --
templatedivh1{{msg}}/h1/div/templatescriptexport default {data(){return {msg:我是Info子组件}}}
/scriptstyle scopedh1{color: yellow;}
/style
!-- App.vue文件导入 --
templatedivh1{{msg}}/h1!-- 3 使用 --my-info/my-info/div/templatescript//1 导入import MyInfo from ./views/MyInfo.vueexport default {data(){return {msg:我是App根组件}},//2 注册components:{MyInfo}}
/scriptstyle scopedh1{color: blue;}
/style
重新启动项目的方法在终端控制台中输入ctrlcY再重新启动服务器npm run serve.