1.vue全家桶:vuejs+vue-roter+vuex+axios,vue-router是单页开发中跳转不同页面,vue-cli是构建工具
2.vue两个核心点:
(1)双向响应式数据数据变化 数据变化时->视图更新
(2)ui页面映射为组件树,组件可维护和复用
3.安装方式
(1)cdn网址引入方式
(2)npm方式:node package manager
npm初始化(npm init )时不能中文 大写 特殊符号,然后生成
package.json
⦁ 4. 小胡子语法{{}} 可以放表达式、取值、赋值等
⦁ 5.vue的指令
⦁ (1) v-model用于表单元素,value、checked、selected等属性一般会被vue忽略掉
(2)v-text 更新textContent等价于v-text,即: = {{msg}}
(3)v-once只绑定一次,当数据再次变化,v-once所在容器的所有内容都不会再刷新
eg: <span v-text="msg"></span>
钱:{{money}}
<div v-once>
once:
<span v-text="msg"></span> 只渲染一次,后面不会变化
钱:{{money}}
</div>
(4)v-html把html字符串当成html渲染,而非普通的字符串
eg:p: <span v-html="p"></span>
data:{ p:"<p>这是html</p>"}
(5)v-for循环,相对于js的innerHtml会操作DOM,性能比较低,v-for会复用原有结构,要 循环哪个元素就在哪个上面加v-for ,语法为site in sites / (site,index) in sites
eg: 循环一个数组中数组
<li v-for="(person,index) in arr">{{person.name}} {{index+1}}
<ul>
<li v-for="(c,index) in person.color">
{{index+1}}:{{c}}
</li>
</ul>
</li>
arr:[{name:'zsx',color:["yellow","green"]},{name: "lisi",color:["yellow","green"]},
{name:"wangwu",color:["yellow","green"]}]
v-for循环其他:<li v-for="c in 'string'">{{c}}</li>循环字符串
<li v-for="c in 5">{{c}}</li>数字从1-30
<li v-for="(value,key,index) in obj"> {{value}}:{{key}}</li> 对象
(6)v-show和v-if的区别 v-show :v-if将元素干掉了,这种需要重新构建DOM树, v-show只是改变元素的display属性,后者效率更高
6.vue 数据响应的变化,响应变化的原理是一个一个属性或者值加get和set
(1)使用对象属性时必须 初始化,否则无法做到响应式
eg: 这是a: {{a.word }} data:{a:{}} //页面不报错,但是word值变化时页面不会响应而渲染,不初始化就不会有get和set
修改: data:{a:{word:‘’}}
(2)改变数组时响应式变化,得使用变异方法:pop,push ,shift和unshift等
eg: data{arr:[1,2,3,4,5]}
错误写法:vm.arr[1]=0 vm.arr.length=3,这样不会给数据加getset,因此无法做到响应渲染
7. 事件使用v-on绑定
(1)方法也可以放data中,但是一般放到methods中
(2)v-on可用@替代
(3)methods和data中的数据名称不能一样,否则冲突报错
(4)vue中调用方法时加括号和不加括号的区别在于,加括号表示用户要传参,那vue就不会自动将事件实例传入,不加括号则vue会自动给一个event事件的实例
eg:
//methods中的this指向vue实例
<div @click="fn($event,1)">点我吧求你了</div>
methods:{
fn(event,a){alert(a)
console.log(event)} //vue自动传参的,如果即想自己传参又想使用event,则$event手动传入
}
8.v-bind 动态绑定标签特性,如动态更新class或者动态更新img的src等,可用:冒号简写
eg:<td><img :src="product.productCover" :title="product.productInfo"/>{{product.productName}}</td>
9.vue的修饰符
(1)表单修饰符
v-model.number让输入框的值变成数字类型,v-model.lazy将v-model实时更新的input事件转变为change事件,v-model.trim自动过滤 输入的首尾空白字符
(2)事件修饰符 stop prevent capture once selft等
事件修饰符 举例 stop=stopPropagation prevent=preventDefault
eg:
<!--stop阻止事件继续传播,包括向上(冒泡)和向下的传播-->
<div class="son" @click.stop="son"></div>
<!--capture捕获内部元素的冒泡-->
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
这里会先执行father函数,然后再执行grandSon,而son不会执行,因为grandSon已经阻止冒泡了,如果capture后面再加.stop,则只会执行father,因为stop阻止事件向下grandson传播了
<div class="father" @click.capture="father">
<div class="son" @click.stop="son">
<div class="grandSon" @click.stop="grandSon"></div>
</div>
</div>
不会跳转
<a href="http://www.baidu.com" @click.prevent="son">百度</a>
<div class="father" @click="father">
<!--once表示只绑定一次,即该事件只执行一次,即便是后面冒泡也会越过该事件-->
<div class="son" @click.once="son">
</div>
</div>
self表示当事件源是自己的时候触发该事件,这样避免因冒泡而影响事件执行
<div class="father" @click.self="father">
10 过滤器,其中的this指向的是window, {{变量|filter1|filter2}},默认第一个参数是管道符前面的结果, 方法传参作为形参的第二个参数开始
eg:<td>{{(product.productCount*product.productPrice)|toFixed(3)}}</td>
filters: {
toFixed(input,param1){ //input是管道符前面内容,3是param1
return '¥'+input.toFixed(param1);
}
}
ps: js中比较时应该使用=和!,箭头函数如果代码多于一行则需要用大括号,return不能省略,如果有返回值的话,一行则可以返回return,自动返回这一行执行的结果
ps:VUE的mvvm模式,绑定的数组一旦变化,其他相关联的数据和方法都会重新执行更新
11.computed计算属性,当依赖的属性值发生改变时会重新取值,而methods在重新渲染时总会调用,计算属性性能会更好,会缓存上一次计算后的值
(1)两者区别举例:
eg:页面:
<td><input type="text" v-model.number.lazy="product.productCount" min="1"></td> //数量
<td>{{(product.productCount*product.productPrice)|toFixed()}}</td> //小计
<td>总计:{{sum()|toFixed()}}</td> //总计,如果手动改数量,小计也会跟着变化,因为每次变动都会重新渲染页面,因此sum()会调用两次
methods: {
sum() {
console.log("调用一次");
return this.products.reduce((sum, p) => sum + p.productCount * p.productPrice
, 0);//累加器,初始值给0
},
},
computed:{
sum () {
console.log("调用一次");
return this.products.reduce((sum,p)=>{ //当写在computed中时,只有当sum属性本次值与上次值不一致时才会调用该get方法,与页面渲染无关系
if(!p.isSelect){
return sum;
}
return sum+p.productCount * p.productPrice;
},0)
}
}
(2)计算属性默认提供get方法,可以手动补充set方法,如果将计算写成函数方式,则默认是get方法
all: { //计算属性当本次值与上一次值有变化时,才会调用对应的get和set方法
//v-model有读的操作,会调用get方法
get(){
console.log("调用get");
return this.products.every((p)=>p.isSelect===true)
},
set(value){
console.log("调用set");
this.products.forEach(p => p.isSelect = (value))
}
}
- axios的ajax请求实例
eg:
⦁ axios发送ajax请求
⦁ getData(){
⦁ axios.get("./result.json").then( (res)=> {
⦁ this.products= res.data;
⦁ }, (error)=> {
⦁ console.log(error)
⦁ })
⦁ }
13.vue动画 通过transition组件包装即可, 使用css过度和动画中自动应用class,或者使用第三方css动画库如Animate.css
(1)基础
eg:过度的几个阶段简介
<transition name="fade">
<div v-show="flag">show再靠</div>
</transition>
/*展示过程中的变化*/
.fade-enter-active{
transition: all 0.5s;
}
/*展示前的属性*/
.fade-enter {
opacity: 0;
}
/*离开前的属性与-leave几乎相同,此时opacity已经是1了*/
.fade-enter-to{
background-color: orange; /*这只是说当过度进入结束时要展示一下背景为orange,最终还是会以元素本身css背景色为准*/
}
/*离开的最终状态 这只是说当过度结束时要展示一下背景为blue,最终还是会以元素本身css背景色为准*/
.fade-leave-to{
background-color: blue;
}
/*离开过程*/
.fade-leave-active{
transition: background-color 2s;
}
(2)animate.css第三方库的使用
i.git手册 https://github.com/animate-css/animate.css/tree/a8d92e585b1b302f7749809c3308d5e381f9cb17
ii.样式中文释义:https://www.cnblogs.com/matd/p/11302014.html
iii.安装 npm install animate.css
iv.目前所有npm下载的包引入都有问题
v使用:必须在每个class上都加上animated类名 然后后面加上具体效果的类名
eg:<transition enter-active-class="animated fadeInLeft" leave-active-class="animated fadeOutRight">
<div v-show="flag">show再靠</div>
</transition>
(3)transition标签只能应用于单个标签,对于多个标签得用transition-group,并需要有一个key,此key应该在元素显示前后不一样,否则就认为没有过度,也不会有过度效果,参考:http://www.qiutianaimeili.com/html/page/2020/06/202068n7nnkc1qfpq.html
eg:
<button @click="getA">展示</button>
<!--key要不同,否则不会有动画效果-->
<transition-group enter-active-class=" animated fadeInUp" >
<div class="box" v-for="(item,index) in arr1 " :key="Math.random()*Math.random()"> //这里的arr1虽然item每次都不一样,但是index始终是0,因为始终只有一个元素{{item}}</div>
</transition-group>
(4)自定义过渡类名 enter-class enter-active-class enter-to-class leave-class leave-active-class leave-to-class
14.全局过滤器,在new实例之前通过Vue.filter(“filterName”,“”)
eg:<div id="app" class="container">
{{12|my()}}
</div>
<div id="app1" class="container">
{{13|my()}}
</div>
Vue.filter("my",my); //全局注册过滤器方法,得在所有vue实例之前注册
function my(data){
return "$"+data;
}
new Vue({
el:"#app1"
});
let vm = new Vue({
el: "#app"
}
)
ps:set方法如果将值赋值给别的属性,并且该属性将该值使用了(消费),那么计算属性本身就不会再get到该值,所以set方法尽量不要用
eg:<input type="text" v-model="msg" style="width: auto" class="col-md-6 form-control" />
<span class="col-md-6 h3" >{{in0}}</span>
computed:{
msg:{
//set方法如果将值赋值给别的属性,并且该属性将该值使用了(消费),那么计算属性本身就不会再get到该值
set(i){
this.in0 = i;
}
}
}
15.watch观察者
(1)computed不支持异步,即只支持实时计算值这种,但是大多数情况下computed是更适合,watch监听器监听值,只要值有变化就会执行
eg:<label>请输入:</label><input type="text" @blur="onb" class="form-control" v-model="q"/> <div>{{a}}</div>
onb(){
setTimeout(()=> this.q = this.q+'zsx' ,5000); //这种异步的a如果跟随q变化,则无法通过计算属性了
},
watch: {
q: function (newV, oldV) { //watch中的属性名要跟被观察的属性一样,也可q(new,old){}
console.log("监听q:"+newV+"--"+oldV);
this.a = this.q.split("").reverse().join(""); //监听q,如果有变化则改变a
}
}
(2)watch中观察哪个值,哪个值变化才会调用,而当未观察的值变化时不会调用,即便是有依赖关系,因此非异步的情况下更倾向于用computed
eg:
<label>请输入firstName:</label><input type="text" class="form-control" v-model="firstName"/>
<label>请输入lastName:</label><input type="text" class="form-control" v-model="lastName"/>
<div>{{a}}</div>
watch: {
firstName: function (newV, oldV) { //只监听firstName,而当lastName变化时a的值不会变,这种用计算属性好
console.log("监听a:"+newV+"--"+oldV);
this.a = this.firstName+this.lastName;
}
}
16.vue中的$
符号表示vue的实例属性,即el和data等,用于与用户属性分开
eg:console.log(vm.$el);//
for(let key in vm.$data){
//遍历对象
console.log(key);
console.log(vm.$data[key])
}
17.template 字符串模板占位符,可以包裹元素,但不会体现在DOM上,v-show 不支持template,因为template不是真正的元素,v-show改变元素的属性也就无从下手,同样style样式也没法使用,只是vue提供的包裹元素的占位符
eg:<template v-for="i in 5" v-if="false">
<label>请输入firstName:</label>
<input type="text" class="form-control" v-model="firstName"/>
</template>
18.vue中元素的key属性,v-for或者v-if等操作dom的标签出现时,vue为了提升性能会就地之前的复用元素,只改变响应元素的节点内容,如果要打断就地复用,则在不想复用的元素上增加key,保证key值不相同
eg:<template v-if="max" >
<label>firstName:</label>
<input type="text" key="2"class="form-control" /> //这里如果不加key,则会v-if操作元素可见时, 会将上下input复用,包括已经输入的内容
</template>
<template v-else>
<label>lastName:</label>
<input type="text" key="1" class="form-control" />
</template>
19:.v-bind动态绑定属性,如绑定class或者style,缩写:冒号,在绑定class或者style时支持对象和数组
eg::class="{className:flag}",动态绑定都是绑定的变量,动态绑定样式时,所有的样式都是驼峰命名
<!--传数组-->
<div :class="[father,son,{grandSon:flag}]">第一个</div>
<!--传对象-->
<div :class="classes">第二个</div>
<!--内联样式动态绑定-->
<div :style="myStyle">style样式绑定</div> //计算属性可以应用
<tr v-for="i in 10" :style="{backgroundColor:i%2===0?'green':'white'}"><td></td></tr>
data: {
flag: true,
father: "father"
},
computed: {
myStyle() {
return {
color: "red",
backgroundColor: this.flag?"blue":"grey"
}
},
classes() {
return {father: this.flag}
}
ps:bootstrap offset-x可直接进行偏移居中等
外围是面板 带头body和脚 body中胶囊foot中是列表组,button的浮动用pull-right, 特殊符号:&tim开头自己选择
20.arguments在方法中可直接打印查看对应方法的参数都有哪些
21.offsetleft和offsettop是当前元素相对于有定位属性(position非默认)的父元素的相对位置,如果 父元素postion都默认,则是相对于body
22.局部自定义指令directives
eg:<div v-color v-drag >2</div> //给元素加上该v-color时就会变色
directives: {
color(el){
let arr = ["red","yellow","blue","pink"]
setInterval(()=>el.style.background=arr[Math.floor(Math.random()*100)%arr.length],1000);
},
23.watch监控默认只能监控一层,如果要深度监控,即对象内部套对象这种的值变化,则需要handler+deep=true
eg:watch:{
items:{ //之前默认写函数时,其实就是写的handler
handler(newV){
localStorage.setItem("items",JSON.stringify(newV));
console.log(localStorage.getItem("items"));
},
deep:true
} ,
24.vue的生命周期
eg:
let vm = new Vue({
el:"#app",
beforeCreate(){},
created(){},//实例创建完,可以操作数据了,一般做ajax请求
beforeMount(){
alert(1)
},
mounted(){},//DOM渲染完了,可以操作DOM了,常用
beforeUpdate(){},//数据更新前
updated(){},//更新后,这两个方法可以用watch代替
beforeDestroy(){},//实例销毁前,一般可解绑或者销毁定时器等
destroyed(){}//销毁后
});
//销毁实例的方法
vm.\$destroy();//销毁后,对实例数据更改,页面不会响应,因为所有的监听器和子组件都被销毁了
- vue的$获取实例属性
(1)this.$options属性能够拿到当前实例中所有的属于实例的属性
(2)this.$nextTick(()=>{})//在数据修改后,DOM会异步更新,为了能感知DOM更新完成,会回调这个nextTick方法,凡是希望在DOM异步更新完后取到真实的dom的结果,一定要加这个nexttick
(3)$refs://在vm实例中要操作dom没必要使用document.getElementBy…,可使用$refs代替,可直接取出对应的完整标签,如果多个ref值一样,除非是v-for循环出的标签能够获得数组,手动写的标签只能拿第一个ref对应的标签
eg:
<p ref="myp">{{msg}}</p>
<p v-for="a in 5" ref="p1">{{a}}</p>
let vm = new Vue({
a:1,
el:"#app",
data:{
msg:'helloWorld'
},
mounted(){
console.log(this.$options.a);//这里可以拿a
//console.log(vm);//在mounted中调用vm时,实例还没定义完且没给vm赋值,所以vm会undefine
this.$nextTick(()=>console.log(vm));//等待DOM渲染完成后会赋值给vm,然后再获取vm
console.log(this.$refs.myp.innerText);//单个
console.log(this.$refs.p1);//数组
},
})
26.组件分类:页面级组件 一个页面一个组件;基础组件:将可复用的部分抽离出
(1)协同开发,减少重复,容易管理,提高开发效率,一个自定义标签即会成为一个组件
⦁ https://www.cnblogs.com/sanshengshui/p/9774746.html netty做http服务端
26.自定义标签就会被vue看成组件,自定义标签或者组件名尽量不大写,多个字母中划线隔开
eg:全局组件定义
Vue.component("my-div",{
template:'<div>{{me}}</div>',
data(){ //数据必须以函数方式返回一个数据对象,否则报错
return {me:'英俊如我'}
}
})
27.局部组件
组件最大的特点就是独立性,所以不能在组件中操作公共作用域的数据,组件中也有完整的vue周期函数,以及普通vue对象的方法,data等所有属性;组件可以套组件
28.组件父传子数据:
props中的属性,可直接在方法中以this引用,跟子组件自己的数据对象一样使用
props即可传对象也可传简单数组
参考 vue api
eg:
//自定义标签上加属性message
<father v-bind:message="msg" v-bind:message1="msg"></father>
let father = {
props:['message','message1'],
template: '<div>我很英俊真的{{message}}{{message1}}<son></son></div>',
};
29.组件子传父 单向数据流,子只能通知父,父改变然后传子,子通知父通过自己on绑定一个事件,然后自己emit触发一个事件,
ps:注意 vue中$emit触发和@on绑定的事件名称不能使用驼峰,否则事件无法触发,因为HTML中不区分大小写,注意注意!!!
eg:
<div id="son2f">
father:<input v-model="money"/>
<!--自己on绑定了一个事件-->
child:<child :m0="money" @changechild="changef" >这里是孩子内部</child>
</div>
let vm0 = new Vue({
el:"#son2f",
data:{
money: 400
},
methods:{
changef(money){
console.log("父亲方法");
this.money=money
}
},
components:{
child:{
data:{
m0:0
},
props:['m0'], //将父传子的属性与child中的data中属性写成一个,这样v-model就同时监听了两
//将两个的值统一了起来,
template:'<input v-model="m0" @keyup="bq"/>',
/* template:'<h2 @click="bq">{{m0}}</h2> ',*/
methods:{
bq(){
this.$emit("changechild",this.m0);//激活绑定的事件
}}}
ps:vue组件使用的三部曲:
eg:
导入,注册,使用
<template>
<div>
<MyHeader :ishow="true">首页</MyHeader> //使用
home
</div>
</template>
<script>
import MyHeader from '../base/myHeader.vue' //导入
export default {
data() {
return {}
},
methods: {},
computed: {},
components: {MyHeader} //注册
}
30.一般不将html代码写在js中,自定义组件模板一般放在template中 ,js中以id引用之
eg:
<template id="my">
<button @click="change">关闭</button>
</template>
components: {
modle: {
props:["show"],
template:"#my", //使用template的id来表示其内容
}
}
- .async语法糖,如果自定义组件中监听的方法就是为了改变一下父组件中的值,那可以用语法糖
<!-- <modle :show="show" @son-show="show=!show"></modle>--> //原本
<modle :show.sync="show"></modle> //现在
components: {
modle: {
props:["show"],
template:"#my", //使用template的id来表示其内容
methods:{
change:function () {
// this.$emit('son-show')//不能驼峰
this.$emit('update:show')//这样触发的方法必须是update:xx的形式,.sync其实是替代了这里的方法名而已
}
}
}
}
30.一般不将html代码写在js中,自定义组件模板一般放在template中 ,js中以id引用之
eg:
<template id="my">
<button @click="change">关闭</button>
</template>
components: {
modle: {
props:["show"],
template:"#my", //使用template的id来表示其内容
}
}
31.动态模板,slot槽位能够将自定义标签中的元素替换进去,实现动态模板
eg:
<div id="app">
自定义组件中的值都是父级事件的,只有属性名是属于组件的
<model><p slot="title">这是我的标题</p><h1 slot="content">这是内容</h1></model>
<model><h2>这是一个h2</h2></model> <!--不写slot属性,则取默认位置的slot内容-->
</div>
<!--模板必须只能有一个根元素-->
<template id="my">
<div>
<slot name="default"><h1>这是动态模板槽位</h1></slot>
<slot name="title"><h1>这是默认标题</h1></slot>
<slot name="content"><h1>这是默认内容</h1></slot>
</div>
</template>
32.父级直接调用子类的方法 则可通过ref标签对自定义组件进行标注,然后获得自定义组件实例
eg:
子组件:
<model ref="mo"><p slot="title">这是我的标题</p><h1 slot="content">这是内容</h1></model>
let vm0 = new Vue({
el: "#app",
data: {
show: false
},
mounted(){
this.$refs.mo.color(); //this.$refs与getEle..byID类似,通过.mo(ref属性的值)获得元素,然后调用color()方法
console.log( this.$refs.mo);
},
components:{
model:{
template:"#my",
methods:{
color(){
this.$el.style.backgroundColor="red";
}
}
}
}
......
})
33.vue中内置的组件
component 可通过is属性动态切换自定义组件,transition和transition-group,slot,keep-alive组件切换时,另其他不用的组件保持在内存中,不销毁
eg:
<input type="radio" v-model="radio" value="home"/>home
<input type="radio" v-model="radio" value="list"/>list
<keep-alive>
<component :is="radio"></component>
</keep-alive>
home:{
template: '<div>home</div>',
beforeDestroy(){
console.log("销毁home") //不加keep-alive就会销毁
}
},
list:{
template: '<div>list</div>',
beforeDestroy(){
console.log("销毁list")
}
}
34:子组件和父组件都有mounted方法时,子组件的mounted会先调用,dom更新时异步的,要在父mounted中 子组件mounted的结果,则一定使用nexttick方法,在dom更新完后延迟调用
35.子组件中也可以使用computed计算属性,与vue实例中使用一样
26.SPA 单页应用路由 v-router的使用,需要引入vue-router.js
eg:
<div id="app">
<router-view></router-view>
<!--灵活的方式是传对象,可以动态拼接变量-->
<router-link tag="button" :to="{path:'/home'}">首页</router-link>
<router-link tag="button" to="/list">列表</router-link>
<button @click="changeHash">点鸡跳转</button>
</div>
const routers = [{path: "/home", component: home}, //hash不同的路径,使用不同的组件,/不能省略
{path: "/list", component: list}];
let router = new VueRouter({
routes: routers ,//routes是参数key,不能变,如果入参变量也叫routes,则routes:routes可简写成routes
mode:'history',//H5的history模式,默认是hash模式,即不用带#号,生产一般用这个,但是回车会请求服务端,404,因此要在ng上配置后候选路径仍为首页
});
let vm1 = new Vue({
el: "#app",
router, //路由
})
27.编程式路由
eg:
其他部分与上面例子一样
$router是每个vue实例中内部生成的一个栈
let home = {
template: '<div>Home' +
'<button @click="toList">去列表</button></div>',
methods: {
toList() {
this.$router.push('/list');//$router是每个vue实例中内部生成的一个栈
}
}
};
let list = {
template: '<div>list<button @click="back">回首页</button></div>',
methods: {
back() {
this.$router.go(-1);//往后走一页
}
}
};
28.嵌套路由
eg:<div id="app">
<router-link to="/home" tag="button">首页</router-link>
<router-link to="/detail" tag="button">详情</router-link>
<router-view></router-view> <!--最顶层的路由出口-->
</div>
<template id="detail">
<div>
<router-link to="/detail/profile" tag="button">简况</router-link>
<router-link to="/detail/about" tag="button">关于</router-link>
<router-view></router-view>
</div>
</template>
const routers = [{path: '/home', component: home},
{
path: '/detail',
component: detail,
children: [ //嵌套路由就是在一级路由里写个子路由
{path: 'profile', component: profile},//嵌套路由一定不写/,/表示一级路由
{path: 'about', component: about},
{path: '*', redirect:'profile'}, //redirect
]
}];
29.动态路由参数,监听器监听路有对象获取参数向后台请求
eg:
let article = {
template: '<div><div>第{{$route.params.id}}篇文章</div><button @click="next">下一篇</button></div>',
data(){
return { n:0}
},
//当路由发生变化时监听路由变化,获取路由参数向服务端请求
watch:{
$route(){//监听路由对象
alert("请求参数"+this.$route.params.id)
this.n=this.$route.params.id;
}
},
methods: {
next() {
this.n++;
this.$router.push({name:'article',params:{id:this.n}});
}
}
}
//路由
//添加路由的名字
{path: '/article/:id', component: article,name:'article'},
32.vue项目的生成过程
eg:
npm install vue-cli -g
vue init webpack projectName --vue是vue-cli 命令行,初始化一个项目,并集成webpack打包工具
cd 项目名
npm install --这一步是把所有的依赖进行安装,也可以在init阶段选择自动install
cd 项目名
npm run dev -- 运行服务
33.esmodule模块的使用
(1)定义模块-- js就是模块;导出模块–export;导入–import
(2)导入导出参考ex6官网
(3)导出的实质规定了对外的接口,在接口名与模块内部变量直接建立关系
(4)import是静态执行的,中间不能使用变量
eg:import { foo } from ‘my_module’; //错误
(5)模块的默认导出
eg:
//第一种导出方式str和str1会以对象的形式导出 {str:'',str1:''}
export let str = "我很帅";
export let str1 = "我很英俊";
let a = 1;
let b =2;
let f = function () {
console.log("this is fu");
};
export { a,b,f};//导出的第二种写法,常用
let a = 1;
let b =2;
let f = function () {
console.log("this is fu");
};
//import导入时,得使用等价的结构对象,不能直接赋值,import有声明变量的功能,
// 且有提升效果,会将变量提升到模块头,不过一般import放顶部
//console.log(str);//结构赋值时的导入方式可,
//第一种方式 import {str,str1} from './test1.js'
//第二种方式 ,将所有导出内容的对象赋值给b
import * as b from './test1.js';
import * as test2 from './test2.js'
import de from './test2.js' //当有默认导出时,才正确
34.webpack的使用
在vue项目路径下
npm init -y
npm install webpack
在package.json中的scripts中配置一个脚本build,脚本用的命令是webpack,会去node_moduels下找bin对应的webpack名字 即bin/webpack.js,webpack.js需要当前目录下有个名字webpack.config.js , 通过npm run build(package.json中配置的脚本)执行的就是当前目录就能找到webpack.config.js
eg:
"scripts": {
"build": "webpack",//使用webpack命令,调用的是node_modules/bin/webpack.exe命令,然后执行的是webpack/bin/webpack.js开始打包 在根路径下找ebpack.config.js配置文件
},
webp.config.js的基本内容,一定要放根路径,否则报错
//webpack必须采用commonjs的写法
let path = require('path');//专门处理路径的模块,以当前路径解析出一个相对路径
console.log(path.resolve('./dist'))
module.exports = {
entry :'./src/main.js',//打包的入口文件,webpack自动查找依赖
output:{ //打包后的名字和属性
filename: "bundle.js",
path: path.resolve('./dist')//必须绝对路径
}
};
然后运行 npm run build即可打包 src为源码 dist为打包后的代码
35.安装babel 将es6转成es5
eg:
npm install babel-core --save-dev
npm install babel-loader --save-dev
npm babel-preset-es2015 --save-dev //开发依赖 预设es2015,将es6转成es2015
然后在跟路径下新建.babelrc文件,内容
{
“presets”: ["es2015"]
}
36.将样式和图片解析成模块
eg:
css-loader将解析的内容插到style标签中
npm install css-loader style-loader --save-dev
在webpack.config.js中配置加载规则
module.exports = {
entry: './src/main.js',//打包的入口文件,webpack自动查找依赖
output: { //打包后的名字和属性
filename: "bundle.js",
path: path.resolve('./dist')//必须绝对路径
},
module: {
//模块的解析规则
// -js 匹配所有的js 用babel-loader转义 排除掉node_modules
rules: [
//es6编译时转es5
/* {test: /\.js$/, use: 'babel-loader', exclude: /node_modules/},*/
//css模块解析规则,应该先加载css样式,再使用style模块,但是这里从右往左写
{
test: /\.css$/,
use: [
{loader: 'style-loader'}, {loader: 'css-loader'}
]
},
{
test:/\.(jpg|png|gif)$/,
use: {
loader: "url-loader",
options: {
limit:1024*4 //如果图片大于等于4kb,则使用file-loader转成base64,否则就不转,直接输出图片,即在编译输出路径下会有图片文件生成
}
} //url-loader依赖于file-loader,因此两个都要安装
}
]
}
};
然后在主模块中导入css
//导入css样式
import "./main.css";
最后打包
所有的模块 js、css等最终都是打包到一个js中的
参考webpack 官网 https://webpack.js.org/concepts/loaders/#configuration
37. npm install命令比较
eg:
npm install module 安装到项目node_modules下,--save表示将模块依赖写入dependencies节点中, --save-dev表示只开发依赖
38 在js中引入图片 import,或者写一个线上路径,如果直接引用相对路径则打包不进去
eg:let img = new Image();
//这里路径会被当成字符串,但是图片本身不会被打包到编译输出路径,因此会404
//GET http://localhost:63342/vue-study/dist/imges/delete.png 404 (Not Found)
//img.src="./imges/delete.png";
//先导入,导入后的img1事图片的路径
import img1 from './images/delete.png'
img.src=img1;
document.body.appendChild(img);
- webpack-dev-server是一个服务器插件, webpack——apache,启动一个web服务器,并实施更新修改,启动修改完文件看不到编译文件的输出,实时编译的文件内容会保存在内存中,一般开发阶段用
eg:
安装npm i -D webpack-dev-server
在package.json的scripts中配置
“dev”: “webpack-dev-server”
然后 npm run dev即可
ps:npm i 基本等于npm install, -D表示依赖的使用范围是dev开发阶段
40. webpack打包html页面,该页面会自动生成script标签,将编译后的js文件引入
eg:
安装:npm install --save-dev html-webpack-plugin
配置和使用:
在webpack.config.js中配置
var HtmlWebpackPlugin = require(‘html-webpack-plugin’);
plugins: [ //跟module平级
new HtmlWebpackPlugin({
template: “./src/index.html” //设置源码html,如果不设置的话会默认生成一个index.html文件
})
]
ps: import 引入自定义模块和第三方不同,自定义模块相对路径需要加./,第三方依赖(都在node_modules)不需要./
eg:
import str from ‘./test1’;
import Vue from ‘vue’
41.使用npm这一套来写vue项目
npm install vue
安装.vue相关的loader
vue-loader //解析vue文件,vue-template-compiler 用来解析vue模板,使用时只用配置vue-loader即可,它会自动依赖后者
npm install vue-loader vue-template-compiler
//在webpack.config.js中编辑解析规则
const VueLoaderPlugin = require('vue-loader/lib/plugin');
{
test:/\.vue$/,
use: {
loader: "vue-loader"
},
},
plugins: [
new VueLoaderPlugin() //应用插件
]
在main.js主模块中引入
//第一种引用方式引用的是vue的runtime-only版本,不支持template,vue分两个版本 runtim-only以及runtime&compiler
//编译器的作用就是将template转换成render函数,即runtime-only版本的vue不支持template属性
//import Vue from 'vue'
//import Vue from 'vue/dist/vue.js' //引用方式2,引用vue.js会将compiler也引入进来,但是compiler有6k,一般也不用
//使用.vue文件代替+直接导入vue运行时版本
import Vue from 'vue'
import App from './App.vue' ;
//vue-loader将.vue文件变成一个模块
console.log(App)
let v = new Vue({
el:'#app',
render:(h)=>h(App) //render方法可以将一个虚拟dom转成真实的dom元素
});
创建app.vue文件 //一个.vue文件就是一个组件
<template>
<div >
<h1>hello vue!</h1>
</div>
</template>
<script>
export default {
//默认导出一个对象
data(){
return {}
},
methods:{},
computed:{}
}
</script>
<style scoped> //限定仅用于当前vue文件中的元素
</style>
ps:一个vue文件有三个部分 结构 样式 行为
<template> <script><style>
ps:import语法如果直接导入的是某个文件夹,其实是默认在导入该文件夹下的index.js文件
eg:
import router from './router' <=> import router from './router/index.js'
42.融入vue-router
main.js中导入 import routerV from "./router/";
router/index.js中构造路由表
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);//和之前不同之处,引入router必须使用use,可以将路由进行全局注册,use方法会调用对导入的组件中的install方法,并执行
import Home from '../components/Home.vue'; //组件1
import List from '../components/List.vue'; //组件2
const index = [{path:'/home',component:Home},
{path: '/list',component: List}];//路由表
export default new VueRouter({ //路由对象 默认导出
routes:index,
});
app.vue中加入router-view
<template>
<div >
<router-view></router-view>
</div>
</template>
43.初始化项目
前提是安装vue-cli
然后运行vue的命令:
vue init webpack vue-book 即可创建vue-book项目文件及基础项目结构
44.router-link提供了标签激活的类名
eg:
a.router-link-active{ /router-link元素提供的激活时的类名/
color: lightgreen;
} //router-link最终会被渲染成a标签
/router-link-exact-active路径完全匹配时才激活/
- node js中提供了一种模拟后端服务器做http请求响应的http模块
eg:
let http = require('http'); //node js中的模块
let fs = require('fs'); //操作文件的模块
let url = require('url'); //解析url的模块
let sliders = require('./sliders');//这里放的是写死的数组
//模拟后端服务器
http.createServer((req,res)=>{
/*解决跨域问题*/
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild");
res.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.setHeader("X-Powered-By","3.2.1");
res.setHeader("Content-Type", "application/json;charset=utf-8");
let {pathname,query} = url.parse(req.url); //解构语法解析url
if(req.method==='OPTIONS') return res.end(); //cors探测方法
if(pathname==="/sliders"){
res.setHeader('Content-Type','application/json;');
res.end(JSON.stringify(sliders)); //响应返回内容
}else{
res.end(JSON.stringify("404"));
}
}).listen(3000); //监听端口
ps:ajax请求时一般只返回一个promise即可,不要直接异步返回数据,那样赋值时undisputed的
eg:
//正解
created(){
//created中一般用于ajax请求
console.log(this.sliders);
getSliders().then(res=>{ //这里的getsliders是一个promise,
this.sliders =res.data; //在这里才能赋值
});
},
//错误
created(){
//created中一般用于ajax请求
console.log(this.sliders);
this.slide = getSliders();//这里的getsliders是直接从response异步返回的值,会导致slide为undefined,因为异步并不会马上返回值
},
ps:公共的style属性,一般放在App.vue中
46项目结构
47.组件异步加载,实现组件懒加载功能,即点到哪个组件请求加载哪个,而非一次性加载所有组件
eg:
//组件采用以下方式异步导入进来,而非直接使用import导入,使用import导入则会一次性全部加载所有组件
export default new Router({
routes: [
{
path: '/add',
component:() => import('../components/Add'),
meta:{title:'标题'}
}...
{
path: '/',
redirect: 'home' //解决超链接没有选中的问题
}
]
})
- router的全局前置守卫,每次跳转前都会执行该钩子方法,可以做一些拦截功能,比如权限校验不通过,则跳转至登陆等
import router from './router/'
router.beforeEach((to,from,next)=>{ //路由跳转时 改变对应的title
document.title = to.meta.title;
next();//一定要确保next执行,否则无法跳转到目标路由
});
49.vuex保存全局数据状态
参考:https://www.jianshu.com/p/54608e9f93f2
组件之间通过父子组件通信也可,规模大则很麻烦,需要将一些共享数据状态集中存储管理
vuex的api:
state 用来保存状态
getters 用来保存状态
mutations commit提交 只能同步
actions dispatch 提交 可提交异步操作
module
以及辅助函数
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新
本质上是一种全局单例
改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation
Vuex的数据流是组件中触发Action,Action提交Mutations,Mutations修改State。 组件根据 States或Getters来渲染页面。
mutation不应该异步修改state
action可以
https://www.jianshu.com/p/54608e9f93f2
//Vuex全局状态管理,用于组件之间共享数据的传递,但是要注意,store中的值在页面刷新后会重置,如果要实现数据持久化,得借勇浏览器的存储功能
import Vuex from 'vuex'
Vue.use(Vuex);
const state = {maxBookId:0};
const mutations = {
increase(state,value){ //第一个参数state默认传入,第二个参数是自定义的“载荷payload”参数,其他组件改变值的方式:this.$store.commit("increase",1);
console.log(value);
state.maxBookId +=value
}
};
- npm安装
npm: Nodejs下的包管理器。
⦁ webpack: 它主要的用途是通过CommonJS的语法把所有浏览器端需要发布的静态资源做相应的准备,比如资源的合并和打包。
⦁ vue-cli: 用户生成Vue工程模板。(帮你快速开始一个vue的项目,也就是给你一套vue的结构,包含基础的依赖库,只需要 npm install就可以安装)
npm安装教程参考:
https://www.cnblogs.com/lgx5/p/10732016.html
42 Vue引入后其实是引入的vue.js类似jquery,然后vue会抛出Vue构造函数,因此每次都会new Vue创建实例化对象
构造函数
ƒ Vue(options) {
if (!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword');
}
this._init(options);
}
43.构造函数传入的是个options对象{},因此每次new Vue({})
options中的属性:
el 属性 ("#app")绑定一个目标区域
data属性声明数据属性,通过{{}}模板语法插值绑定和取数
template属性,定义模板,如果定义了非空内容,则会优先挂在其,否则才会加载el绑定的区域,template中的内容是直接覆盖el绑定区域的内容的
44 除了自定义的一些属性和方法以外new Vue对象本身还暴露了很多有用的实力属性和方法,都加了 符号,取得时候应该加上美元符号 , e g : 符号,取得时候应该加上美元符号,eg: 符号,取得时候应该加上美元符号,eg:el等
// 引入构造函数后,就需要new 一个全局对象,参数是options
let vue = new Vue({
el:"#app", //绑定一个目标区域
data: { //属性声明数据属性,通过{{}}模板语法插值绑定和取数
msg:"zsx"
},
template: ''//'<div>{{msg.repeat(3)}}</div>' //template属性,定义模板,如果定义了非空内容,则会优先挂在其,否则才会加载el绑定的区域,template中的内容是直接覆盖el绑定区域的内容的
});
/* 除了自定义的一些属性和方法以外new Vue对象本身还暴露了很多有用的实力属性和方法,都加了$符号,取得时候应该加上$*/
console.log(vue.$el) /*打印app的div*/
console.log(vue.$data.msg)
console.log(vue.$data)
console.log(vue.$options)
44前端浏览器直接请求时,如果有跨域,则默认服务端只会暴露几个固定的响应头给浏览器,而其他头会隐藏,需要服务端设置响应头解决跨域请求结果中header的权限控制Access-Control-Expose-Headers
response.addHeader("Access-Control-Expose-Headers": "Content-Length, X-Kuma-Revision")
45 npm换源
//查看源
npm config get registry
//更换源
npm config set registry https://registry.npmjs.org
//淘宝源
npm config set registry https://registry.npm.taobao.org