Vue——前端学习的必经之路,是一套用于构建用户界面的渐进式框架。只关注视图层,易于上手。

前言:" 今生遇汝,何其幸哉;于我蒙昧之时遇到你,于我大雾初透之时爱上你,于我大智初醒之时沉沦你。 "

官网: 介绍 — Vue.js (vuejs.org)

指令与修饰符

创建实例

<div id="app">
  {{ message }}
</div>
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

结果 Hello Vue!

v-html

    <div id="box">
        <!-- v-html -->
        <div v-html="myhtml"></div>
    </div>

    <script type="text/javascript">
        new Vue({
            el: "#box",
            data: {
                myhtml: "<b>1111</b>"
            }

        })
    </script>
v-html,防止xSS,csrf (
	(1)前端过滤
	(2)后台转义(< > &lt;&gt;)
	(3)给cookie加上属性http
)

v-cloak与v-text

  • 使用 v-cloakv-text 与能够解决插值表达式闪烁的问题
<p v-cloak>{{msg}}</p>
<p v-text="msg"></p>

//=====
<style>

  [v-cloak]{
      display: none;
  }  
    
</style>

v-show 与 v-if

    <div id="box">
        <div v-show="isShow">动态显示与隐藏</div>
        <div v-if="isCreated">动态创建与删除</div>

    </div>

    <script type="text/javascript">
        new Vue({
            el: "#box",
            data: {
                isShow: false,
                isCreated: true
            }
        })
    </script>

vue-class 绑定

    <div id="box">
        <div :class="isActive?'red':'yellow'">
            我的样式是动态切换的!----三目写法
        </div>
        <button @click="handleClick()">click</button>
        <div :class="classObj">
            我的样式是动态切换的!----对象写法
        </div>
        <div :class="classArr">
            我的样式是动态切换的!----数组写法
        </div>
    </div>

    <script type="text/javascript">
        new Vue({
            el: "#box",
            data: {
                isActive: true,
                classObj: {
                    a: true,
                    b: true
                }, // a,b 为class名称
                classArr: ["a","b"]
            },
            methods: {
                handleClick() {
                    this.isActive = !this.isActive
                }
            }

        })
    </script>

vue-style 绑定

    <div id="box">
        
        <button @click="handleClick()">click</button>
        <div :style="'background:'+isActive?'red':'yellow'">
            我的样式是动态切换的!----三目写法
        </div>
        <div :style="styleObj">
            我的样式是动态切换的!----对象写法
        </div>
        <div :style="styleArr">  
            我的样式是动态切换的!----数组写法
        </div>
    </div>

    <script type="text/javascript">
        new Vue({
            el: "#box",
            data: {
                isActive: true,
                styleObj: {
                   backgroundColor: "red"
                }, 
                styleArr: ["a","b"]  //建议使用数组  shift()删除所有的样式
            },
            methods: {
                handleClick() {
                    this.isActive = !this.isActive
                }
            }

        })
    </script>

vue 条件渲染

    <div id="box">

        <button @click="handleClick()">click</button>
        <div v-if="isCreated">动态的创建与删除----111</div>
        <div v-else>动态的创建与删除----222</div>
        <!-- 实例 -->
        <ul v-if="dataList.length">
            <li v-for="data in dataList">
                {{data}}
            </li>
        </ul>
        <div v-else>空空如也</div>


    <div v-if="which==1">111</div>
    <div v-else-if="which==2">222</div>
    <div v-else>333</div>

</div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#box",
            data: {
                isCreated: true,
                dataList: [],
                which: 1
            },
            methods: {
                handleClick() {
                    this.isCreated = !this.isCreated,
                        this.dataList = ["111", "2222"]
                }
            }

        })
    </script>

vue 列表渲染

    <div id="box">
        <ul>
            <li v-for="(data,index) in dataList">
                {{data}}----{{index}}
            </li>
        </ul>

        <ul>
            <li v-for="(data,index) of dataList">
                {{data}}----{{index}}
            </li>
        </ul>

        <ul>
            <li v-for="(data,key) in dataObj">
                {{data}}----{{key}}
            </li>
        </ul>


    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#box",
            data: {
                dataList: ["111", "2222", "333"],
                dataObj: {
                    name: "qiandu",
                    age: 18,
                    sex: "男"
                }
            }
        })
    </script>

vue 列表key值设置

跟踪每个节点的身份,从而重用和重新排序现有元素

理想的 key值是每项都有的且唯一的id。data.id

列表数组检测

a.使用以下方法操作数组,可以检测变动

  push()  pop()   shift()    unshift()  splice() sort()    reverse()

b. filter(), concat() 和 slice() ,map(),新数组替换旧数组

c.不能检测以下变动的数组

  • vm.items [ indexOfltem] = newValue

  • 解决 (1) Vue.set(example1.items, indexOfltem, newValue)

    ​ (2)splice

过滤--模糊查询

 <div id="box">

        <input type="text" @input="handleInput()" v-model="mytext" />
        <!-- @change 只要失去焦点就会触发 -->
        <ul>
            <li v-for="data in dataList">
                {{data}}
            </li>
        </ul>

    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#box",
            data: {
                mytext: '',
                dataList: ["111", "2222", "333"],
            },
            methods: {
                handleInput() {
                    // console.log("只要value改变 就会触发");
                    //利用输入框的字符,过滤包含字段的元素
                    //filter 过滤

             var newList = this.dataList.filter(item => item.indexOf(this.mytext) > -1);
                    console.log(newList);

                   /*  改变列表值 有两种方法  
                   
                            1. 复制一份数组  List: ["111", "2222", "333"]
        var newList = this.List.filter(item => item.indexOf(this.mytext) > -1);
                            this.dataList = newList;
                            2. 计算属性 后期使用
                   */
                }
            }
        })
    </script>

