vue个人总结--喜欢的点赞哟!

vue

基础知识补充

MVC 与 MVVM的

  1. MVC :

    后端开发模式

    • V --> view 视图层或者表现层
    • C --> control 控制器
    • M --> model 数据层

    当用户操作了视图层,如果需要进行业务处理,通过ajax发送到服务器,被入口js文件监听到,经过控制器 (路由模块,业务模块)的处理,最终对数据层(数据库的操作)

  2. MVVM

    前端的开发模式

    • V --> view 视图层 (页面的HTML结构)
    • VM --> 调度层 (为了数据双向绑定)
    • M --> 数据层( 每个页面中单独的数据 )

    MVVM是前端的视图层的分层开发思想, M是数据层,V是视图层,VM用于控制数据的双向绑定,分割了V和M,当V中绑定的数据被修改时,VM会自动将数据层对应的数据进行修改

vscode插件安装

  • Vetur vue工具
  • Vue 2 Snippets 代码片段

Vue-devtools

  • 安装步骤
  1. 打开谷歌浏览器开发者模式
  2. 将文件拖进去 : 文件要放在一个固定不动的地方 / 我的备份文件放在makedown文件夹中
  3. 打开详情 : 允许访问文件网址这一个勾上
  • 使用 :
    1. 当访问用vue写的网址的时候,会点亮工具图标
    2. F12可以最后一个检测组件的数据

常用接口

天气预报

请求地址 : http://wthrcdn.etouch.cn/weather_mini

  • 请求方式 : get
  • 请求参数 : {city : ‘深圳’}
  • 返回数据 : 字符串

聊天机器人

请求地址 : http://www.tuling123.com/openapi/api

  • 请求方式 : get
  • 请求参数 : {info:‘你好!’, key : ‘7aafde12d9a149428c5cc910f11d4f83’}

常用框架

moment.js(时间处理)

  • 适用于任何地方 不依赖于任何第三方框架
 // YYYY就是年:4个Y代表是要占4位
    // MM就是月:2个M就代表2位
    // DD就是日:2个DD就代表2位
    // HH就是时
    // mm就是分
    // 除了以上特殊字符,其他你写什么都原样显示
    // 如果moment里面不传就代表获取当前时间
    var now = moment().format('YYYY年MM月DD日HH:mm');
    console.log(now);
    
    // 如果你传入了时间,那么就获得是你传入的时间
    var now = moment('1999-01-01 19:35').format('YYYY年MM月DD日HH:mm');
    console.log(now);

基础知识

hello world

  • el --> element : 代表控制的是哪个组件(挂载)
  • {{}} --> 表达式 : 只能作用于标签内部
<script src="./vue.js"></script>

<div id="app">   // Vue控制的元素区域就是视图层View
    {{age + 5}} <br>
        {{makeCount()}}
</div>

<script>
    
    let vm = new Vue({    // 创建的VM实例对象就是控制器VM
        el : '#app',     
        data : {               // data就是Model
            name : '龚利明',
            age : 18
        },
        methods : {
            makeCount(){
                return 1+1;
            }
        }
    })
</script>

常用指令(directive)

v-bind:

  • 设置行内标签的属性的值
  • 或者直接用 :

​ class和style例外 : 通过数组来控制data变量的获取

  • 设置传递给子组件的值(后面补充)
  • 默认就有的class类的话,加上引号,样式的值也是,加上引号
<html lang="en">
<head>
    <style>
    .type1{
        color: red;
    }
    .type2{
        font-size: 40px;
    }
    </style>
    <script src="./../vue.js"></script>
</head>
<body>
        // 默认就有的class类的话,加上引号,样式的值也是,加上引号
  <div id="app" :class="[aini,{type2 : true}]" :style="[{marginLeft : '100px'},{marginTop : h}]">
        你好,我爱你{{name}},我是{{xixi()}}
  </div>
    <script>
     let vm = new Vue({
         el : '#app',
         data() {
             return {
                 name : '龚利明',
                 aini : 'type1',
                 h : '100px'
             }
         },
         methods: {
             xixi(){
                 return '刘诗诗'
             }
         },
     })
    </script>
</body>
</html>

v-text 和 v-html

<div v-text="msg"></div>
/*********类似于下边代码**************/
<div>{{msg}}</div>

v-on:

  • 缩写为@
  • @click=“fn()” fn可以加括号和不加括号,最好还是加括号,有的时候要传参
<div v-on:click="makeSomething"></div>
/*********或者下边代码**************/
<div @click="makeSomething"></div>

v-model

v-model的修饰符

  1. trim 清空字符串两边
    • v-model.trim=""
  2. number 自动转化成数字类型
    • v-model.number=""
  3. lazy
    • v-model.lazy=""

双向数据绑定的成品

  1. select选择框
    • 直接把一个空字符串str用v-model绑定在select的标签上,其中option不需要再绑定v-model了,默认select选择的值回事option的value值,但是如果option不设置value的话,那么select默认会把option的innertext的值作为value的值赋值给str这个变量
// 1. 控制select
<select v-model="select">
    <option value="你好">你好</option>
    <option value="北京">你好</option>
    <option value="天津">你好</option>
    <option value="华山">你好</option>
</select>
  1. checkbox复选择框
    • 当只有一个checkbox的时候, 一个isTrue存储true或者false,接着用v-model把isTrue绑定在input表单上,来控制数据的双向绑定
    • 当多个checkbox的时候,我们要存储的就是多个input上的value的值,那么此时就用一个变量arr等于空数组绑定在多个input上
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../vue.js"></script>
</head>
<body>
<div id="app">
    // 1. 一个checkbox的时候处理情况
    <input  type="checkbox" id="box1" v-model="change" value="aaa"><label for="box1">同意该协议
    <p>{{ change }}</p>
    <br>
     // 2. 多个checkbox的时候处理情况
    <input type="checkbox" id="juzi" value="橘子" v-model="choose"><label for="juzi">橘子</label>
    <input type="checkbox" id="apple" value="苹果" v-model="choose"><label for="apple">苹果</label>
    <input type="checkbox" id="banana" value="香蕉" v-model="choose"><label for="banana">香蕉
    <input type="checkbox" id="boluo" value="菠萝" v-model="choose"><label for="boluo">菠萝</label>
    <p>{{ choose }}</p>
</div>
<script>
    let vm = new Vue({
        el:"#app",
        data:{
           change:true,
            choose:[],     // 2. 定义个空数组来存储value的值
        }
    })
</script>
</body>
</html>
  1. radio单选框中使用
<div id="example-4">
  <input type="radio" id="one" value="One" v-model="picked">
  <label for="one">One</label>
  <br>
  <input type="radio" id="two" value="Two" v-model="picked">
  <label for="two">Two</label>
  <br>
  <span>Picked: {{ picked }}</span>
</div>



new Vue({
  el: '#example-4',
  data: {
    picked: ''
  }
})


结果  :  Picked: One

v-for

  • 能够遍历数组 / 对象 / 字符串 / 数字
  • :key的重要性 : 不添加key,那么for循环仅仅是渲染页面

v-if 和 v-show

  • v-if 真正做到删除元素
