vue 学习

安装

  需安装node、webpack、vue-cli
  检查node的安装情况,node -v
  检查npm的安装情况,npm -v

  windows下更新node找了很多资料,最后看到说是覆盖安装msi文件(不太懂这个和重新安装有什么区别)。

  安装webpack4和之前的版本不太一样,先是npm install webpack -g。如果是自己配置,还需要安装npm install webpack-cli -g,(好像可以不用安装webpack,安装vue-cli时自带,没试过)。
然后安装npm install vue-cli -g,这里查看版本是vue -V(V大写)。

cnpm替换npm

  npm 服务器是放在国外的,有时候会很慢,国内可以使用淘宝镜像 cnpm。
  安装淘宝镜像,npm install -g cnpm --registry=http://registry.npm.taobao.org,验证是否安装成功,cnpm -v
  还可以修改npm的指向地址,npm config set registry https://registry.npm.taobao.org

npm install报错,解决办法:

  有的时候我们git他人的项目,但是执行下载所有依赖npm install后启动npm run dev运行的最后一步经常会报错,不是缺少依赖模板,就是node_modules版本与本机安装的nodenpm版本不一致。这时解决的方法就是直接删除vue项目中的node_modules,同时修改package.json文件里面的nodenpm版本号,同电脑一致,然后执行npm install重新下载所有依赖,最后执行npm run dev就能成功运行项目了。

删除node_modules文件:

 npm install rimraf -g
 rimraf node_modules

搭建项目

  • vue init webpack projectname创建项目
  • cd projectname进入项目文件夹
  • npm install安装项目依赖,这个命令可以执行是由于,定位到工程文件的前提下,目录下有一个package.json文件,里面配置了依赖所需;
  • 安装vue路由模块vue-router和网络请求模块vue-resourcenpm install vue-router vue-resource --save
      搭建完成之后会产生一个文件夹,如下:
    vue项目结构
  • config是构建配置目录,里面的index.js17行代码可以设置端口port,我们的8080端口可能占用,可以在这修改。
  • 上图中的index.html就是入口页面,也可以叫容器,里面有个idappdiv
  • src就是我们写代码的地方,源代码目录。
  • src中的main.js就是入口 js 文件,也叫逻辑入口;
  • src中的App.vue相当于是主组件,所有的组件都将在它里面组合。这里有个有趣的地方,它里面也有个iappdiv。但却不会和index.html里的同iddiv冲突。
  • main.js会调用主组件App.vue和路由,并创建一个Vue实例,关联到index.html里的div上,最个div被替换成App.vuediv替换。至于如何替换的,就不太清楚了。

安装各种依赖

  npm install xxx xxx --save -dev
  • --save是指我们在生产环境下安装的各种依赖,在package.json中就是dependencies
  • -dev是开发环境下的依赖,在package.json中就是devDependencies


      npm 安装package.json中的模块依赖分为两种情况
  • package.json不存在时: 命令:npm init可自动创建package.json文件。
  • package.json存在时: 直接命令:npm install或者npm install –save-dev会自动将package.json中的模块安装到node-modules文件夹下。

指令

指令 描述
v-once 数据不更新,初次数据就是永久数据
v-if 判断是否渲染元素,元素在显示和销毁之间切换,适用于不经常改变的场景
v-show 判断是否展示元素,元素在显示和隐藏之间切换
v-else v-else-if 必须和v-if结合使用,并且语句必须前后连在一起
v-for 优先级比v-if高,(item,index) in arr/str/num
v-text / v-html
v-bind 动态绑定属性、样式、类等,简写直接:
v-on 绑定事件,简写@,停止冒泡@click.stop=,阻止默认事件@click.prevent=,串联写法@click.stop.prevent=

Class 与 Style 绑定

  当有多个条件class时这样写有些繁琐。所以在数组语法中也可以使用对象语法。

  <div v-bind:class="[{ active: isActive }, errorClass]"></div>