事件处理器

Vue2.0 基础入门_ios

    <div id="box">

        <!-- 无需参数 -->
        <button @click="handleClick()">click1</button>
        <!-- 需要参数 -->
        <button @click="handleClick">click2</button>
        <!-- 语句简单 尽量避免 -->
        <button @click="isCreated = !isCreated">click3</button>
        <div v-show="isCreated">动态的创建与删除----111</div>

</div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#box",
            data: {
                isCreated: false,
            },
            methods: {
                handleClick() {
                    this.isCreated = !this.isCreated;
                }
            }

        })
    </script>

事件修饰符

    <div id="box">
        <!-- 点自己才会触发 -->
        <ul @click.self="handleULClick">
            <li @click.stop="handleLiClick"> 111</li>
            <li @click.once="handleLiClick"> 222</li>
            <li @click="handleLiClick"> 111</li>
        </ul>

        <a href="www.baidu.com" @click.prevent="handleChangePage">changePage</a>

    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#box",
            data: {
                isCreated: false,
            },
            methods: {
                // handleClick() {
                //     this.isCreated = !this.isCreated;
                // }
                handleLiClick(ev) {
                    //  ev.stopPropagation(); 原生
                    console.log("111");
                },
                handleULClick() {
                    console.log("222");
                },
                handleChangePage(ev) {
                   //   ev.preventDefault();  阻止默认
                    console.log("333")
                }
            }
        })
    </script>

按键修饰符

 <div id="box">

        <a href="www.baidu.com" @click.prevent="handleChangePage">changePage</a>

        <!-- 键值也可以 -->
        <input type="text" @keyup.enter="handleULClick($event)" />

    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#box",
            data: {
            },
            methods: {
                handleULClick() {
                    console.log("222");
                    //传统方法
                    // if (ev.keyCode === 13) {
                    //     //....13表示回车键
                    // }

                },
            }
        })
    </script>

表单控件绑定

   <div id="box">
        <input type="text" v-model="mytext">
        <textarea name="" id="" cols="30" rows="10" v-model="mytext"></textarea>
        {{mytext}}
        <br>
        <input type="checkbox" v-model="isChecked">记住我
        <br>
        <p>你喜欢的运动为:
            <input type="checkbox" v-model="checkgroup" value="游泳" />游泳
            <input type="checkbox" v-model="checkgroup" value="滑冰" />滑冰
        </p>
        {{checkgroup}}
        <br>
        <p>你最喜欢的运动为:
            <input type="radio" v-model="picked" value="游泳" />游泳
            <input type="radio" v-model="picked" value="滑冰" />滑冰
        </p>
        {{picked}}

    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#box",
            data: {
                mytext: "aaaa",
                isChecked: true,
                checkgroup: [],
                picked: ""
            }
        })
    </script>

购物车案例

    <div id="box">
        <input type="checkbox" @change="handleChange" v-model="isAllChecked">
        <ul>
            <li v-for="data in dataList">
                <input type="checkbox" v-model="checkGroup" :value="data" @change="handleLiChange">
                {{data}}
                <button @click="data.number++">add</button>
                {{data.number}}
                <button @click="handleDelClick(data)">del</button>
            </li>
        </ul>
        {{checkGroup}}
        <p>总金额为:{{getSum()}}</p>
    </div>
    <script type="text/javascript">
        new Vue({
            el: "#box",
            data: {
                checkGroup: [],
                isAllChecked: false,
                dataList: [
                    {
                        name: "商品1",
                        price: 10,
                        number: 1,
                        id: "1"
                    },
                    {
                        name: "商品2",
                        price: 20,
                        number: 4,
                        id: "2"
                    }
                ]
            },
            methods: {
                getSum() {
                    //函数计算的状态改变,会自动执行一次
                    var sum = 0;

                    for (var i in this.checkGroup) {
   sum += this.checkGroup[i].number * this.checkGroup[i].price;
                    }
                    return sum;
                },
                handleChange() {
                    if (this.isAllChecked) {
                        this.checkGroup = this.dataList;
                    } else {
                        this.checkGroup = [];
                    }
                },
                handleLiChange() {
                    if (this.dataList.length === this.checkGroup.length) {
                        this.isAllChecked = true;
                    } else {
                        this.isAllChecked = false;
                    }
                },
                handleDelClick(data) {
                    if (data.number != 0) {
                        data.number--
                    } else { data.number = 0 }

                }
            }
        })
    </script>

表单修饰符

        <!-- 失去焦点才显示 -->
        <input type="text" v-model.lazy="mytext">
        <!-- 只能输入数字 效果不好 -->
        <input type="text" v-model.number="mynumber">
        <!-- 去除收尾空格 -->
        <input type="text" v-model.trim="myname">

axios

  • 方式一
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
   aaa: function () {
                    axios.get("xxx").then((res) => {
                        console.log(res.data)
                    }).catch((err) => {

                    });
                },
   bbb: function () {
                    axios.post("xxx", {
                        //请求参数
                    }).then(res => {
                        console.log(res.data)
                    }).catch(err => {
                        console.log(err)
                    })
                }
  • 方式二
  1. 安装axios依赖
npm install axios
  1. 在main.js中引入
import axios from 'axios'

Vue.prototype.$axios = axios;
  1. 使用
mounted() {
    this.$axios.get('http://www.liulongbin.top:3005/api/getlunbo')
      .then(function (response) {
        console.log(response);
      })
      .catch(function (error) {
        console.log(error);
      });
  }

vue引入Axios

随笔-vue项目引入axios

使用增删改查

npm 安装axios和使用增删改查

Vue项目引入Axios 插件(封装):

Vue项目引入Axios 插件(封装) - 简书 (jianshu.com)

  • 完整写法
    axios({
        url:"",
        headers:{

        }
    }).then(res=>{
			console.log(res.data)
    }).catch(err => {
            console.log(err)
    })