<div v-if="age < 18">小于18</div>
<div v-elseif="18>小于18</div>
<div v-else>小于18</div>

  • v-show不像v-if一样, v-show做的是控制display是显示还是隐藏

v-once

v-pre

  • 指令不被解析

    ​ 就是说只要标签添加这个属性之后,里边的所有内容就不会执行vue的操作

v-cloak

当页面加载过程中数据还未加载,为了防止页面上很多的vue标签,需要对数据未加载好的进行隐藏, 这里的v-clock需要配合CSS来配合使用

  • 当数据加载之后 v-clock会自动消失
<style>
    [v-clock]{display : none}
</style>

<div v-clock>{{name}}</div>

自定义指令

  • bind 当这个指令绑定在元素上时,触发function这个函数
    • 这个通常用于处理css样式
  • inserted 当这个绑定好指令的元素添加到页面中时触发函数
    • 这里通常处理 focus()等业务
  • update 当这个元素发生跟新的时候触发函数

全局自定义指令

 Vue.directive('color',{
bind : function(el, color){   // 第一个数字必须为元素的元素DOM对象,第二个参数开始为形参
    el.style.color = color.value    // 形参.value才能够获取到传递进来的值
},
inserted :  function(el){}
update : function(el){}`	
})


局部自定义指令

<body>
    <div id="app">
        <p v-demo> {{msg}} </p>
        <p v-aaa="'blue'"> {{msg}} </p>
    </div>
    <script>
        // 定义全局的自定义指令
        Vue.directive('demo', function (el) {
            el.style.color = 'red';
        })

        let vm = new Vue({
            el: '#app',
            data: {
                msg: 'nihao'
            },
            // 定义局部的自定义指令
            directives: {
                aaa: {
                    bind : function (el, color) {
                        el.style.color = color.value;
                    },
                    inserted : function(el){},
                    update : function(el){}
                }
            }
        })
    </script>
</body>

自定义属性的简单版本

// 此时的function表示作用域bind和inserted两个函数
directives : {
                changeColor: function(el){
                    el.style.color = 'red'; }
            }

事件修饰符

@click.prevent
  • 阻止默认行为
@click.stop
  • 阻止事件冒泡
  • @click.stop.prevent="" 也是可以的
@click.capture
  • 事件捕获触发, 从外到里
@click.self
  • 只有当自己触发的时候,才执行,不管是事件捕获还是事件冒泡都不触发
@click.once
  • 只会执行一次
@click.native
  • 应用场景 : 当使用第三方的组件的时候,例如element-ui的input标签,封装好的input是不能直接使用@keyup.enter事件的,因此需要变成 : @keyup.enter.native 才能作用
@click.enter
@click.13
自定义按键修饰符
  • 定义f2

Vue.config.kerCodes.名称 = 按键值

Vue.config.keyCodes.f2 = 113

数据同步与双向绑定 底层原理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="box">
        <input type="text" v-model="name" id="input">
        我叫{{name}},今年{{age}}岁了!
    </div>
    <script>
    // 1. 获取元素
    let box = document.getElementById('box');
    let input = document.getElementsByTagName('input')
    
    // 2.记录模板的的值
    let template = box.innerHTML;

    // 3.渲染的原始data值
    let _data = {
        name : '龚利明',
        age : 18
    }
    // 4.调用perxy监听数据变化
    let data = new Proxy(_data,{
        set(obj,key,value){
            // 让原始的数据变化 
            _data[key] = value
            // 重新渲染这个box的html
            render()
        }
    })
   // 5.一加载就渲染 
    render()

	// 渲染的函数
    function render(){
        box.innerHTML = template.replace(/\{\{\w+\}\}/g,str=>{
            str = str.substring(2,str.length-2)
            return _data[str]
        })
        // 渲染input
        Array.from(input).filter(ele=>{     //  Array.from --> 伪数组转真数组
          return ele.getAttribute('v-model')
       }).forEach(ele=>{
          let nowdata =  ele.getAttribute('v-model')
          ele.value = _data[nowdata];
            // 监听input,从而触发双向绑定
          ele.oninput  = function(){
            data[nowdata] = this.value
       }
       })
    }
    </script>
</body>
</html>

常用的Vue属性方法

data (存储数据)

  1. 创建vm实例对象以后,不会存在vm不会存在data这个属性, data中的所有属性会分别赋值给vm这个实例对象,methods也是如此
  2. 如果是子组件要用 data(return{}) 来编写属性,目的是当多个地方调用这个组件以后,组件内的数据不会共享
  3. 配合插件开发的时候,一个组件之间要在data中申明的,最好用一个对象来存储数据,比较好归类

computed(计算属性)

使用地点 : 购物车使用, 包括统计当前购物车有多少件商品,统计你选中的商品有多少个. 都有个结果输出,此时从computed作为动态属性加载到页面,随时因为数据变化而变化. 通过set方法,当你主动发生数据改变,可以触发事件,比如全选,全不选都由一个按键来控制

优点 :

  1. 具有数据缓存, 当有中大型的计算时候,可以用computed,methods就没有数据缓存,methods虽然也可以作为属性,但是不推荐这么使用.推荐只当触发事件的时候,才调用methods.并且methods没有数据缓存,每当调用一次,都要从新计算
  2. 同时拥有get 和set方法
    • get : 被动触发!!! 当get方法内部有任何属性的改变,就会触发get事件.
    • set : 主动触发!!! 当get触发后数据改变,对set是没有影响的.set方法只有自己手动的触发才有效果!!!

例子 :

<body>
    <div id="app">: <input type="text" v-model="xing"><br>: <input type="text" v-model="ming"><br>
        <p>{{name}}</p>
        <input type="text" v-model="name">
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el : '#app',
            data: {
                xing : '龚',
                ming : '利明'
            },
            computed: {
                // 此处name为对象
                name : {
                    get(){
                        return this.xing + this.ming;
                    },
                    set(value){
                        if(value == ''){
                            return                            
                        }
                        this.xing = value[0];
                        this.ming = value.substring(1)
                    }
                }
            },
        })
    </script>
</body>

watch (监听属性)

  • 使用方法 : 当属性变化时,自动触发watch,并执行里边的函数
  • 组件内部的所有数据都能够监听到,包括 : data computed props传进来的 $route.query $route.params 但是父组件通过ref监听子组件的变化是不行的
  • 应用场景 :
    • 通常用于外部传入的数据进行监听,然后触发事件
<body>
    <div id="app">
        <input type="text" v-model="xing"><br>
        <input type="text" v-model="ming"><br>
        <input type="text" v-model="hobby.chi"><br>
        <p>{{name}}</p>
        <input type="text" v-model="name">
    </div>
    <script src="../js/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                xing: '龚',
                ming: '利明',
                hobby: {
                    chi: '零食',
                    wan: '天津'
                },
            },
            computed: {
                name(){
                    return this.xing + this.ming;
                }
            },
            watch: {
                name(){
                    console.log(this.name);
                },
                'hobby.chi' : function(){
                    console.log('chi变化了!');
                }
            },
        })
    </script>
</body>

$nextTick
  • 数据刷新,在下一次DOM更新后执行回调函数

应用场景 :

  • 当加载第三方插件的时候,需要绑定html创建实例, 但是会存在这种情况 : 请求到的数据已经加载到data中或者还在请求,所以此时数据还没有渲染到html代码上, 但是在js代码会先跳过异步处理的东西,会先执行创建实例的代码, 因此会产生问题. 可以通过$nextTick来让创建实例的js代码延迟到html代码数据渲染完成之后执行

filters (过滤)

作用 : 过滤功能

应用场景 :

  1. 当文字出现一些敏感词汇,就不适合显示在页面上
  2. 给定某个时间, 过滤出好看的时间格式

原理 : 其实和method没啥区别, 单纯的就是为了语义化. 不然都写在methods不太合适

注意事项 : 一个 |, 并不是 ||, 这个不是,仅仅是vue提供的一种格式

{{data | myFormat}}

// 1. 全局过滤

Vue.filter('myFormat',function(data){
    return data + '返回的内容';
})

// 2. 局部过滤

let vm = new Vue({
    el :'#app',
    data : {
        data : 'fuck',
    },
    filters : {
        myFormat(data){
            return data + '返回的内容'
        }
    }
})

axios框架

  • 一个ajax的框架

工作中的token使用(重点)

  1. 账号验证功能已经基本不用cookies了,用的是token, token安全性能强很多
  2. 向服务器发送登录请求之后,服务器会返回token数据,token,不会像cookies一样,token默认不会自己存储在浏览器,发送请求也不会默认携带token. 因此前端工作者需要将这些数据存储到localStorage或者sessionStorage. 当请求数据的时候,要从存储的地方取出来,get方式加载请求头中,post方式加在请求体中发送给服务器
// 登录验证
 http.post(url,sendLogin)
     .then(backdata=>{
                                              // 具体传输位置,看接口怎么写
     window.sessionStorage.setItem("glmtoken",backdata.data.toklen)
 })

  1. 前端需要控制不同路由的跳转, 例如个人中心在没有登录之前是不能跳转过去的,应该打回去到登录界面, 应该需要用token配合路由守卫来使用

登录成功后get方式的请求数据 :

  • Authorization : 发送保存的token
  1. 土方法 (不推荐)
    • 就是挨个的发送的时候,自己带上请求头,并将token带上
axios.get(url,{
    params:{userName : '龚利明', password :'123456'},   // 发送传递数据
    headers: { Authorization: window.sessionStorage.getItem("glmtoken") },   // 发送请求头
})

  1. 工作中用的 (ajax拦截器)
    • 拦截器 : 每一个ajax在发送之前与接收返回之后分别会在第一时间做一个统一的检查功能
    • ajax在发送之前,会统一给请求头添加Authorization,值为本地的token值,没有的话就携带空值发送出去.
    • ajax在接收数据以后, 提前判断收到的数据是什么数据,当判断发送的token错误,或者没有token没有的话,需要让页面跳转到登录界面
// 引入axios
import axios from 'axios'
//引入vue
import Vue from 'vue'
// 引入路由
import Router from '../router/index'

// !!! 设置这个axios的请求跟路径,以后用相对路径就好了,并且暴露出去
export const http = axios.create({
    baseURL: 'http://localhost:8888/api/private/v1/',
})

// 添加请求拦截器
http.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么?
    // 给axios带上请求头:Authorization, 值为token值
    config.headers.Authorization = window.sessionStorage.getItem('glmtoken')
    // 返回ajax全部东西,接着开始发送请求
    return config
  });

// 添加响应拦截器
http.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    if(response.data.meta.msg = '无效token' && response.data.meta.status == 400){
        Vue.prototype.$message.warning('请重新登录!')
        Router.push('/login')
    }else{
        return response;
    }
  });


// 登录验证
http.login = (url,sendLogin)=>{
    return http.post(url,sendLogin)
}

// 左侧菜单获取
http.menus = (url,sendLogin)=>{
    return http.get(url,sendLogin)
}



get方式

  • 传递的参数放在url中
                axios
                    .get(`http://wthrcdn2.etouch.cn/weather_mini?city=${this.city}`)

                    .then(backData => {
                        // 成功的回调函数,参数是响应体
                        console.log(backData);
                    })
                    .catch(error => {
                        // 失败的回调函数(参数是返回的错误信息)
                        console.log('失败了!');
                        console.log(error);
                    })
                    .finally( ()=> {
                        // 这个一般不会用(了解)
                        // 不管成功还是失败,最终都会来调用这个
                        console.log('不管成功还是是失败,你都能看到我哦!');
                    } )


get对象形式传参
axios.get(url,{
    params:{},   // 发送传递数据
    headers: { Authorization: window.sessionStorage.getItem("glmtoken") },   // 发送请求头
})

post方式

使用方法 :

  1. 默认post传输数据的格式有四种 : json / x-www-form-urlencoded / form-data / XML
  2. axios默认的请求方式是json格式
  3. 前台具体传输哪一种数据看后台的要求

重点 : axios传递什么类型数据,请求头的content-type就发送什么类型,关键在于node.js后台需要用不同的方式方式来接收这个数据!!!

前台和后台的分别处理

json格式
  • axios默认前端请求头为 application/json
  • 后台接收需要body-parser插件
  • body-parser中间件设置成json格式 : app.use(bodyParser.json())
// 前端 :  
axios.post('/upload',{data:{name:"glm",age:18}})   // 默认是json格式,所以不需要传递请求头
      .then(function(data){
         console.log('上传成功');
       })

// 后端express :
let express = require('express');
let bodyParser = require('body-parser')  // 引入body-parser框架

let app = express()                      // 开启服务器
app.use(bodyParser.json())               // 设置中间件

app.post('/upload',function(req, res){   
    console.log(req.body);               // 经过中间件层的处理就能够获取到数据
})

app.listen(3000,function(){              // 监听服务器
    console.log('running!');
})

formdata格式
  1. 文件上传需要用到formdata格式
  2. 后台接收需要用multer插件
  3. 前端发送formdata数据,那么在请求头中content-type默认会把json格式转换成formdata格式
//前端 : 
    let fordata = new FormData($('form')[0])
    fordata.append('name','龚利明')

    // 发送ajax请求
     axios.post('/upload',fordata)
     .then(function(data){
         console.log('上传成功');
     })

//后端express :
    let express = require('express');   
    let multer = require('multer');
    let app = express()

    // 设置multer
    let upload = multer({
        dest: './public/img'
    })
    // 接收post的formdata请求
    app.post('/upload',upload.single('img'),function(req, res){
        console.log(req.file);
        console.log(req.body);
    })
    // 监听服务器
    app.listen(3000,function(){
        console.log('running!');
    })

application/x-www-form-urlencoded格式
//前端

    let params = new URLSearchParams();
    params.append('key','d7c82ebd8b304abeacc73b366e42b9ed');
    params.append('info','你好啊');
    // 发送ajax请求
    axios.post('/upload',params)
    .then(function(data){
    console.log('上传成功');
    })

// 后端express

    let express = require('express');
    // 引入body-parser框架
    let bodyParser = require('body-parser')  
    // 开启服务器
    let app = express()       
    // 设置中间件
    app.use(bodyParser.urlencoded({extended:false}))  

	
    app.post('/upload',function(req, res){   
        console.log(req.body);               
    })
     // 监听服务器
    app.listen(3000,function(){             
        console.log('running!');
    })

在vue-cli中的使用

在下面的vue-cli中有介绍

跨域问题处理

  • aixos默认不支持跨域, 在引入axios之后要设置一下

    // 每次请求携带cookies信息
    axios.defaults.withCredentials = true
    
    

动画

单个动画入门

知识点&&注意点

  1. 动画只能够配合 v-if 或者 v-show的消失隐藏来用
  2. 需要消失隐 藏的元素用vue提供的标签transition 来包裹
  3. transition默认为span标签,需要用tag来赋值transition为什么标签
  4. transition中有name属性,来控制css六中状态的样式编写 name的值为多少,就是把v-enter等中的v替换掉

系统默认的六个状态

  1. v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
  2. v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
  3. v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
  4. v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
  5. v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
  6. v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

使用

  • 使用transition可以使用延迟效果, 用animate.css库的时候不能使用动画的延时效果
<style>
    .glm-enter,
    .glm-leave-to{
    	opacity : 0;
        transform : translateX(45px)
     }

	.glm-enter-active,
     .glm-leave-active{
     	transition : all 0.5s       
     }
</style>

 <transition name="glm" tag="div">  
    <p> 你好  </p>
 </transition>
// p标签的消失隐藏用transition来包裹  
// name设定的值和上边的css类的前缀对应,不设置默认为v  

多元素使用

  • 多元素需要将transition-group替换掉transition 用法一样
//css : 
     // 1. 设置进出时候的效果
    .glm-enter,.sweath-leave-to{
      opacity: 0;
      transform: translateX(100px)
    }
	// 2. 设置进去的时候的动画
	.glm-enter-active{
      transition: all 0.5s ease
    }
    // 3. 挨个设置不同的延时时间
  .weather_list div li:nth-child(1){
      transition-delay: 0.2s
    } 
    .weather_list div li:nth-child(2){
      transition-delay: 0.4s
    }
    .weather_list div li:nth-child(3){
      transition-delay: 0.6s
    }
    .weather_list div li:nth-child(4){
      transition-delay: 0.8s
    }
    .weather_list div li:nth-child(5){
      transition-delay: 1s
    } 

// html : 

    

{{ item }}

配合animate.css使用

  1. 导入animate.css文件
  2. 到官网查看想要的动画 https://daneden.github.io/animate.css/
 .sweath-enter-active{
      animation: slideInDown 0.8s ease 
    }
 .sweath-leave-active{
   animation: slideInDown 0.8s ease reverse
  }

ref 功能

ref的两种作用

  1. 当ref作用在一个组件内部的某个标签的时候,并且这个标签并不是component注册好的子组件标签. 通过this.$refs获取到的是这个标签的原生dom元素
  2. 当ref作用在一个组件内部的component定义的子标签的时候, 通过this.refs获取的是这个子组件的Vue实例对象,也就意味着能够直接通过这样来使用子组件的属性或者方法

使用注意事项

  • 一个组件只能获取当前组件的ref ==> 包括原生dom对象.和子组件的Vue实例对象, 不能够获取父组件或者子组件内部定义的ref标签对象

使用

  • 让父子组件分别去访问父子组件内部定义的ref
<body>
    // 子组件son1
    <template id="son1">
        <div ref="son111">
            <button @click="getson1name()">我是son1的按钮</button>
            <div>我是{{name}},我今年{{age}}岁了!</div>
        </div>
    </template>
	// 父组件
    <div id="app">
        <button @click="getson1name()">获取名字</button>
        <son1 ref="son1"></son1>
    </div>
	
    <script src="../js/vue.js"></script>
    <script>
        // 定义子组件模板对象
        let son1 = {
            template : '#son1',
            data() {
                return {
                    name : '龚利明',
                    age : 18
                }
            },
            methods: { // 让子组件点击按钮执行下边代码
                getson1name(){
                    console.log(this.$refs.son111);    // 打印出当前子组件的dom原生对象
                    console.log(this.$refs.son1.name);  // son1是父元素声明的ref,所以不能访问,会报错
                }
            },
        }
		// 父组件实例
        let vm = new Vue({
            el : "#app",
            components:{
                son1
            },
            methods: {
                getson1name(){
                    console.log(this.$refs.son1);  // 不能访问子组件内部的ref
                    console.log(this.$refs.son111.name);  // 打印出子组件的vue实例对象
                }
            },
        })
    </script>
        
    // 总结  :   一个组件只能访问当前组件的原生dom对象

生命周期

什么是生命周期

  • 从Vue实例创建,运行,到销毁期间总是伴随着各种各样的事件,这些事件统称为生命周期
  • 经常使用的生命周期钩子为 created mounted updated

八大钩子函数

创建期间

beforeCreate
  • 实例在内存中刚刚创建出来,此时还没有初始化好data 和methods
created
  • 实例创建完成,能够使用data和methods, 但是还没有开始编译模板
beforeMount
  • 模板在内存中编译完成,但是还没有把模板渲染到页面中,页面中的只是之前写好的模板字符串
mounted
  • 模板编译完成,并且已经将data和methods挂载上去

运行期间

beforeUpdate
  • 状态更新之前执行这个函数, 简单的说就是data,methods等数据已经是最新的了,但是模板上的数据还是旧的数据
updated
  • 此时data和methods等数据在html上渲染完成

销毁期间

beforeDestroy
  • 实例销毁之前调用,这一步的时候实例仍然完全可用
Destroy
  • Vue实例销毁以后调用,调用后,Vue实例指示所有东西自动解绑,所有事件监听器会自动移除,所有子实例也会被消除

组件化

组件化和模块化的区别

模块化 : 是后端业务逻辑的拆分,目的是为了只能单一

组件化 : 根据前端UI来划分的,方便UI的重用

组件的创建方式

这里使用的是全局组件创建, 下边会使用局部组件创建方式

  1. Vue.extend()
// 创建组件模板
let son = Vue.extend({
    template : '

hello world!!

'
}) // 注册组件模板 (注册了才能使用) Vue.component('son',son)
  1. 直接在component中定义对象
Vue.component('son',{
    template : '
你好!
'
})
  1. 使用template标签编写模板
<template id="son">
    <div>
       你好!
    </div>
</template>

Vue.component('son',{
    template : '#son'
})

  1. 最终版本

    <template id="son">
        <div>
           你好!
        </div>
    </template>
    
    let obj = {
        template : '#son'
    }
    
    Vue.component('son',obj)
    
    

局部组件注册

<template id="son">
    <div>
       你好!
    </div>
</template>

let son = {
    template : '#son'
}

new Vue({
    el : '#app',
    components : {
        son :  son ,
    }
})

组件使用的注意事项

  1. component注册好模板后,如果使用的驼峰命名来存储这个组件,在使用这个标签的时候就不能用驼峰名字作为标签了,可以用-来替代大写字母 (反正不不用驼峰就好了)
  2. 创建模板组件的时候,最外面必须要一个盒子包裹起来,在一个盒子里边编写组件

组件使用的注意事项

  1. template这个标签只是一个编写html代码的地方,不能在template这个标签设置样式,页面上只显示template包裹的盒子

组件之间的传参

props 父组件向子组件传递属性或者方法

  • 父组件 : v-bind:属性变量名=“传递的值” ==> 绑定一个变量,变量值为传递给子组件的参数,
  • 子组件: 通过props来接收传递过来的值 ==> props:[‘属性变量名’] ==> 此时可以当做属性来使用
  • props : 用数组去存取 值只可读,不可修改
父组件
<router-view :downSearch="downSearch"></router-view>
子组件
  props: ['downSearch'],   或者  props:{downSearch:String}
   methods: {
     getList(){
       console.log(this.downSearch);
     }
   },

this.$emit() 父组件向子组件传递方法

  • 父组件 : @函数变量名=“函数名” ==> 绑定一个变量,变量值为传递给子组件的函数,
  • 子组件申明一个函数,并在这个函数中执行这行代码 : this.$emit(函数变量名,形参1,形参2) ==> 已经算调用了

注意 : this.$emit的this指向当前子组件, 但是传递过来的函数内部的this还是指向父组件,简单的说就是父组件把自己的一个方法传递给子组件,但是还是在父组件的作用域内执行,父组件只不过是把开关给了子组件,子组件帮父组件开启这个函数,并且也可以把字句的属性作为形参传递给父组件

ref父组件访问子组件的属性与方法

  1. 在父组件中的子组件标签上绑定ref标签
  2. 在父组件中的方法中使用 this.refs.绑定的ref名字获取这个东西
  3. 详情见上边的ref总结

总结 : 反正都用props和ref就好了!!!

router(路由)

使用#的好处

  • # 英文(hash) 俗称哈希,锚点
  1. 浏览器窗口可以前进后退
  2. 刷新可以保持不动
  3. 非常适合单页面网页

一级基本使用步骤

  1. 声明 router-view 和 router-link
    • router-view : vue提供的占位置标签,可以存放组件
    • router-link : 跳转的标签,控制router-view标签里存放哪个注册好的组件
      • to : 指的是跳转到哪个组件,具体的哪个组件通过路由表中的path来区别
      • router-link类似于a标签, to="/aaa" 类似于 href="#aaa"
      • 当选中这个标签时,默认会有两个类 : router-link-active 和 router-link-exact-active 可以作为设置css样式,建议使用router-link-active来设置样式
 <div id="app">
        我是标题
        <router-link to="/aaa">aaa</router-link>
        <router-link to="/bbb">bbb</router-link>
        <router-link to="/ccc">ccc</router-link>
        <router-view></router-view>
    </div>

  1. 导入路由模块
  • 当导入这个插件的时候,在window默认就有一个VueRouter的构造函数了

  1. 编写组件
// 组件aaa
<template id="aaa">
<div>
    aaaaa
 div>
template>

// 组件bbb
<template id="bbb">
<div>
    bbbbbb
 div>
template>

// 组件模板ccc
<template id="ccc">
<div>
    cccccc
 div>
template>

// 定义对象组件模板
ccc = {
template : '#ccc'
}

  1. 编写路由表
let router = new VueRouter({
    routes :[
        {path : '/aaa', component : {template : '#aaa'}},
         {path : '/bbb', component : {template : '#bbb'}},
         {path : '/ccc', component : ccc},    //   c-cli脚手架就是这么用的
        {path : '/', redirect : '/aaa'}
    ]
})

  1. 创建的路由实例对象挂载到vue的实例上,让两者有关联
let vm = new Vue({
    el : 'app',
    router : router
})
// 或者直接简写 :  router : touter  ==>  router

使用注意事项

  1. 不管是局部组件注册还是路由表组件的注册,都是需要让字符串模板先进行注册才能使用
  2. router-view可以设置样式,设置的样式会和template中的最外层盒子的行内样式叠加在一起,并且router-view的权重会比组件内部设置的样式权重大, 相当于组件内部写的样式是默认样式, 在router-view调用之后,样式被改掉了. 建议用一个div盒子包裹router-view来操作css样式!

router-link的选中类:active-class

  • 在选中某个router-link之后,虽然会有route-link-active这个类用于修改选中后的css样式,但是这样不实用。
  • 某个router-link选中以后有一个行内属性 active-class这个属性记录的内容会自动添加到class中,用于修改这个router-link的css样式
<router-link class="bar-item" active-class="active" to="/result">搜索结果</router-link>
<router-link class="bar-item" active-class="active" to="/player">歌曲播放</router-link>
<router-link class="bar-item" active-class="active" to="/mv">mv</router-link>
<router-link class="bar-item" active-class="active" to="/comment">歌曲评论</router-link>

控制路由跳转

to配合router-link

  1. name可有可无,但是如果想通过name来控制路由则在to前边必须绑定v-bind:
html :
<router-link :to="{name : 'news'}">aaa</router-link>
// 或者下边的
<router-link to="/login">aaa</router-link>    // 必须是绝对路径
js:
let router = new VueRouter({
    routes :[
        {path : '/aaa',
         name  : 'news',
         component : {template : '#aaa'}
        },
    ]
})

js控制

this. r o u t e r . p u s h ( ) 或 者 t h i s . router.push() 或者 this. router.push()this.router.replace()

两者区别 : push能使用浏览器的前进后退, replace是直接替换掉最后一个,所以没有前进后退,使用方法是根据具体情况来使用,通常同级路由有replace,父子之间用push

有以下两种办法写在methods中 :

  • this.$router.push(’/news/19’)
  • this.$router.push({name : ‘news’, params : { id : 19 } } )
let router = new VueRouter({
    routes :[
        {path : '/news/:id',
         name  : 'news',
         component : {template : '
传递进来的参数id为 : {{$route.params.id}}
'
} }, ] })

路由传参

  1. 当路由挂载到vm实例对象上的时候, vm实例对象和子组件就会有 r o u t e 这 个 属 性 , 但 是 此 时 如 果 u r l 没 有 跳 转 到 任 何 一 个 子 组 件 , 那 么 这 个 时 候 v m 和 子 组 件 的 route这个属性, 但是此时如果url没有跳转到任何一个子组件,那么这个时候vm和子组件的 route,url,vmroute都没有参数.因为没有跳转
  2. 当vm这个实例点击了其中某一个path, router-view显示了某个子组件的内容,那么此时的vm实例和子组件这个实例对象上的$route属性都会有值

注意 : $route主要要用的两个参数就是 query 和 params 两者的传参性质不太一样.但是目的都是为了父组件向子组件传值.

url的query获取

直接在url上传参, query本来就是获取url的传参的方式

  1. router-link标签的to属性绑定 v-bind: 且用字符串拼接操作作为get方式的传参
  2. 在子组件中通过 this. r o u t e 来 调 用 传 进 来 的 参 数 , 类 似 于 t h i s . route 来调用传进来的参数,类似于this. route,this.refs是一样的

使用

<body>
    <div id="app">
        <h1>我是主界面</h1>
        //  可以通过两种字符串拼接作为传参的方式
        <router-link :to="'/login?id='+ id">去登陆</router-link> 
        <router-link :to="`/register?name=${name}`">去注册</router-link> 

        <router-view></router-view>
    </div>
</body>
<script src="../js/vue.js"></script>
<script src="../js/vue-router-3.0.1.js"></script>
<script>
    // 1. 定义一个子组件
    let login = {
        template : `

我是登录

{{$route.query.id}}

`
} let register = { template : `

我是注册

{{$route.query.name}}

`
} // 2. 定义路由表 let router = new VueRouter({ routes : [ {path : '/login', component : login}, {path : '/register', component : register}, {path : '/', redirect : '/login'} ] }) // 3. 创建父组件的vue实例 let vm = new Vue({ el : '#app', data() { return { id : 20, name : '龚利明' } }, // 3.1挂载路由 router }) </script> </html>

params获取

  • 直接將数组做为路由来传递

使用方法 : 看下边的例子说明

例子 :

  1. 让 routes 中的path变成 : /login/:id/:name ==> id和name是想子组件传值过来
  2. 在router-link中to属性 : to="/login/123456/龚利明"
  3. 最终在子路由组件中通过 this. r o u t e . p a r a m s . i d 和 t h i s . route.params.id 和 this. route.params.idthis.route.params.name来获取传递过来的值
<body>
    <div id="app">
        <h1>我是主界面</h1>
        <router-link to="/login/123456/龚利明">去登陆</router-link>       
        <router-link to="/register">去注册</router-link> 

        <router-view></router-view>
    </div>
</body>
<script src="../js/vue.js"></script>
<script src="../js/vue-router-3.0.1.js"></script>
<script>
    // 1. 定义一个子组件
    let login = {
        template : `

我是登录

{{$route.query.id}}

`
} let register = { template : `

我是注册

{{$route.query.name}}

`
} // 2. 定义路由表 let router = new VueRouter({ routes : [ {path : '/login/:id/:name', component : login}, {path : '/register', component : register}, {path : '/', redirect : '/login'} ] }) // 3. 创建父组件的vue实例 let vm = new Vue({ el : '#app', data() { return { id : 20, name : '龚利明' } }, // 3.1挂载路由 router }) </script> </html>

获取当前路由 this.$route.path

  • this.$route

二级路由

import Vue from 'vue';
import VueRouter from 'vue-router';

// 引入包
import Home from '../pages/home/Home.vue'
    import Hot from '../pages/home/children/Hot.vue'
    import Good from '../pages/home/children/Food.vue'
    import Girl from '../pages/home/children/girl.vue'
    import Liming from '../pages/home/children/Liming.vue'
    import Love from '../pages/home/children/Love.vue'
    import Machine from '../pages/home/children/machine.vue'
    import Many from '../pages/home/children/Many.vue'
    import Neiyi from '../pages/home/children/Neiyi.vue'
    import Shoose from '../pages/home/children/Shoose.vue'
    import SmallGirl from '../pages/home/children/SmallGirl.vue'
    import Wbaobao from '../pages/home/children/Wbaobao.vue'
    import Xidada from '../pages/home/children/Xidada.vue'
import Chat from '../pages/chat/Chat.vue'
import Mine from '../pages/mine/Mine.vue'
import Recomment from '../pages/recomment/Recomment.vue'
import Search from '../pages/search/Search.vue'
// 注册路由
Vue.use(VueRouter);

export default new VueRouter({
    routes : [
        {path : '/home',component:Home,
        children:[
            {path:'hot',component:Hot},
            {path:'good',component:Good},
            {path:'girl',component:Girl},
            {path:'liming',component:Liming},
            {path:'love',component:Love},
            {path:'machine',component:Machine},
            {path:'many',component:Many},
            {path:'neiyi',component:Neiyi},
            {path:'shoose',component:Shoose},
            {path:'smallGirl',component:SmallGirl},
            {path:'wbaobao',component:Wbaobao},
            {path:'xidada',component:Xidada},
            {path:'',redirect:'hot'},  // 二级路由的redirect和path要注意
        ]
    },
        {path : '/chat',component:Chat},
        {path : '/mine',component:Mine},
        {path : '/recomment',component:Recomment},
        {path : '/search',component:Search},
        {path : '/',redirect:'/home'},
    ]
})

路由守卫

作用 : 网页有些路由界面必须要先登录才能加载,此时可以通过路由守卫来进行预处理,当登录后,允许跳转到相应界面,未登录,则跳转到登录界面…

一般都使用全局路由!!!

使用 :

  1. 局部路由守卫
import Vue from 'vue'
import VueRouter from 'vue-router'
import axios from 'axios'
Vue.use(VueRouter)

// 引入组件
import Main from '../views/main.vue'
import GoodsInfo from '../views/GoodsInfo.vue'
import Login from '../views/Login.vue'
import Vip from '../views/vip.vue'
let router =   new VueRouter({
    routes : [
        {path:'/main',component:Main},
        {path:'/goodsinfo',component:GoodsInfo},
        {path:'/login',component:Login},
        {path:'/vip',
        component:Vip,
         // 跳转到 '/vip'路由之前开启这个函数
        beforeEnter(to,from,next){
            // 发送请求,判断是否登录
            axios.get('site/account/islogin')
            .then(callback=>{
                // 如果登录,则允许访问
                if(callback.data.code == 'logined'){
                    console.log(callback.data.code);
                    
                    next()
                }
                else{
                    // 没有登录,跳转到登录界面
                    router.push('/login')
                }
            })
        }
    },
        {path:'/',redirect:'/main'},
    ]
})

export default router

  1. 全局守卫

全局守卫 : 让所有的路由跳转之前先判断是否登录

使用方法 :

  1. 用路由元信息meta开控制哪个需要登录验证
import Vue from 'vue'
import VueRouter from 'vue-router';

import Login from '../views/login/Login.vue';
import Main from '../views/main/main.vue'
    import User  from '../views/main/children/user.vue'

Vue.use(VueRouter)

const Router = new VueRouter({
    routes: [{
            path: '/login',
            component: Login
        },
        {
            path: '/main',
            component: Main,
            // meta  记录main需要验证
            meta: {
                requiresAuth: true
            },
            children:[
                {
                    path : '/users', component : User,
                }
            ]
        },
        {
            path: '/',
            redirect: '/main'
        }
    ]
})
// 全局路由守卫
Router.beforeEach((to, from, next) => {
    // 判断跳转到的路由是否需要验证
    if (to.meta.requiresAuth) {
        // 判断是否有在存储的token信息
        if (window.sessionStorage.getItem('glmtoken') != null) {
            next()
        } else {
            // 没有token信息,跳转回登录页面
            Vue.prototype.$message({
                message: "请重新登录!",
                type: "warning"
            })
            Router.push('/login')
        }
    } else {
        // 不需要验证的路由,直接跳转到该路由
        next()
    }
})

export default Router

统一错误页 404

在一级路由最下边注册一个path 为*, 并且component为自己设置的error界面

[外链图片转存失败(img-NaV9meLV-1569292941630)(/1564125937094.png)]

  1. error.vue界面
<template>
  <div class="makeLove">
    <h1>找不到服务器,404报错了哦!!!!!!h1>
  div>
template>
<script>
script>
<style scoped lang="less">
.makeLove {
  width: 100%;
  height: 100%;
  position: absolute;
  z-index: 999999;
  left: 0;
  top: 0;
  h1 {
    position: absolute;
    left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  }
}
style>


  1. 路由文件

    通过 * 来搞定

import Vue from 'vue';
import VueRouter from 'vue-router';

// 引入包
import Home from '../pages/home/Home.vue'
import Chat from '../pages/chat/Chat.vue'
import Mine from '../pages/mine/Mine.vue'
import Recomment from '../pages/recomment/Recomment.vue'
import Search from '../pages/search/Search.vue'
import Error1 from '../components/error/Error.vue'
// 注册路由
Vue.use(VueRouter);

export default new VueRouter({
    routes : [
        {path : '/home',component:Home},
        {path : '/chat',component:Chat},
        {path : '/mine',component:Mine},
        {path : '/recomment',component:Recomment},
        {path : '/search',component:Search},
        {path : '/',redirect:'/home'},
        // 通过 * 来搞定
        {path : '*',component : Error1},
    ]
})

脚手架 vue-cli

安装vue-cli

  1. 需要安装node.js
  2. 安装全局的vue-cli : npm i -g @vue/cli ------------@的意思是最新版

创建工程

  1. 创建一个保存工程的文件夹,进入这个文件夹控制命令行 vue create 项目名字
  2. 进入到这个模式 : default:默认 Manually select features : 自定义安装 选择自定义安装

[外链图片转存失败(img-ucNMDUeg-1569292941630)(/1563615247820.png)]

  1. 进去到下边这个界面 : 空格是选中,

    [外链图片转存失败(img-xvoyN3b7-1569292941631)(/1563615445145.png)]

  2. 接着进入各种默认选择, 我选less 其它的选择还不怎么懂。 跳过跳过!

    [外链图片转存失败(img-xP6xDLgy-1569292941632)(/…/…/…/…/…/AppData/Roaming/Typora/typora-user-images/1563615572895.png)]

  3. 最后安装就好了

基本使用

书写规范

  1. 所有的组件名字都要大写开头,遵循大驼峰命名
  2. 所有的组件被引入的时候也都要大写,组件注册,组件使用都要用大驼峰布局,并且保持单词都一样
  3. 组件注册好后,作为标签使用的时候,首字母可以大写,后边的大写字母变成 -
  4. 所有第三方包引入都要首字母大写 import Vue from ‘vue’
  5. 所有的自己写的js文件都遵循小驼峰命名
  6. 所有的文件夹都是小驼峰命名
  7. router.js
    • 使用注意 :
      1. 需要用Vue.use(Router)
      2. 可以进行懒加载,但是我觉得不提倡
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
    }
  ]
})


  1. main.js
    • 使用注意 :
      1. render 就是相当于 template:App,将index.html文件中的#app替换掉 ---------结合生命周期来理解
      2. $mount 相当于 el
      3. Vue.config.productionTip = false ==》 在控制台中少输出一段乱七八糟的提示
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

  1. App.vue
