【vue】vue2.x详解大全

不会就问就查询!科技利民,学海无涯2

1、vue.js的安装

  • 方式一:直接CDN引入

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>

<script src="https://cdn.jsdelivr.net/npm/vue">script>
  • 方式二:下载和引入
  • 方式三:npm下载

2、vue指令

<p v-once>{{message}}</p>//值不再改变
<p v-pre>{{message}}</p>//原样输出
<p v-clock>{{message}}</p>//结合[v-clock]{display:none;}样式,实现斗篷效果;

<p v-html="message">我会被覆盖</p>
v-html='属性名':动态绑定输出内容,能识别解析html标签,覆盖标签文本

<p v-text="message">我会被覆盖</p>
v-text='属性名':动态绑定输出内容,正常输出内容,覆盖标签文本

<li v-for="(item,index) in array">{{item}}</li>
v-for='':实现for循环

<button v-on:click='add'>add事件</button>
v-on:[dom事件]='事件名':绑定(点击)事件,可以绑定其他事件

<img v-bind:src="imgUrl" alt="">
v-bind:[html属性]='属性名':动态绑定属性值

3、指令详解

4、ES6中对象字面量增强(简写)写法

  • 属性增强写法:
let name = 'aa';
let obj = {name};//增强写法,就是直接使用外面定义好的变量名;
let obj = { name:name };//常规写法
  • 函数增强写法
  methods:{
    add:function(){},//常规写法:键值对
    add(){},//增强写法
 }  

5、针对vue中元素复用:使用key属性,避免输入框切换时value输入值被带过来;
【vue】vue2.x详解大全_第1张图片
6、key属性

  • 不能用index索引值,因为索引是变化的;
  • 要用唯一标识;
  • 作用:为了高效的更新虚拟DOM;
  • 列表中for循环数组时如果在中间插入新元素,不加key会元素复用,导致后面所有元素都会改变;加key属性,之前的元素就不会改变,只需要创建一个新的元素然后放到指定位置;(与JS相关不加引号是变量,加引号是字符串;html、css相关加引号也是字符串,但是与vue结合相关的都是变量)
    <ul>
      <li v-for="(item,index) in array" :key="item.id">{{item}}--{{index}}</li>
    </ul>

7、vue中哪些数组方法是响应式的?

响应式:

  • push(…item):向数组结尾添加若干元素
  • pop():删除数组最后一个元素
  • shift():删除数组第一个元素
  • unshift(…item):向数组开头添加若干元素
  • splice(开始下标[>=0],要删除的个数[>=0],‘插入的新值’,‘插入的新值’,,,,):删除、插入、替换数组元素;(返回新数组,同时改变原数组)

非响应:

  • 直接按索引改变数组某个值;app.array[0]='aaa';
    • 借助splice实现改变值的响应效果;
    • Vue内置方法:Vue.set(修改的对象,索引值,修改后的值);
    • eg:Vue.set(this.array,0,'aaa');

8、JS数组的高阶函数

  • filter( fn( item){} ):将原数组中符合条件的元素返回到新数组中,最后返回一个新数组;
    • 参数为回调函数,回调函数传入的值是数组中每一项;
    • 内部回调函数返回true:就把当前传入的item添加到新数组中;
    • 内部回调函数返回false:直接过滤掉,进行下一个item操作;
  <script>
    const arr = [1,2,3,4,5];
    let newArr = arr.filter(function(n){
      return n<3;
    });
    console.log(newArr);//[1,2]
  </script>
  • map( fn( item){} ):将数组中每一项进行运算,把得到的新值赋值到新数组中,最后返回一个新数组;
    const arr = [1,2,3,4,5];
    let newArr = arr.map(function(n){
      return n+3;
    });
    console.log(newArr)//[4, 5, 6, 7, 8] 
  • reduce( fn( pre,item){},[pre的初始值] ):对数组中每一项挨个操作,最后返回一个值;
    const arr = [1,2,3,4,'a'];
    let tatol = arr.reduce(function(pre,item){
      return pre + item;
    },0);
    console.log(tatol)//10a  字符串

9、指令修饰符:事件修饰符、双向绑定修饰符;
v-on:click.stop="事件名";
v-model.number=" data中属性名 "

10、vue组使用件的注册