条件渲染

  v-if元素必须紧跟在带v-if或者v-else-if的元素的后面,否则它将不会被识别。
  Vue为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的key属性即可。 
  v-if是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
  相比之下,v-show就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于CSS进行切换。
  一般来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show较好;如果在运行时条件很少改变,则使用v-if较好。
  当它们处于同一节点,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for循环中。

事件处理

  有时候,你可能想在某个组件的根元素上监听一个原生事件。可以使用v-on的修饰符.native

<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

<!-- 只有在 `keyCode` 是 13 时调用 `vm.submit()` -->
<input v-on:keyup.13="submit">

<my-component v-on:click.native="doSomeThing"></my-component>

键盘事件及修饰符

  • @click.once = " ", 只有第一次点击有效。
  • @keyup.enter = " ", 输入完成并且按下回车,才会触发。
  • @keyup.alt.enter = " ", 输入完成并且同时按下回车和alt键,才会触发。

实例对象的数据选项

data

  dataVue实例的数据对象。Vue将会递归将data的属性转换为getter/setter,从而让data属性能响应数据变化。
  [注意]不应该对data属性使用箭头函数。
  Vue实例创建之后,可以通过vm.$data访问原始数据对象。
  Vue实例也代理了data对象上所有的属性。但是,以_$开头的属性不会被Vue实例代理,因为它们可能和Vue内置的属性或方法冲突。可以使用例如vm.$data._property的方式访问这些属性。
  构造Vue实例时传入的各种选项大多数都可以在组件里使用。只有一个例外:data必须是函数。

Vue.component('simple-counter', {
  template: '<button v-on:click="counter += 1">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  }
})

computed

  计算属性computed,实时触发,默认只有getter方法,有需要时可以加setter方法。计算结果会缓存,下次直接调用缓存,计算属性只有在它的相关依赖发生改变时(虚拟DOM和真实DOM不同时)才会重新求值,是同步的,需要return出来。

method

  对于最终的结果,computedmethod两种方式是相同的。
  然而,不同的是computed是基于它们的依赖进行缓存的,computed只有在它的相关依赖发生改变时才会重新求值。这就意味着只要data还没有发生改变,多次访问computed会立即返回之前的计算结果,而不必再次执行函数。
  相比而言,只要发生重新渲染method调用总会重新执行该函数。
  如果不希望有缓存,则用method替代。

watch

  Vue提供了一种通用的方式来观察和响应Vue实例上的数据变动:watch属性。watch属性是一个对象,键是需要观察的表达式,值是对应回调函数,回调函数得到的参数为新值和旧值。值也可以是方法名,或者包含选项的对象。Vue实例将会在实例化时调用$watch,遍历watch对象的每一个属性。
  除了使用数据选项中的watch方法以外,还可以使用实例对象的$watch方法, 该方法的返回值是一个取消观察函数,用来停止触发回调。
  当数据需要随着其它数据变动而变动时,我们应该避免滥用watch属性,使用computed计算属性也可达到相同的目的。

组件

  组件分为全局组件和局部组件,全局组件在所有实例中都可使用,局部组件仅可在注册的实例中使用
  组件的创建和使用分为三步:创建组件构造器、注册组件、挂载作用域下实例化

创建构造器

  let Profile = Vue.extend({
      templete:~
          <div>   </div>
      ~
  })    

注册全局组件

  //Vue.component("组件自定义名称","构造器名称")
  Vue.component("my-div","Profile");

实例化调用

  组件的创建和使用可简化在一起,创建构造器和注册组件可写到一起,

  Vue.component("my-div",{
      templete:~
          <div> </div>
      ~ 
  })    