<template>
 <div id="app">
    <div class="tab-wrapper">
      <!-- tab栏 -->
      <div class="tab-bar">
        <router-link class="bar-item" active-class="active" to="/result">搜索结果</router-link>
        <router-link class="bar-item" active-class="active" to="/player">歌曲播放</router-link>
        <router-link class="bar-item" active-class="active" to="/video">mv</router-link>
        <router-link class="bar-item" active-class="active" to="/comment">歌曲评论</router-link>
      </div>
      <!-- 对应的内容区域 -->
      <div class="tab-content" @click="getAxios()">
        <router-view></router-view>
      </div>
    </div>
  </div>
 </div>
</template>
<script>
 export default {
   methods: {
     getAxios(){
     }
   },
 }
</script>

<style scoped lang="less">
    @import url('./assets/css/comment.css');
</style>


axios

使用方法一 :

  1. 下载包 : npm i axios -D

  2. 把aixos注册到vue构造函数的原型上

    import Vue from 'vue';
    import axios from 'axios'
    Vue.prototype.axios = axios;
    
    
  3. 在组件对象中使用需要使用this,因为组件对象的是由Vue构造函数创建的,通过原型链可以访问到Vue构造函数的原型对象上的方法

使用方法二 :

  1. 下载包 :

    npm i axios -D

    npm i vue-axios -D

  2. use作用起来