常规注册:
第一步:创建组件构造对象:Vue.extend();(现在一般不直接写这个,采用语法糖形式,这一步可以省;)
第二步:注册组件(全局/局部)
第三步:使用组件:

  • 全局组件:在Vue实例外注册,其他的Vue实例对应的 div 元素内也可以使用;
  • 局部组件:在Vue实例内注册,只有对应的 div 元素内才能使用;
  <script>
    const cpn = Vue.extend({
      template:`
      

我是父组件

`
});//创建组件构造器 Vue.component('cpn1',cpn);//注册全局组件,一般用不着这个 const app = new Vue({ el:'#app', data:{}, components: { myCpn:cpn } })//注册局部组件 </script>

补充一、语法糖形式:将创建组件模板与注册合二为一步;

    Vue.component('cpn1',{
      template:`

我是语法糖组件

`
});//语法糖:创建并注册全局组件 ----------------------------------------------------------------------- const app = new Vue({ el: '#app', data: {}, components: { cpn1: { template: `

我是语法糖组件aa

`
} } })//语法糖:创建并注册局部组件

补充二、语法糖基础上再做模板的分离:将模板中html代码分离出去,通过id属性引入;(两种方式)

  方法一:
  <script type="text/x-template" id="aaa">
    <div>
      <p>我是语法糖组件分离写法</p>
    </div>
  </script>
  方法二:(推荐)
    <template id="aaa">
    <div>
      <p>我是语法糖组件分离写法</p>
    </div>
  </template>
  --------------------------------------
  <script>
    const app = new Vue({
      el: '#app',
      data: {},
      components: {
        cpn1: {
          template: '#aaa'
        }
      }
    })
  </script>

补充三、创建父组件子组件:创建子组件构造器,必须在父组件之前定义;

    const cpn2 = Vue.extend({
      template:`
      

我是子组件

`
});//创建子组件构造器,必须在父组件之前定义 const cpn = Vue.extend({ template:`

我是组件