计算属性

  • 定义像函数 使用像属性
  • 计算属性会缓存

计算属性模糊查询

    <div id="box">

        <input type="text" v-model="mytext" />
        <!-- @change 只要失去焦点就会触发 -->
        <ul>
            <li v-for="data in getDataList">
                {{data}}
            </li>
        </ul>

    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#box",
            data: {
                mytext: '',
                dataList: ["111", "2222", "333"],
            },
            computed: {
                getDataList() {
 return this.dataList.filter(item => item.indexOf(this.mytext) > -1)
                }
            }
        })
    </script>

组件化开发

定义全局组件

    <div id="box">
        <navbar></navbar>

    </div>

    <script type="text/javascript">
        //1.全局定义组件(作用域隔离)
        Vue.component("navbar", {
            template: `
            <div @click="handleback()" style="background:red">
            我是导航栏
            </div>
            `,
            methods: {
                handleback() {
                    console.log("back...")
                }
            }
        })

        new Vue({
            el: "#box",
        })
    </script>

局部

  <div id="box">
        <navbar></navbar>

    </div>

    <script type="text/javascript">
        //1.全局定义组件(作用域隔离)
        Vue.component("navbar", {
            template: `
            <div @click="handleback()" style="background:red">
            我是导航栏
            <child></child>
            <navbarchild></navbarchild>
            </div>
           
            `,
            methods: {
                handleback() {
                    console.log("back...")
                }
            },
            components: {
                navbarchild: {
                    template: `
                         <div >
                          我是child组件----局部定义
                         </div>
                       `
                }
            } //局部
        })

        //全局
        Vue.component("child", {
            template: `
            <div  style="background:green">
            我是child组件----全局定义
            </div>
            `,
            methods: {
                handleback() {
                    console.log("back...")
                }
            }
        })

        new Vue({
            el: "#box",
        })
    </script>

Vue2.0 基础入门_javascript_02

父传子与属性验证

  <div id="box">
        <navbar myname="home" :myshow="false"></navbar>
        <navbar myname="list" :myshow="true"></navbar>
        <navbar :myname="parentname" :myshow="true"></navbar>
    </div>

    <script type="text/javascript">
        //全局
        Vue.component("navbar", {
            template: `
            <div  style="background:green">
            <button v-show="myshow">返回</button>
            导航栏----{{myname}}
            <button v-show="myshow">首页</button>
            </div>
            `,
           // props: ["myname","myshow"]  //接收父组件传来的属性  js代码用v-bind
		  //属性验证
            props:{
                myname:String,
                myshow:Boolean
            }
        })

        new Vue({
            el: "#box",
            data: {
                parentname: "parentname属性"
            }
        })
    </script>

Vue2.0 基础入门_ide_03