import Vue from 'vue';
import axios from 'axios';
import VueAxios from 'vue-axios';

Vue.use(VueAxios,axios)

如此, 可以了把axios对象添加到Vue实例的原型上

vuex

作用 : 将数据存储在一个地方,方便任何的子组件来操作这些数据.直接通过一些vuex的API就可以操作

操作流程图

[外链图片转存失败(img-iIrtbgG1-1569292941633)(/1563702212403.png)]

挨个文件的操作

项目打包

  • 执行npm run bulid
  • 会产生一个dist的文件夹,需要的东西会都在里边

手动配置 vue.config.js文件,这个文件需要自己在根目录下创建

// vue.config.js
module.exports = {
  // 打包的根路径 使用的是相对
  publicPath:'./',
  // 移除map文件
  productionSourceMap:false,
}

项目首次加载提速方法

路由懒加载

作用 :

  1. 首次加载不会把全部js都一起导入,优化了第一次进入页面的性能,把时间分散化
  2. 用户可能不需要浏览每一个组件,可以帮用户节省浏览

[外链图片转存失败(img-g0FavIyJ-1569292941633)(/1564988895067.png)]

cdn加速

作用 : 把npm下载的vue / element-ui / aixos等框架通过cdn网络的形式导入,打包的时候就不用打包自己npm下载的这些库了, 大大减少了压缩后的文件大小.