template 和 script 写模板

  用template写模板,可以像标签一样更直观,用id来和组件对应

  <template id="my-template-div">
      <div>  </div>
  </template>

  注册组件时把id对应

  Vue.component("my-div",{
      template:"#my-template-div"
  })

  也可以用script写模板,需要指定类型,注册时一样的用id对应,

  <script type="text/template" id="my-tempalte-div">
      <div></div> 
  </script>

  项目中用template更多,更直观
  组件中的 data 属性,必须是函数

  Vue.component("my-parent",{
   //组件中data属性,必须是函数的形式传递的
      data(){
          return{
          
          }
      }
      template:"#parent" 
  })    

组件通信

子组件获取父组件

  通过props传递,在子组件实例时使用props数组,显式的声明需要的参数(字符串形式);在子组件调用的时候,通过动态绑定的形式获得数据。组件中可以传值,也可以传引用,还可以传父组件。传值之后,当值更改,其他的相同的不会变更,但传引用会同时变更。
  还可以在子组件中通过this.$parent.属性/方法

父组件获取子组件

  原始的方式通过自定义事件$on()监听和$emit()触发来传递数据;在子组件调用的时候@total=''监听,在子组件的对应参数变化时使用this.$emit('total')触发。$emit(向父组件传递的事件名,向父组件传递的数据)
  还可以在父组件中调用子组件的时候,通过ref属性绑定,然后,this.$refs.xxx.属性/方法

非父子组件传值

  新建一个公共的Vue实例publicVue,用它传值。在传送方引入这个公共实例,通过publicVue.$emit("名称","数据")发送。在接收方也映入这个公共实例,通过publicVue.$on("名称",function(data){})接收。

  <div id="#app">
      <my-parent :message="message"></my-parent>
  </div>

  //子组件模板
  <template id="child">
      <div> {{message}} </div>
  </template>

  //父组件模板
  <template id="parent">
      <div>
          <my-chilid :message="message"> </my-chilid>
      </div>
  </template>

  <script>
      //子组件的实例
      let Child = Vue.extend(
          template:"#child",
      //在子组件实例时使用 props 显式的声明需要的参数(字符串形式)
          //第一种写法
          //props:["message"]
          //第二种写法,比第一种更严谨
          props:{
              message:{
                  type:String,
                  required:true
              }
          }
      );
      
      //注册父组件
      Vue.component("my-parent",{
          //父组件也要向外层拿数据
          props:["message"],
          //子组件注册
          components:{
              "my-chilid":Child
          },
          template:"#parent"   
      })

      new Vue({
          el:"#app",
          data:{
              message:"今天天气很好!"
          }
      })          
  </script>             

slot的介绍

  slot分为匿名插槽和实名插槽,匿名插槽可以填入任何标签,实名插槽则必须有对应的slot属性的标签,标签的slot的属性值和slotname属性值对应

  <div id="app">
      <my_slot>
          <div slot="cpu"></div>
          <div slot="memory"></div>
          <div slot="hard-drive"></div>
      </my_slot>
  </div>
  //组件模板
  <template id="my_slot">
      <div>
          //匿名插槽
          <slot> 可以替换任何标签 ,默认显示提示的内容</slot>
          //实名插槽
          <slot name="cpu"> </slot>
          <slot name="memory"> </slot>
          <slot name="hard-drive"> </slot>
      </div>
  </template>

  <script>
      Vue.component("my-slot",{
          template:"#my_slot"   
      })            
  </script>        

路由

安装 vue-router

  npm install vue-router --save-dev
  <div id="app">
      <div>
          //6.路由入口 
          <router-link to="/html5"> html5学院 </router-link>
      </div>
      <div>
          //7.路由出口 
          <router-view></router-view>    
      </div>
  </div>

  <template id="html5">
      <div> 学习html5 </div>
  </template>   

  <script>
      //1.引入vue-router
      import VueRouter from "vue-router"

      //2.用 vue-router
      Vue.use(VueRouter );

      //3.创建组件 
      let Html5 = Vue.extend({
          template:"#html5"
      })

      //4.配置路由 
      const router = new VueRouter({
          routes:[
              {path:"/html5",component:"Html5"},
              //记得配置根路由(用 redirect 重新指向)
              {path:"/" ,redirect:"/html5"}
          ],
          //删除路径中的 /# 
          mode:"history"
      });

      //5.创建 Vue 实例并挂载 
      new Vue({
          router
      }).$mount("#app");
  </script>  