子传父

    <div id="box">
        <navbar @myevent="handleEvent($event)"></navbar>
        <!-- 或者 -->
        <navbar @myevent="handleEvent"></navbar>
    </div>

    <script type="text/javascript">

        //全局
        Vue.component("navbar", {
            template: `
            <div  style="background:green">
            <button @click="pay()">返回</button>
            </div>
            `,
            data() {
                return {
                    txt: "子组件的内容"
                }
            },
            methods: {
                pay() {
                    this.$emit("myevent",this.txt)  //分发事件
                }
            }
        })

        new Vue({
            el: "#box",
            data: {
                parentname: "parentname属性"
            },
            methods: {
                handleEvent() {
                    console.log("父组件收到!")
                }
            }
        })
    </script>
  • 案例 侧边栏的隐藏与显示
  <div id="box">
        <!-- 2.触发后 执行父组件方法 -->
        <navbar @myevent="handleEvent($event)"></navbar>
        <sidebar v-show="isShow"></sidebar>
    </div>

    <script type="text/javascript">

        Vue.component("navbar", {
            template: `<div>
            <button @click="handleClick">点击</button>
             </div>
                `,
            methods: {
                handleClick() {
                    this.$emit("myevent")    //1.点击按钮 触发回调函数 找到 myevent
                }
            }
        })

        Vue.component("sidebar", {
            template: `
            <div>
                <ul>
                  <li>
                     选项1 
                  </li>
                  <li>
                     选项2
                  </li>
                </ul>
            </div>`
        })

        new Vue({
            el: "#box",
            data: {
                isShow: false
            },
            methods: {
                handleEvent() {
                    this.isShow = !this.isShow  //3. 控制
                }
            }
        })
    </script>

  • 方法改造
   <div id="box">
        <!-- 2.触发后 执行父组件方法 -->
        <navbar>
            <button @click="handleEvent($event)">点击</button>
        </navbar>
        <sidebar v-show="isShow"></sidebar>
    </div>

    <script type="text/javascript">

        Vue.component("navbar", {
            template: `<div>
             <slot></slot>
             </div>
        })
        Vue.component("sidebar", {
            template: `
            <div>
                <ul>
                  <li>
                     选项1 
                  </li>
            </div>`
        })

        new Vue({
            el: "#box",
            data: {
                isShow: false
            },
            methods: {
                handleEvent() {
                    this.isShow = !this.isShow  //3. 控制
                }
            }
        })
    </script>

父传子靠属性,子传父靠事件**

ref-父子通信通信

    <div id="box">
        <input type="text" ref="mytext">
        <button @click="handleEvent()">click</button>
        <child ref="mychild"></child>

    </div>

    <script type="text/javascript">

        Vue.component("child", {
            template: `
            <div>
                child
                </div>
            `,
            data() {
                return {
                    name: "childName"
                }
            },
            methods: {
                aa(data) {
                    console.log("自己的", data)
                }
            }

        })
        new Vue({
            el: "#box",
            methods: {
                handleEvent() {
                    console.log(this.$refs.mytext.value)
                    console.log(this.$refs.mychild)
                    this.$refs.mychild.aa("传过去的")
                }
            }
        })

        /*
            绝对的控制权
         1. ref放在标签上拿到的是原生节点
         2. ref放在组件上,拿到的是组件对象
        */
    </script>

非父子通信--事件总线

    <div id="box">
        <author></author>
        <user></user>
    </div>

    <script type="text/javascript">
        /* 创建事件总线 $emit与$on */
        //创建空的vue实例赋值给一个变量
        var bus = new Vue();

        Vue.component("author", {
            template: `
            <div>
             <input type="text" ref="mytext" />
             <button @click="handleClick()">发布</button>
                </div>
                `,
            methods: {
                handleClick() {
                    bus.$emit("mseeage",this.$refs.mytext.value)
                }
            }
        })

        Vue.component("user", {
            //合适的位置订阅=>当前组件创建完成时 bus.$on
            template: `
            <div>
            我是用户
                </div>
            `,
            mounted() {  //组件创建完调用
                bus.$on("mseeage", (data) => {
                    console.log("收到推送",data)
                })
                console.log("生命周期函数--当前组件dom创建完成之后就会调用")
            }
        })
    </script>

动态组件

Vue2.0 基础入门_前端_04

    <div id="box">
        <!-- vue 提供动态组件  is属性 -->
        <component is="home"></component>

        <!-- 避免重新渲染 -->
        <keep-alive>
            <component is="home"></component>
        </keep-alive>
    </div>

    <script type="text/javascript">
        new Vue({
            el: "#box",
            components: {
                "home": {
                    template: `<div>home组件</div>`
                },
                "list": {
                    template: `<div>list组件</div>`
                },
                "footer": {
                    template: `<div>footer组件</div>`
                }
            }
        })
    </script>

slot插槽

Vue2.0 基础入门_html_05

  • 使用场景:轮播图
    <div id="box">
        <swiper>
            <li v-for="data in dataList">
                {{data}}
            </li>
        </swiper>
    </div>

    <script type="text/javascript">
        Vue.component("swiper", {
            template: `
            <div>
                 <ul>
                    <slot></slot>
                 </ul>
             </div>
            `
        })
        new Vue({
            el: "#box",
            data: {
                dataList: ["1111", "222", "333"]
            }
        })
    </script>
  • 具名插槽 [ name 与 slot ]
 <div id="box">
        <swiper>
           <p slot="a">111</p>
           <p slot="b">222</p>
        </swiper>
 </div>

//=============================
 Vue.component("swiper", {
            template: `
            <div>
                 <slot name="a"></slot>
                 ---------------------
                 <slot name="b"></slot>
             </div>
            `
        })

元素过度

不在详细学习 具体请看教程

动画效果

Vue2.0 基础入门_ide_06

<link href="https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.compat.css" rel="stylesheet">
    
//或者
    
npm install animate.css
// or
yarn install animate.css    

使用详解===> Vue.animate.css组件库的使用的详细解析

生命周期

生命周期

超强VUE教程(强烈推荐)_哔哩哔哩_bilibili

  • mounted:页面一创建发送ajax请求
  • dom节点更新完之后的操作放入updated之中

Vue2.0 基础入门_前端_07

过滤器

		<!-- 格式:要有空格 -->
 <img src="xxx.jpg | aaafilter" alt="">

			<!-- js -->
//过滤器
Vue.filter("aafilter", function (data) {
      return data.replce("xxx", "xxxx");  //替换源---替换目标
 })

Vue2.0 基础入门_ide_08

Swiper轮播

  • 引入cdn
    <link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.css">
    <script src="https://unpkg.com/swiper/swiper-bundle.js"> </script>
  • 实例
 <div id="box">
        
        <div class="swiper-container">
            <div class="swiper-wrapper">
                <div class="swiper-slide" v-for="data in dataList" style="width: 300px;height: 300px;">
                    {{data}}
                </div>

            </div>
            <!-- 如果需要分页器 -->
            <div class="swiper-pagination"></div>

            <!-- 如果需要导航按钮 -->
            <div class="swiper-button-prev"></div>
            <div class="swiper-button-next"></div>

            <!-- 如果需要滚动条 -->
            <div class="swiper-scrollbar"></div>
        </div>

    </div>

    <script type="text/javascript">

        new Vue({
            el: "#box",
            data: {
                dataList: []
            },
            mounted() {    //swiper放入mounted会出现初始化过早问题
                setTimeout(() => {
                    this.dataList = ["1111", "2222", "3333"]   //异步更新dom节点
                }, 2000)
            },
            updated() {
                new Swiper('.swiper-container', {
                    //   direction: 'vertical', // 垂直切换选项
                    loop: true, // 循环模式选项
                    // 如果需要分页器
                    pagination: {
                        el: '.swiper-pagination',
                        clickable: true

                    },

                    // 如果需要前进后退按钮
                    navigation: {
                        nextEl: '.swiper-button-next',
                        prevEl: '.swiper-button-prev',
                    },

                    // 如果需要滚动条
                    scrollbar: {
                        el: '.swiper-scrollbar',
                    },
                    //设置自动轮播
                    autoplay: true
                })
            }
        })
    </script>

上述方法使用太麻烦,我们封装成组件

<!-- css 自己设置 -->
     <swiper :key="dataList.length">
            <div class="swiper-slide" v-for="data in dataList" style="width: 300px;height: 300px;">
                {{data}}
            </div>
      </swiper>
//===================================
  Vue.component("swiper", {
            template: `
            <div class="swiper-container">
            <div class="swiper-wrapper">
              <slot></slot>
            </div>
            <!-- 如果需要分页器 -->
            <div class="swiper-pagination"></div>
            <!-- 如果需要导航按钮 -->
            <div class="swiper-button-prev"></div>
            <div class="swiper-button-next"></div>
            <!-- 如果需要滚动条 -->
            <div class="swiper-scrollbar"></div>
        </div>
             `,
            mounted() {
                new Swiper('.swiper-container', {
                    //   direction: 'vertical', // 垂直切换选项
                    loop: true, // 循环模式选项
                    // 如果需要分页器
                    pagination: {
                        el: '.swiper-pagination',
                        clickable: true
                    },
                    // 如果需要前进后退按钮
                    navigation: {
                        nextEl: '.swiper-button-next',
                        prevEl: '.swiper-button-prev',
                    },
                    // 如果需要滚动条
                    scrollbar: {
                        el: '.swiper-scrollbar',
                    },
                    //设置自动轮播
                    autoplay: true
                })
            }
        })
  • 用指令封装
  <div id="box">
        <div class="swiper-container">
            <div class="swiper-wrapper">
                <div class="swiper-slide" v-for="(data,index) in dataList" 		           style="width: 300px;height: 300px;" v-swiper=" {
                    index:index,
                    length:dataList.length
                }">
                    {{data}}
                </div>
            </div>
            <!-- 如果需要分页器 -->
            <div class="swiper-pagination"></div>

            <!-- 如果需要导航按钮 -->
            <div class="swiper-button-prev"></div>
            <div class="swiper-button-next"></div>
        </div>

    </div>
    <script type="text/javascript">
        Vue.directive("swiper", {
            inserted(el, bind) {
                if (bind.value.index === bind.value.length - 1) {
                    new Swiper('.swiper-container', {
                        //   direction: 'vertical', // 垂直切换选项
                        loop: true, // 循环模式选项
                        // 如果需要分页器
                        pagination: {
                            el: '.swiper-pagination',
                            clickable: true

                        },
                        // 如果需要前进后退按钮
                        navigation: {
                            nextEl: '.swiper-button-next',
                            prevEl: '.swiper-button-prev',
                        },
                        // 如果需要滚动条
                        scrollbar: {
                            el: '.swiper-scrollbar',
                        },
                    })
                }
            }
        })

        new Vue({
            el: "#box",
            data: {
                dataList: []
            },
            mounted() {
                setTimeout(() => {
                    this.dataList = ["1111", "2222", "3333"]
                }, 2000)

            }
        })
    </script>

指令用法

  • 自定义指令 自己可以操作 Dom

Vue2.0 基础入门_ide_09

  <div id="box">
        <div v-qiandu="'red'">1111</div>
        <div v-qiandu="color">1111</div>
    </div>
    <script type="text/javascript">

        Vue.directive("qiandu", {
            inserted(el, bind) {  //el:获取dom
                //插入指令  ----创建阶段  只执行一次
                console.log("当前节点插入到父节点中了")
                console.log(el)
                console.log(bind)
                el.style.background=bind.value   //改变背景色
            },
            update(el, bind) {
                el.style.background=bind.value
            }
        })

        new Vue({
            el: "#box",
            data: {
                color:"yellow"
            },
            computed: {

            }
        })
    </script>

脚手架

cli配置

安装Node.js

配置 ===> 安装npm及cnpm(Windows) - 山高我为峰 - 博客园 (cnblogs.com)

Vue cli安装

安装 | Vue CLI (vuejs.org)

npm install -g @vue/cli
# OR
yarn global add @vue/cli

创建脚手架

  1. 创建路径运行终端 输入
 vue create xxx
  1. 一系列设置

具体配置教程: 脚手架配置

参考文章: VueCLI v4.5.4 创建vue项目(手选模式创建)_{竹子} -CSDN博客

Vue2.0 基础入门_ios_10

  • 所有的静态资源全部放入public文件夹下 引入到index.html
<link rel="stylesheet" href="<%= BASE_URL %>public下的文件路径">
  • 模块化引入css
import 'swiper/dist/css/swiper.css'

单文件组件

Vue2.0 基础入门_前端_11

  • 以xxx.vue命名
  • 结构样式

Vue2.0 基础入门_ios_12

基本写法

<template>

</template>

<script>
export default {
    
};
</script>

<style>
</style>

例子

//Navbar.vue
<template>
  <nav>导航栏</nav>
</template>

//APP.vue

<template>
  <div id="app">
    <!-- <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/> -->
    <p>HelloWorld</p>
    <Navbar></Navbar>
    <siderbar></siderbar>
  </div>
</template>

<script>
import Navbar from "./components/Navbar.vue";
import Siderbar from "./components/Siderbar.vue";
// import Vue from "vue";
// Vue.component("Navbar", NavBar);
// Vue.component("Siderbar", Siderbar);

export default {
  name: "App",
  components: {
    Navbar:Navbar,
    Siderbar:Siderbar,
  },
};
</script>

注意!!!为防止互相影响 加上 scoped属性

打包

修复错误

npm run lint

上线项目

npm run build

成功生成dist文件夹拷出里面文件即可

跨域请求

解决跨域请求vue.config.js配置(与 package.json )同级

官方文档 配置参考 | Vue CLI (vuejs.org)

注意:更改配置文件要重启服务器

module.exports = {
    devServer: {
      proxy: {
        '/api': {     // *: 所有请求都会转到target
          target: '<url>',  
        //   ws: true,
          changeOrigin: true
        },
        '/api': {     // 第二个
            target: '<url>',  
          //   ws: true,
            changeOrigin: true
          },
        // '/foo': {
        //   target: '<other_url>'
        // }
      }
    }
  }

  //比如 http:www.baidu.com/ajax?&q=ewqe
  // api填写:ajax
  //target填:http:www.baidu.com
  //axios填写后面字段:/ajax?&q=ewqe

路由

  • 写法

Vue2.0 基础入门_前端_13

路由配置

  • 路径改变,页面不会刷新

相关配置教程 vue的路由安装及配置

关于components与views文件夹

  • 把需要共享的组件放入到 components 文件夹中
  • 把单页面或者只用于一次的组件放入到 views 之中
  1. 引入路由 新建 vouter.jsmain.js同级
npm install vue-router
  1. 编写路由
import Vue from 'vue' // 引入vue
import VRouter from 'vue-router' // 引入路由
import File  from '@/views/File' // 引入需要用到路由的页面  @:表示指向src文件夹
import Center from '@/views/Center'

Vue.use(VRouter) // vue使用路由

export default new VRouter({ // 创建路由
    mode: 'history', // 去掉链接中的#  /File || /#/File
    routes: [ // 此处写路由  放入数组
        {
            path: '/File', // 链接中的显示路劲
            name: 'File', // 名字
            component: File // 引入的路由名称,必须与import里的名称一样
        }
    ]
})
  1. main.js引入
import router from './router'

Vue.config.productionTip = false

new Vue({
  router: router,  //key与value相同时,可以简写为router
  render: h => h(App),
}).$mount('#app')
  1. 使用
<template>
  <div id="app">
    <!-- <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/> -->
    <p>HelloWorld</p>
    <Navbar></Navbar>
    <siderbar></siderbar>
    <!-- 路由容器 -->
    <router-view></router-view>
  </div>
</template>
  1. 在 ```views文件夹下编写相应的vue文件``

声明式导航

  • (点击)事件跳转到相应路由

Vue2.0 基础入门_ios_14

router-link 可以达到高亮显示效果----同步变化

  • to :/url
  • tag:标签
  • active-class:class
<template>
  <div>
    <ul>
      <!-- 声明式导航 -->
      <router-link to="/File" tag="li" active-class="myactive"
        >file</router-link>
      <router-link to="/Center" tag="li" active-class="myactive"
        >center</router-link
      >
      <!-- 作用与下方相同 -->
      <!-- <li>
        <a href="/File">-File-</a>
      </li>
      <li>
        <a href="/Center">-Center-</a>
      </li> -->
    </ul>
  </div>
</template>

<style scoped>
.myactive {
  color: red;
}
</style>

重定向

默认显示或者请求url错误显示

import Vue from 'vue' // 引入vue
import VRouter from 'vue-router' // 引入路由

Vue.use(VRouter) // vue使用路由

export default new VRouter({ // 创建路由
    mode: 'history', // 去掉链接中的#  /File || /#/File
    routes: [ // 此处写路由  放入数组
        {
            path:'*',
            redirect:'/File'
        }
    ]
})

二级路由

  • 例子
http://localhost:8080/#/File/aaa
http://localhost:8080/#/File/bbb
  1. router.js
import Vue from 'vue' // 引入vue
import VRouter from 'vue-router' // 引入路由

Vue.use(VRouter) // vue使用路由

export default new VRouter({ // 创建路由
    // mode: 'history', // 去掉链接中的#  /File || /#/File
    routes: [ // 此处写路由  放入数组
        {
            path: '/File', // 链接中的显示路劲
            name: 'File', // 名字
            component: File, 
            children:[    //二级路由数组
                {
                    path:'',  //此路径无需加不能加 /
                    component:File  
                }
            ]
        }
    ]
})

  1. 父组件留插槽
    <!-- 路由容器 -->
    <router-view></router-view>
  1. 创建相应的子组件 并有完整的项目结构 二级放入一级文件夹下

设置子路由默认路径

import Vue from 'vue' // 引入vue
import VRouter from 'vue-router' // 引入路由
import File from '@/views/File' // 引入需要用到路由的页面  @:表示指向src文件夹
import Center from '@/views/Center'

Vue.use(VRouter) // vue使用路由

export default new VRouter({ // 创建路由
    // mode: 'history', // 去掉链接中的#  /File || /#/File
    routes: [ // 此处写路由  放入数组
        {
            path: '/File', // 链接中的显示路劲
            name: 'File', // 名字
            component: File,
            children: [    //二级路由数组
                {
                    path: '',
                    component: File
                },
                {
                    prth: '',
                    redirect: "/父路径/子路径"
                }
            ]
        }
    ]
})

动态路由

点击事件 列表跳转详情页面

  1. 列表页面
<template>
  <div>
    <ul>
      <li v-for="data in dataList" :key="data" @click="handlePage(data)">
        {{ data }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  setup() {},
  data() {
    return { dataList: ["1111", "2222", "3333"] };
  },
  methods: {
    handlePage(id) {
      console.log(id);
      //编程式导航  按照路径
      this.$router.push('/detail/'+id)  //跳转具体页面     
        
      //编程式导航  按照name
      this.$router.push({name:"qddetail",params:{id:id}});
    },
  },
};
</script>
  1. 详情页面
<template>
  <div>detail</div>
</template>

<script>
export default {
  setup() { },
  mounted() {
      // $route,this  获取参数
        console.log(this.$route,this.$route.params.id);
  },
};
</script>
  1. 动态路由设置
import Vue from 'vue' // 引入vue
import VRouter from 'vue-router' // 引入路由
import File from '@/views/File' // 引入需要用到路由的页面  @:表示指向src文件夹
import Center from '@/views/Center'
import Erji from '@/views/Erji'
import detail from '@/views/detail'

Vue.use(VRouter) // vue使用路由

export default new VRouter({ 
    // mode: 'history', // 去掉链接中的#  /File || /#/File
    routes: [ 
        {
            path: '/detail/:id', // 动态路由 冒号+自定义参数
            name: "qddetail",
            component: detail 
        }
    ]
})

===

//页面跳转
this.$router.push('/detail/'+id)  //跳转具体页面   
//存到本地
localStorage.setItem("key","value")
//获取本地值
localStorage.getItem("key")
//移除  清除
remove   clear

History模式

正常的路由采用的是hash模式 url会有#标志 去除#号 只需加上这一句

   mode: 'history',

不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite .com/user/id就会返回404,这就不好看了。

Vue2.0 基础入门_javascript_15

路由拦截

  • 举例

我们在选购商品准备付款时,判断你是否登录,未登录跳转到登录页面,

只有登录后才能购买

全局

//验证方法
const auth = {
    isLogin() {
        //判断token session cookie等
        return false;
    }
}

//全局守卫:任何一个路由跳转进来执行此方法
VRouter.beforeEach((to, from, next) => {
    if (to.path === '/shoppPage') {
        if (auth.isLogin()) {
            next()
        }
    } else {
        next() //放行
    }
})

局部 ===> 写在组件< script>中

const Foo = {
  template: `...`,
  beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

Vuex

入门

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。尤其为非父子通信服务非常好

官网: Vuex 是什么? | Vuex (vuejs.org)

  1. 引入
npm install vuex --save
  1. main.js同级新建 store.js内部结构
import Vue from "vue";
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {

    },
    mutations: {

    },
    actions: {

    }
})
  1. main.js中引入
import store from './store'

new Vue({
  router: router,  //key与value相同时,可以简写为router
  store,
  render: h => h(App),
}).$mount('#app')
  1. 使用
v-show="this.$store.state.isTabbarShow"   //this可以省略

this.$store.state.字段

设计原则

  • 应用层级的状态应该集中到单个store对象中。

  • 提交mutation是更改状态的唯一方法,并且这个过程是同步的。

  • 异步逻辑都应该封装到action里面。

状态管理

我们需要一个监控或者管理系统来具体了解什么时候改变了状态

所有修改状态都会经过 mutations这一层 调式工具会记录下来

Vue2.0 基础入门_javascript_16

  1. 具体更改方法中
this.$store.commit( "自定义函数名",false);  //第一个参数就是mutation名字
this.$store.commit( "自定义函数名",true); 
  1. store.js
    state: {
        //放入全局的自定义共享状态
        isTabbarShow: false
    },
    mutations: {  //唯一修改状态的位置
        zidingyi(state, data) {
            state.isTabbarShow = data
        }
    },

异步处理

  • 需求

电影网站分为热映与即将上映 当我们点击热映时 ,判断热映页面是否有数据 如果没有,发起ajax请求 然后存放到mutation 然后页面更新 如果有 直接取数据 渲染页面 无需Ajax请求

实现

  1. 具体地址调用
  if (this.$store.state.dataList.length === 0) {
      //发送Ajax请求
      this.$store.disapath("自定义函数");
    } else {
      //使用缓存的数据
    }
  1. store.js
export default new Vuex.Store({
    state: {
        //放入全局的自定义共享状态
        dataList: []
    },
    mutations: {  //唯一修改状态的位置
        dataListMutation(state, data) {
            state.dataList = data
        }
    },
    actions: { //从后端异步请求需要经过actions
        //异步处理
        zidingyi(store) {
            //axios请求
            //引入axios
            //传入到mutations中
            store.commit("dataListMutation", "获取的数据")
        }
    }
})

写法转换

  • 对比
this.$store.state.data

import {mapState} from 'vuex'

computed:{
    mapState(["data"])  //不建议
	...mapState(["data"])  //建议这样写  ES6中展开合并运算符
}

导入导出规范

  • 问题

很多时候我们只需要某个包中的一个或者几个方法 但是之前的方法会默认导入全部 加载会慢

  • 对比

Bad

//===========A1.js================
function A(){ }
function B(){ }
function C(){ }
//ES6导出规范
const All = {
    A,B,C
}

export default All

//=============导入=================
import All from 'A1'

//结果 引入全部方法

Good

//===========A1.js================
export function A(){ }
export function B(){ }
export function C(){ }
//=============导入=================
import {A,B} from 'A1'

//结果 引入A B方法

import {A as myA} from 'A1'    //起别名

Gitters

有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数

Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

  1. store.js
    getters: {  //处理数据
        zidingyi(state) {
            return state.dataList.filter((item, index) => index < 3)
        }

    }
  1. 使用
this.$store.getters.自定义函数名
mapGitters(["  "])

mutation常量风格

  • 问题

当我们方法多了或者多人开发势必会出现同名方法 这里可以规避这个问题

  1. 新建文件夹 比如 type 下的 a1.js有如下代码
export const   SHOW_TABBAR_MUTATION = "show"
  1. store.js
//===先引入a1.js

	mutations: {  //唯一修改状态的位置
        show (state, data) {
        }
      //等同于
        [SHOW_TABBAR_MUTATION] (state, data) {
        }
    },

注意:commit 调用方法也需要改

element UI

介绍

Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库

  • 官网地址 ===> 组件 | Element

    element-ui是由饿了么前端团队推出的一套为开发者、设计师和产品经理准备的基于Vue.js 2.0的桌面组件库。

扩展使用文章:===> Element-ui 基本使用 - 简书 (jianshu.com)

安装

引入element ui到vue中

npm i element-ui -S
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>

vscoe代码提示插件 : Element-UI-Snippets

使用方法====> ( Element-UI-Snippets-VSCode插件代码提示快捷键_

引入

  • 全局引入,在vue入口main.js中增加内容如下
  import ElementUI from 'element-ui';

  import 'element-ui/lib/theme-chalk/index.css';

   Vue.use(ElementUI);
  • 局部引入,在指定的vue文件中引入所需要的组件或主题样式,如下
    import '@/style/theme/element-variables.scss'

    import { Message, MessageBox, Loading } from  'element-ui'

    Vue.use(Loading.directive) 
    Vue.prototype.$loading = Loading.service 
    Vue.prototype.$msgbox = MessageBox 
    Vue.prototype.$alert = MessageBox.alert 
    Vue.prototype.$confirm = MessageBox.confirm 
    Vue.prototype.$prompt = MessageBox.prompt 
    Vue.prototype.$message = Message

具体使用请前往官网查看

手势事件

  1. 安装
npm install vue-touch@next --save
  1. 在 需要的文件中引入
	import Vue from "vue";
	import VueTouch from 'vue-touch'

	Vue.use(VueTouch, {name: 'v-touch'})  v-touch可以是自定义名称
  1. 使用
<v-touch @swipeleft="onSwipeLeft">
    <div style="background :red;height : 100px">center</div>
</v-touch>
	<v-touch 	
		(1)替换标签
			tag="要变成的标签名称,默认为div"
		
		(2)定义手势
			@事件类型='回调' 
			
		(3)配置手势事件选项
			:小写事件类型名称-options="{ direction: 'horizontal', threshold: 100 }
				threshold临界值
				directions方向: 'up', 'down', 'left', 'right', 'horizontal', 'vertical', 'all'
				具体配置查看hammerjs
				
		(4)阻止/触发手势
			:enabled="true/false"   允许/禁止所有的手势
			:enabled="{ pinch: true, rotate: false }"  允许和禁止指定手势
		
		(5)公共组件方法
			1、通过ref获取到该标签
			2、在方法中
				this.$refs.tapper.disable('tap')
				
			公共方法:
				disable('手势名称') 	
				enable('手势名称') 	
				toggle('手势名称') 	
				disableAll() 	disable all Recognizers
				enableAll() 	enable all Recognizers
				isEnabled('手势名称') 	
			
		(6)自定义手势
			在main.js中,在Vue.use之前使用
			
			VueTouchVueTouch.registerCustomEvent('doubletap', {
			  type: '手势名称',
			  ...手势事件的配置选项,见(3)
			  taps: 2  对应tap手势的触发点击次数配置
			})
	
	> ...</v-touch>
	
4、事件类型:
	Pan平移 	
		pan, panstart, panmove, panend, pancancel,
		panleft, panright, panup, pandown 	
		
	Pinch缩放 	
		pinch, pinchstart, pinchmove,pinchend,
		pinchcancel, pinchin, pinchout 	
		
	Press按压 	
		press, pressup 	
		
	Rotate旋转 	
		rotate, rotatestart, rotatemove,
		rotateend, rotatecancel, 	
		
	Swipe滑动 	
		swipe, swipeleft, swiperight,
		swipeup, swipedown 	
		
	Tap点击 	
		tap 

Vue2.0 基础入门_javascript_17

Vue SSR

介绍

官网: Vue.js 服务器端渲染指南 )

  • 什么是服务器端渲染 (SSR)?

Vue.js 是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出 Vue 组件,进行生成 DOM 和操作 DOM。然而,也可以将同一个组件渲染为服务器端的 HTML 字符串,将它们直接发送到浏览器,最后将这些静态标记"激活"为客户端上完全可交互的应用程序。

服务器渲染的 Vue.js 应用程序也可以被认为是"同构"或"通用",因为应用程序的大部分代码都可以在服务器客户端上运行。

优点

  • SEO和爬虫都是根据url返回的数据来进行的 , 爬虫seo获取的数据,是一个没有数据的壳子

  • 首屏渲染 像vue这样的单页面应用,首屏渲染是单页面spa的通病,打包出来的dist过大,会导致首屏加载缓慢

缺点

  • 需要配置两个入口文件,一个是服务端首屏渲染所需要的,第二个是前端激活所需要的
  • 相比于单纯的spa,服务端渲染加重了服务器的负担
  • 前后端同构,在后端就需要写前端vue的代码,与前后端分离相违背,这个可以通过webpack打包实现,只需要配置入口文件以及相应的逻辑就可以。
  • 缓存和运维的问题。

服务端与客户端渲染的对比====> 关于SSR( 服务端渲染 )其利与弊是什么? - 知乎 (zhihu.com)

快速使用

  1. 安装
npm install vue vue-server-renderer --save
  1. 渲染示例
// 第 1 步:创建一个 Vue 实例
const Vue = require('vue')
const app = new Vue({
  template: `<div>Hello World  ----{{myname}}----{{age}} </div>`,
    data:{
        myname:"前度",
        age:"18"
    }
})

// 第 2 步:创建一个 renderer
const renderer = require('vue-server-renderer').createRenderer()

// 在 2.5.0+,如果没有传入回调函数,则会返回 Promise:
renderer.renderToString(app).then(html => {
  console.log(html)
}).catch(err => {
  console.error(err)
})
  1. 终端调用
node 路径+文件名

与服务器集成

npm install express --save
const Vue = require('vue')
const server = require('express')()
const renderer = require('vue-server-renderer').createRenderer()

server.get('*', (req, res) => {
  const app = new Vue({
    data: {
      url: req.url
    },
    template: `<div>访问的 URL 是: {{ url }}</div>`
  })

  renderer.renderToString(app, (err, html) => {
    if (err) {
      res.status(500).end('Internal Server Error')
      return
    }
   res.writeHead(200,{"Content-Type":"text/html;charset=utf8"})        
    res.end(`
      <!DOCTYPE html>
      <html lang="en">
        <head><title>Hello</title></head>
        <body>${html}</body>
      </html>
    `)
  })
})

server.listen(8080)
node 文件名
访问端口号

Nuxt.js

官网: 关于 Nuxt.js - NuxtJS | Nuxt.js 中文网

  • 项目的构建

安装 - NuxtJS | Nuxt.js 中文网

  • 相关教程

nuxt.js

ps:此文章只是对Vue2.0的简单使用与介绍,不涉及更深层面,仅仅入门,有些介绍也引入了其他小伙伴的博客,还望海涵