使用 :

  1. 配置vue.config.js文件

    // vue.config.js
    module.exports = {
      // 打包的根路径 使用的是相对
      publicPath:'./',
      // 移除map文件
      productionSourceMap:false,
      // 和import Vue from 'vue' 中的Vue要对上号,但是element例外
      externals: {
          'vue':'Vue',
          'vue-router':"VueRouter",
          'axios':'Axios',
          'element-ui':"ELEMENT"
        }
    }
    
    
  2. 网络第三方库查找

    1. bootcdn
    2. 模块的官网

cdn介绍:

  1. cdn就是一个多台电脑形成的一个服务器网络,不同的用户访问同一个服务器,服务器会根据访问者的信息,分配一台网络节点电脑来和用户通信.
  2. 举个例子 : 当我们在广东和天津分别访问www.baidu.com的时候,cdn会进行解析一个ip作为访问的服务器. 但是我们会发现这两个ip地址不一样.

[外链图片转存失败(img-HPhlrsFi-1569292941633)(/1564989748634.png)]

提升访问速度的方法

  1. 提神服务器的带宽
  2. 使用静态资源服务器 ==> 将一个网站的静态资源专门用一个服务器存放 ==> 常见的 七牛云
  3. webp图片格式
  4. 减少http请求
  5. 精灵图
  6. 懒加载
  7. base64
  8. 少用递归,闭包,全局变量,循环嵌套等