多层路由

  //9.配置子路由入口和出口,用 name 代替路径的新入口 
  <router-link :to="{name:'html5'}"> html5学院 </router-link>

  <script>
      //7.创建子组件
      //8.定义子路由
      const routes = [
          //定义根路由
          {path:"/",redirect:"/html5"},
          {
              path:"/html5",
              //入口的路径太长,可以用 name 属性代替
              name:"html5",
              component:Html5",
              children:[
                  {path:"child1",component:Child1"},
                  //定义根路由
                  {path:"/",redirect:"child1"}
              ]
          }
      ];
  </script>  

页面传参

  用name可以传参,组件中用$route.name接收;
  还可以用<router-link>标签中的to属性进行传参,使用时:to={name:'xxx',params:{username:'xxx',id:'xxx'}},这时传递参数就得用params了,接收参数是$route.parmas.username,这里的name还可以当做路径使用

  通过url动态路由传参,在路由设置的时候以:冒号的形式传递参数,这就是对参数的绑定,path:'/params/:newsId/:newsTitle',在<router-link>设置参数<router-link to="/params/198/vue-router">传递参数</router-link>;在组件中接收参数,$route.params.newsId

  通过url GET传参,还可以在<router-link>设置参数<router-link to="/content?newsId =123">传递参数</router-link>;在组件中接收参数,$route.query.newsId

编程式导航

  也就是通过JS跳转路由,

    this.$router.push('home')。
    this.$router.push(name:'content',params:{userId:123});

路由模块化

  单独写一个router.js,并且在程序末尾导出router实例,export default router。在main.jsimport router from "../router.js"

路由其他

  通过在实例中注入路由,我们可以在任何组件内通过this.$router访问路由,也可以通过this.$router访问当前路由。

  单页面多路由区域操作,在<router-view name='自定义组件名'></router-view>components:{default: '默认组件' ,自定义组件名:'组件'},其中name和 自定义组件名对应,

  路由的重新定向,有时候我们的路径不一致,但希望到同一页面,这就需要页面重定向了redirectpath之后就不用写组件了,设置redirect,参数为需求页面的path

  alias别名也可以实现重定向的效果,在pathcomponent写完之后,设置alias;用的时候路径就写alias值,也会跳转到path路径的页面;<router-link to="/alias">;别名请不要用在path/中,是不起作用的。

页面转场动画

  路由的过渡动画,在<router-view>外层加上<transition>,组件过渡过程中,会有四个CSS类名进行切换,这四个类名与transitionname属性有关,比如name="fade",过渡模式是默认的mode模式in-out模式,我们也可以设置为out-in。如果想做出实用酷炫的过渡效果,可以用插件等工具。

history模式

  路由的mode的设置为history,可以省略浏览器显示的路径中的#

404页面

  404页面,当用户地址输入错误,应该显示有好的提示信息,显示进入错误,{path:'*',component:Error}Error组件可以做的好看好一点;

路由钩子函数

  路由中的钩子函数,路由的钩子选项可以写在路由配置文件中,也可以写在我们的组件模板中。
  在路由文件中我们只能写一个beforeEnter,就是在进入此路由配置时。bdforeEnter的钩子函数,需要传递三个参数beforeEnter:(to,from,next)=>{}:

  • to路由将要跳转的路径信息,信息是包含在对像里边的;
  • from路径跳转前的路径信息,也是一个对象的形式。
  • next路由的控制参数,常用的有next(true)next(false)。相当于一个控制开关,确认是否跳转的。我们可以在这里做个判断语句,判断参数是否正确,路径是否正确,然后再跳转。

  在模板中就可以有两个钩子函数可以使用:beforeRouteEnter在路由进入前的钩子函数。beforeRouteLeave在路由离开前的钩子函数。也可以轻易的读出tofrom的值。记得一定写next(),不然路由失败。

  在业务逻辑代码中需要跳转页面我们如何操作,这就需要编程时导航了,$router.go(-1)后退;$router.go(1)前进;$router.push('xxx')xxx可以是任意路径。这里是$router,不是$route

生命周期

  beforeCreate(){}, 组件实例化之前执行的函数,一般做加载的动画
  created(){}, 组件实例化完成,但还没生成DOM,页面还未显示。可以获取接口数据,赋给属性,还可以结束上面的加载动画。
  beforeMount(){}, 组件挂载前,页面仍未显示,但虚拟DOM已配置
  mounted(){}, 组件挂载完成,此方法只会执行一次,此方法执行后,页面显示,请求网络数据,业务处理
  beforeUpdate(){}, 组件更新前,页面仍未更新,但虚拟DOM已配置
  updated(){}, 组件更新后,此方法执行后,页面显示,一般我们在这里处理组件发生改变的情况
  beforeDestory(){}, 组件销毁前
  destoryed(){}, 组件已销毁
vue生命周期

渲染机制

  vm.$mountvue渲染的主要函数
  独立构建和运行时构建:

  • new vue,执行初始化。
  • 挂载$mount方法,通过自定义render方法、templateel等生成Render函数。
  • 通过Watcher监听数据变化。
  • 当数据变化时,Render函数执行生成VNode对象。
  • 通过patch方法,对比新旧VNode对象,通过DOM Diff方法,添加修改删除真正的Dom元素。

状态管理VUEX

  vue项目当中的非父子非兄弟组件之间的通讯传值可以用url、storage 和 cookie,在小型项目中这样用是很好的。如果是大型项目,用vuex就更合适,vuex可以把所有的状态(参数)共享在一起,同时自动更新。

安装 vuex

npm install vuex --save

使用 vuex

  • src文件夹下创建vuex文件夹,然后在该文件夹内创建store.js文件。
  • 然后在store.js文件内引入vuevuex,然后使用Vuex,新建store对象,我们就可以在store中写state,mutations,getters,actions,同时向外导出store
  • 也可以使用模块组moudels,每个module都有自己的state、getter、mutation、actions,并且要在store中引入所有moudel
  • store下面的getter.jsactions.js,这两个主要是管理模块之间状态;
  • mian.js中 引入store文件,在实例化Vue对象时,加入引入的store对象,这样就可以在所有子组件中使用vuex

state

  state,是vuex自己维护的一份状态数据。数据的格式需要你根据业务去设计。
  在组件中获取state参数,有两种方式,
  第一种就是直接取this.$store.state.xxx
  第二种是使用映射函数mapState函数取,先从vuex引入mapState( 引入的时候要用{}) ,再mapState(["xxx"]),当和其他计算属性同时使用的时候要用延展操作符...mapState(["xxx"]),写在computed里;

mutations

  mutations,更改Vuexstore中的状态的唯一方法就是mutations``。mutations必须是同步函数。
  每一个mutations都有一个事件类型type和一个回调函数handler
  使用常量替代mutation事件类型;待扩展。
  在组件中调用mutations里的方法,有两种方式:

  • 第一种需要通过this.$store.commit("xxx")方法调用,可以添加第二个参数进行传参,$store.commit("xxx","xxx"),也可以传入一个对象。
  • 第二种是使用映射函数mapMutations调用,先从vuex引入mapMutations( 引入的时候要用{}) ,再mapMutations["xxx"],当和其他方法同时使用要使用延展操作符...mapMutations (["xxx"]),调用的时候可以直接传参,写在methods里;

getters

  getters,可以把他看作在获取数据之前进行的一种再编辑,相当于对数据的一个过滤和加工。可以认为是store的计算属性,就像计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
  getters接受state作为其第一个参数,getters也可以接受其他getters作为第二个参数,你也可以通过让getter返回一个函数,来实现给getter传参,在你对store里的数组进行查询时非常有用。
  在组件中可以使用this.$store.getters.xxx或者mapGetters["xxx"]调用,与mapState类似,也是写在computed里。
  在组件中设置了mapGetters,在组件的beforeCreated事件中,是取不到相应的值的,在created之后,才能取到。???,待了解

actions

actions,类似于mutations,不同在于:actions提交的是mutations,而不是直接变更状态。actions 可以包含任意异步操作,而mutations是同步操作。
  Action函数接受一个与store实例具有相同方法和属性的context对象,因此可以调用context.commit("xxx"),提交一个mutation,或者通过context.statecontext.getters来获取stategetters。也可以传入{commit},直接commit("xxx"),这里actions的第一参数永远默认为是context,很容易理解,因为我获取的是状态,也就是如果你直接写(commit)的话,就必须写成(commit) => commit.commit.xxx
  组件中使用的时候,有两种方式,this.$store.dispatch("xxx")...mapActions (["xxx"]),写在methods里。

moudels

  moudelsVuex只能有一个单一的store对象,但是当应用变得庞大复杂的时候store就可能变得非常的臃肿;所以 Vuex 允许我们将store分割成模块module。每个模块拥有自己的state、mutation、action、getter,甚至是嵌套子模块——从上至下进行同样方式的分割。

  对于模块内部的mutationgetter,接收的第一个参数是模块的局部状态对象state。同样,对于模块内部的action,局部状态通过context.state暴露出来,根节点状态则为context.rootState。对于模块内部的getter,根节点状态会作为第三个参数暴露出来。

钩子函数

  过滤filters:{ }过滤符的使用;

混入

  混入mixins是一种分发Vue组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

过渡和动画

显性的过渡时间

  你可以用<transition>组件上的duration属性定制一个显性的过渡持续时间 (以毫秒计):

  <transition :duration="1000">...</transition>

  也可以定制进入和移出的持续时间:

  <transition :duration="{ enter: 500, leave: 800 }">...</transition>

  当有相同标签名的元素切换时,需要通过key特性设置唯一的值来标记以让Vue区分它们。

过渡模式

  同时生效的进入和离开的过渡不能满足所有要求,所以Vue提供了 过渡模式。

  • in-out:新元素先进行过渡,完成之后当前元素过渡离开。
  • out-in:当前元素先进行过渡,完成之后新元素过渡进入。
  <transition name="fade" mode="out-in">
    <!-- ... the buttons ... -->
  </transition>

实例方法

  vm.$set(target,key,value);往对象中添加属性

ref属性获取dom节点

  <div ref="box"></div>
  this.$ref.box.style="xxx"

获取当前节点的属性

  $event.target.style.color="red"

网络请求

vue-resource

  vue自己的资源请求工具,直接在main.jsimport引入,然后Vue.use(vue-resource),之后再所有组件中都可以使用了。this.$http.get(url).then((res)=>{},(err)=>{})

axios

  第三方工具,在哪用就在import引入,axios.get(url).then(()=>{}).catch()

UI框架

Mint-UI 移动端的UI框架

  https://mint-ui.github.io/docs/#/zh-cn2

    //在main.js 中,
    import Mint from 'mint-ui';
    import 'mint-ui/lib/style.css'
    Vue.use(Mint);

Element-UI PC端的UI框架

  http://element-cn.eleme.io/#/zh-CN/component/installation

  //在 mian.js 中,
  import ElementUI from 'element-ui';
  import 'element-ui/lib/theme-chalk/index.css';
  Vue.use(ElementUI);

  字体文件如果报错,webpack.config.js配置file_loader

  {
    test: /.(eot|svg|ttf|woff|woff2)(?S*)?$/,
    loader: 'file-loader'
  }
原文地址:https://www.cnblogs.com/sspeng/p/11466076.html