vue学习

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))
    }
}
  1. 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();//销毁后,对实例数据更改,页面不会响应,因为所有的监听器和子组件都被销毁了
  1. 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来表示其内容
        }
}
  1. .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);
  1. 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路径完全匹配时才激活/

  1. 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' //解决超链接没有选中的问题
          
        }
    ]
})
  1. 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
  }
}; 

在这里插入图片描述


  1. 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值