常用插件

修改插件样式

[外链图片转存失败(img-AoA4ZRi0-1569292941634)(/1563873186960.png)]

步骤

  1. F12, 查看当前你要修改的这个插件有啥class类
  2. 利用 自己的div类 /deep/ 插件的类 来修改

scoped /deep/

scoped : 当子组件设置了scoped, 父子组件相同的类设置了同一个样式, 当有冲突,最后加载的样式以子组件为主. 父组件新增的样式,要满足子组件没有设置,就可以作用了, 因此,当调用第三方组件,想对样式修改,是不能直接作用上去的. 必须通过/deep/来深度设置, 那么就可以覆盖掉子组件原本设置的样式了.

moment 时间处理

  1. 安装

    ​ npm install moment --save

  2. 引入和使用

在main.js中 导入组件
import moment from 'moment'

Vue.filter('FormateTime', function(dataStr, pattern = 'YYYY-MM-DD') {
    return moment(dataStr).format(pattern)
})

Element-ui ---- PC端ui框架

安装

  1. 下载插件 : npm i element-ui -D 或者在创建工程的时候下载
vue create my-app
cd my-app
vue add element

  1. 引入和设置参数(全局或者按需引入)

    2.1 全局

    import Vue from 'vue';
    import ElementUI from 'element-ui';
    import 'element-ui/lib/theme-chalk/index.css;
    Vue.use(ElementUI);
    
    

    2.2 按需引入

    import Vue from 'vue';
    import { Button, Select } from 'element-ui';
    Vue.use(Button)
    Vue.use(Select)
    
    // 设置  babel.config.js
    
    {
      "plugins": [
        [
          "component",
          {
            "libraryName": "element-ui",
            "styleLibraryName": "theme-chalk"
          }
        ]
      ]
    }
    
    