`
, components:{ Cpn:cpn2 }//在父组件中注册子组件,并使用 });//创建父组件构造器

11、组件传值:父子组件传值、兄弟之间传值

12、组件访问:父组件访问子组件、子组件访问父组件;

  • 父访问子:
    • 方式一:this.$children[]:通过下标找子组件,子组件改变可能会找错;
    • 方式二:this.refs.aaa.[属性名]+ref="aaa":给子组件设置ref,按名查找;
  • 子访问父:
    • 方式一:this.$parent.[属性名]:访问父组件data中数据
    • 方式二:this.$root.[]属性名:直接访问Vue实例data中数据

13、插槽slot元素的使用

  • 普通插槽:当子组件只有一个插槽slot;
  <div id="app">
    <cpn><button>子组件的插槽</button></cpn>
  </div>
  <template id="aaa">
    <slot></slot>
  </template>
  • 具名插槽:当子组件有多个插槽时,给每个插槽设置name属性;
  <div id="app">
    <cpn>
      <button slot='bb'>子组件第二个插槽</button>
      <p slot="aa">子组件第一个插槽</p>
    </cpn>
  </div>

  <template id="aaa">
    <div>
      <slot name="aa"></slot>
      <slot name="bb"></slot>
    </div>
  </template>

14、作用域插槽slot-scope

用于父子组件中插槽的传值:父组件中获取子组件插槽传来的数据,将数据反作用于子组件的插槽,决定插槽中数据的使用方式;

  <div id="app">
    <cpn>
      <template slot-scope='slot'>
        <p>{{slot.data}}</p>//属性名与插槽中属性命名对应即可
      </template>
    </cpn>
  </div>

  <template id="aaa">
    <div>
      <slot :data="array"></slot>//属性名data可以随便命名;
    </div>
  </template>

15、模块化开发:核心-(在js文件中)导入导出

历史:
JS文件分散,不同文件全局变量冲突—>使用匿名函数,不同文件代码不可复用—>简单模块化,文件中导出对象,暴露出去成全局变量—>统一规范的模块化(CommenJS(nodejs、webpack采用的就是这个规范)、AMD、CMD、ES6的modules)

  • CommenJS:在nodejs环境中可以识别解析它的语法;
导出:
    module.exports = {
      a:1,
      b:'aaa'
    };//导出对象形式
导入:
    var { a , b } = require('../aa.js');//因为commenJS导出的是对象,所以导入时可以使用解构写法
  • ES6的模块化:es6语法可以识别;
    首先,导入导出之前先确保不同JS文件分隔开
    • 可以不在同一个文件中引入;
    • 或者使用模块化标签:声明是模块化的,相当于各自不干扰;
  <script src="aaa.js" type="module"></script>
  <script src="bbb.js" type="module"></script>

然后,在JS文件中按需导入导出:

aaa.js导出:
export { a,b }//导出方式一,定义后统一导出
export let a = 'haha'//方式二,定义时直接导出
export function aa(){}//导出函数
bbb.js导入:
import { a,b } from "./aaa.js"

可以改名的导入导出:
export default a//只能导出一个变量
import [自主命名] from "./aaa.js"//导入时可以改名

统一导入:当需要导入很多变量时
import * as aa from "./aaa,js"//将所有要导入的变量存在aa对象中使用;

16、脚手架cli (command-line interface命令行界面)

vue-cli2、vue-cli3

  • 环境依赖:node.js、webpack
  • 安装:直接安装cli3即可npm install -g @vue/cli;通过拉取cli2模板·,实现在cli3环境下可以创建cli2项目;npm install @vue/cli-init -g
  • 创建vuecli2项目:vue init webpack [项目名],不用中文和大写字母
  • 创建vuecli3项目:vue creat [项目名],不用中文和大写字母
  • vue两个版本:runtime-only(简化版(默认版本),不允许JS文件中使用template,JS文件中的不能编译)、runtime-compiler(内容多,允许js文件中有template)
runtime-only main.js:
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
  el: '#app',
  render: h => h(App)
})
------
runtime-compiler main.js:
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
  el: '#app',
  components: { App },
  template: ''
})

17、路由vue-router

背景:

  • 后端渲染阶段:后端(服务器)路由
    • 后端渲染:早期,浏览器发送网址给服务器,服务器通过通过正则对url进行匹配(后端路由),找到对应的页面(包含html、css、后端代码),并交给controller处理渲染好,交给浏览器直接展示;
    • 后端路由:就是url与页面的对应关系,由服务器匹配;
    • 优点:后端渲染有利于seo优化;
    • 缺点:主要由后端人员开发,前后端代码混淆;所有页面都在服务器,请求不同页面要发请求;
  • 前后端分离阶段:前端渲染、后端路由
    • ajax出现;静态资源服务器(html、css、js,浏览器请求);数据服务器(用于api请求);
    • html、css、js、数据都是在浏览器渲染,所以是前端渲染;
    • 优点:前后端责任清晰,后端专注数据、前端专注交互与可视化;而且后端的数据api接口可供多端使用;
    • 缺点:所有页面仍然都在服务器,每次使用不同页面都要请求(页面请求、AJAX数据请求这是两种);
  • 前端路由阶段:前端渲染、单页面SPA
    • 前端路由同样是改变url,但是不会传到服务器(会使用history或hash技术让浏览器不去发请求),是给本地js(所有.vue组件都在打包后的js文件中)用来选择展示哪个组件使用;
    • 一般整个spa页面不能刷新(刷新会向服务器发请求,history或hash技术不能控制刷新时发送请求,只是自身路由添加时管用),刷新会出现404,所以要使用nginx配置重定向来解决不能刷新问题
    • 缺点:一次性请求所有资源;不利于SEO优化;

前端路由:防止url改变发送请求

  • hash哈希模式(利用:#)
    • location.hash='aaa':本质是修改window.location的href属性;页面不会刷新;
  • history模式(h5)
    • history.pushState({},'','home'):进栈出栈,支持浏览器点击前进后退;
    • history.back():后退一步(出栈一个),等价history.go(-1)
    • history.forward():前进一步,等价history.go(1)
    • history.go(-n):后退n步
    • history.go(n):前进n步
    • history.replaceState({},'','about'):替换,不能后退、前进

vue -router 路由

  • 设定访问路径,将路径与组件映射起来;
  • vue-router的单页面应用中,页面的路径的改变就是组件的切换;

vue -router 路由的安装与使用

  • 安装vue-router:
    • 通过vue-cli
    • npm install vue-router --save
  • 使用:
    • 1、:导入路由对象,并且调用Vue。use(VueRouter)/router/index.js
    • 2、:创建路由实例,并且传入路由映射配置;/router/index.js、App.vue
    • 3、:在Vue实例中挂载创建的路由实例:相当于给Vue原型对象添加:$router(路径)、$route(活跃的路由)属性;main.js

main.js:

import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  render: h => h(App)
})

  • 2、映射配置:/router/index.js、App.vue
    • 2.1、:创建路由组件:HelloWorld.vue
    • 2.2、:配置路由映射:组件和路径映射关系
    • 2.3、:使用路由:通过

2.2、index.js:

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '',
      redirect: '/hello'
    },
    {
      path: '/hello',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ],
  mode:'history'
})

2.3、App.vue:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-link to='/hello'>hello</router-link>
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

vue -router 路由的注意点

  • 标签点击后的自带类:class="router-link-exact-active router-link-active"
    可以通过router实例改变类名:

index.js:

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/hello',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ],
  linkActiveClass:'active'
})
  • 通过代码实现hello

App.vue:

<script>
export default {
  name: 'App',
  methods: {
    helloClick(){
      // this.$router.push('/hello');
      this.$router.replace('/hello')
    }
  }
}
</script>

vue -router 动态路由:vue文件

  • 动态路由:在路由跳转是传参数;
    • 方式一:params传参;第一步:通过v-bind动态绑定to属性实现路径拼接;第二步:在路由配置路径中使用:[参数名]接收,第三步:在活跃组件中computed计算属性使用this.$route.params.[参数名]获取参数值,或者利用{{$route.params.[参数名]}}
    • 方式二:query传参;
      档案

vue -router 动态懒加载与嵌套:index.js

const Home = ()=>import('../components/Home.vue')
const HomeNews = ()=>import('../components/Homes/HomeNews.vue')
const HomeMessage = ()=>import('../components/Homes/HomeMessage.vue')
const routes = [
  {
    path:'',
    redirect: '/home'
  },
  {
    path:'/home',
    component:Home,
    children:[
      {
        path:'news',
        component:HomeNews
      },
      {
        path:'message',
        component:HomeMessage
      }
    ]
  }
]

vue -router 全局导航守卫:(守卫不需要定义,直接传参执行的)index.js中定义(需要借助vue-router实例执行)、也可以在main.js中定义

  • 前置守卫guard(钩子函数hook):router.beforeEach((to, from, next) => { next();[自己的代码] }):点击路由要进入这个组件时触发,next决定是否让进;刚加载时不执行;
  • 后置守卫guard(钩子函数hook):router.afterEach( (to,from) => {})):进入某个路由组件后执行;刚加载页面时也执行,from是/根目录

main.js:

new Vue({
  el: '#app',
  router,
  render: h => h(App)
})
router.beforeEach((to, from, next) => {
  document.title = to.matched[0].meta.title;
/*   console.log(to);
  console.log(from); */
  next('/login');//(可以利用判断条件)强制跳到login组件,不写默认进入当前组件
})

vue -router 导航守卫补充:路由独享守卫、组件内守卫

  • 路由独享守卫:beforeEnter,刚加载页面时也执行;(类似全局导航方法的参数)
    index.js:
     {
        path:'news',
        name:'HomeNews',
        component:HomeNews,
        beforeEnter:(to,from,next)=>{
          console.log(to);
          next();
        }
      },
  • 组件内部守卫:自身vue文件中定义;(也类似全局导航方法的参数)
export default {
  name:'Profile',
  beforeRouteEnter(to, from, next) {
    console.log(this);
    console.log(from);
    console.log(to);
    next()
  },
  beforeRouteUpdate(to,from,next){
    
  },
  beforeRouteLeave(to, from, next) {
    console.log(this);
    console.log(from);
    console.log(to);
  }
}

vue -router 路由补充:状态保存 keep-alive

  • keep-alive是Vue内置组件,用于使被包含的组件保留状态,避免重新渲染;所以可以
  • 包住,让所有匹配到的视图组件都会被缓存;
<keep-alive><router-view/></keep-alive>
  • 结合两个钩子函数:活跃activated、不活跃deactivated
export default {
  name:'Home',
  activated () {},
  deactivated () {}
}

18、Vuex状态管理模式

你可能感兴趣的:(VUE)