Pagination 分页器

[外链图片转存失败(img-THrZg2o7-1569292941634)(/1563793440542.png)]

html :

      
      el-pagination>
					small :                     // 小一点

Form表单

  • model : 绑定的data对象
  • status-icon : 显示提示的图标
  • rules :绑定的data规则对象
  • label-width : label宽度
  • label-position : 靠左 上 右
  • label : label绑定的文字
  • prop : 绑定rules中的规则属性

注意 : 1. prop=“name” 和 v-model=“ruleForm.name” 在data中名字要一样

自定义规则: 正则使用

  1. 推荐方法 : { pattern:/^1[3456789]\d{9}$/, message: '请输入正确手机号码', trigger: 'blur' }

    ​ 官网没有 pattern 这个属性, 我是在百度查到的,反正可以用, 直接在pattern 里边写正则

  2. 复杂点的 : { validator: checkPhone, trigger: 'blur'}

    ​ validator可以绑定自定义的方法来验证, 具体看下边例子。 反正我觉得没上边的简单

<template>
 <div class="login">
   <div class="login_main">
     <h2>利明后台管理登录</h2>
     <el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm" label-position="top">
  <el-form-item label="账号" prop="name">
    <el-input type="text" v-model="ruleForm.name" autocomplete="off"></el-input>
  </el-form-item>
  <el-form-item label="密码" prop="password">
    <el-input type="password" v-model="ruleForm.password" autocomplete="off"></el-input>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="submitForm('ruleForm')" class="login_btn">登录</el-button>
  </el-form-item>
</el-form>
   </div>
 </div>
</template>

<script>
 export default {
    data() {
       var checkPhone = (rule, value, callback) => {
        if (!(/^1[3456789]\d{9}$/.test(value))) {
          return callback(new Error('输入正确的手机号码'));
        }
      };
      return {
        ruleForm: {
          name: '',
          password: '',
        },
        rules: {
          name: [
            { required: true, message: '请输入账号', trigger: 'blur' },
             { validator: checkPhone, trigger: 'blur'}{ pattern:/^1[3456789]\d{9}$/, message: '请输入正确手机号码', trigger: 'blur' },
          ],
          password: [
            { required: true, message: '请输入密码', trigger: 'blur' }
          ]
        }
      };
    },
    methods: {
      submitForm(formName) {
        this.$refs[formName].validate((valid) => {
          if (valid) {
		// 验证成功在这里发送ajax请求
          } else {
            console.log('error submit!!');
            return false;
          }
        });
      },
    }
  }
 
</script>

<style scoped lang="less">
.login{
  width: 100%;
  height: 100%;
  background: rgb(50, 65, 82);
  display: flex;
  align-items: center;
  justify-content: center;
  .login_main{
    h2{
      display: flex;
      align-items: center;
      justify-content: center;
    }
    width: 580px;
    height: 400px;
    padding: 30px;
    background: #fff;
    border-radius: 8px;
    box-sizing: border-box;
    .login_btn{
      width: 100%;
      margin-top: 20px;
      background: skyblue;
    }

    /deep/ label{
      font-size: 18px;
    }  

    /deep/ input{
      height: 50px;
    } 
  }
}
 
</style>


修改css样式

  • 看着不爽直接用 /deep/锁定标签名字 input 或者 label直接修改

表单中创建表单

  • 具体看官网 https://element.eleme.cn/#/zh-CN/component/form

拼多多项目

项目准备

  1. 项目排布

    [外链图片转存失败(img-t9tVFnF8-1569292941635)(/1563875250020.png)]

正式开始

起步

问题一 : 自定义控制路由转化

[外链图片转存失败(img-ifUncfda-1569292941635)(/1563883682659.png)]

  1. 加载本地文件的url需要通过require来导入,经过webpack一系列的操作 反正具体不懂! 记住就好… 网络请求的不会这样
  2. 路由也可以直接通过a标签的href属性直接设置.

问题二 : body和html可以都设置宽高百分之百来撑开

首页问题

问题一 : ly-tab插件的使用

很简单,进npm官网看 https://www.npmjs.com/package/ly-tab

  1. 下载包 npm i ly-tab -D

  2. 引入注册

    import Vue from 'vue'
    import LyTab from 'ly-tab'
    Vue.use(LyTab)
    
    
  3. 使用

    html :
    <ly-tab
        v-model="selectedId"
        :items="items"
        :options="options"
        @change="setPath"
        >
     </ly-tab>
    
    js
    
    
    
    

swiper框架使用

debugger使用

  • 直接在js内部使用debugger来打断点,可以查看数据 当跳不到这个断点的时候,只能说明,代码还没有执行到这里就报错了

数据异步请求 v-if的使用

  • 等得到了数据,再加载html代码。防止出错!

标签只要是数据异步请求获得的,然后要渲染到html中(多半是第三方组件),都要加上v-if 防止发生错误。。 例如在swiper中,通过v-for渲染的img,loop属性需要

better-scroll使用

简单使用

上拉加载 下拉刷新

你可能感兴趣的:(vue个人总结--喜欢的点赞哟!)