Vue

前端目前形势

前端发展史

1.HTML(5)、CSS(3)、JavaScript(ES5、ES6):编写一个个的页面 -> 给后端(PHP、Python、Go、Java) -> 后端嵌入模板语法 -> 后端渲染完数据 -> 返回数据给前端 -> 在浏览器中查看

2.Ajax的出现 -> 后台发送异步请求,Render+Ajax混合

3.单用Ajax(加载数据,DOM渲染页面):前后端分离的雏形

4.Angular框架的出现(1个JS框架):出现了“前端工程化”的概念(前端也是1个工程、1个项目)

5.ReactVue框架:当下最火的2个前端框架(Vue:国人喜欢用,React:外国人喜欢用)

6.移动开发(Android+IOS) + Web(Web+微信小程序+支付宝小程序) + 桌面开发(Windows桌面):前端 -> 大前端

7.一套代码在各个平台运行(大前端):谷歌Flutter(Dart语言:和Java很像)可以运行在IOS、Android、PC端

8.在Vue框架的基础性上 uni-app一套编码 编到10个平台

9.在不久的将来 ,前端框架可能会一统天下

介绍

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架

与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用

Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合

渐进式框架

可以一点一点地使用它,只用一部分,也可以整个工程都使用它

网站

特点

  • 易用
    • 通过HTML、CSS、JavaScript构建应用
  • 灵活
    • 不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸缩
  • 高效
    • 20kB min+gzip 运行大小
    • 超快虚拟DOM
    • 最省心的优化

M-V-VM思想

介绍

MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,是一种事件驱动编程方式

  • Model :vue对象的data属性里面的数据,这里的数据要显示到页面中
  • View :vue中数据要显示的HTML页面,在vue中,也称之为“视图模板” (HTML+CSS)
  • ViewModel:vue中编写代码时的vm对象,它是vue.js的核心,负责连接 View 和 Model数据的中转,保证视图和数据的一致性,所以前面代码中,data里面的数据被显示中p标签中就是vm对象自动完成的(双向数据绑定:JS中变量变了,HTML中数据也跟着改变)

img

特性

  • 低耦合视图(View)可以独立于Model变化和修改,1个ViewModel可以绑定到不同的View上,当View变化的时候 Model可以不变,当Model变化的时候 View也可以不变
  • 可复用:可以把一些视图逻辑放在1个ViewModel中,让很多View重用这端视图的逻辑(以此减少代码冗余)
  • 独立开发开发人员可以专注于业务逻辑数据的开发(ViewModel),设计人员可以专注于页面设计
  • 可测试:界面元素是比较难以测试的,而现在的测试可以针对ViewModel来编写

MVVM的逻辑

img

组件化开发、单页面开发

类似于DTL中的include,每一个组件的内容都可以被替换和复用

img

单页面开发

  • 只需要一个页面,结合组件化开发来替换页面中的内容
  • 页面的切换只是组件的替换,页面还是只有一个index.html

版本

  • 1.X:使用得较少
  • 2.X:普遍使用
  • 3.X:刚出没多久,只有Beta版

引入方式

补充

  • 解释型的语言是需要解释器的
  • nodejs:一门后端语言

使用

模板语法

{{变量、js语法}}

指令之文本指令

v-html		# 让HTML字符串渲染成标题
v-text		# 标签内容显示js变量对应的值
v-show		# 放一个布尔值:为真 标签就显示;为假,标签就隐藏
v-if		# 放一个布尔值:为真 标签就显示;为假,标签就隐藏(删除)

指令之事件指令

v-on:事件		# 触发事件(不推荐)
@事件			# 触发事件(推荐)
@[event]	 # 触发event事件(可以是其他任意事件)

Style与Class

数据的绑定

:属性名 = js变量/js语法

class: 字符串、三目运算符、数组、对象{red:true}
    :class='js变量、字符串、js数组'

style: 字符串、三目运算符、数组[{backgreound:'red'}]、对象{red:true}
    
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <style>
        .cls_obj_red{
            background-color: red;
        }
    </style>
</head>
<body>
<div id="app">
<!--    <p :class="cls_obj">阿巴阿巴</p>-->
<!--    <p :style="style_obj">滴滴答答</p>-->
</div>

<script>
    var vm = new Vue({
        el:'#app',
        data:{
            // cls_obj:{cls_obj_red:true}
            // cls_obj:['cls_obj_red']
            // cls_obj:'cls_obj_red'
            // style_obj:'background-color:red'
            // style_obj:[{backgroundColor:'red'},]
            // style_obj:{backgroundColor:'red'}
        }
    })
</script>
</body>
</html>

条件渲染

指令 释义
v-if 相当于: if
v-else 相当于:else
v-else-if 相当于:else if
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <style>
        .cls_obj_red{
            background-color: red;
        }
    </style>
</head>
<body>
<div id="app">
    <p v-if="show">嘀哩嘀哩</p>
    <p v-if="type==1">1</p>
    <p v-else-if="type==2">2</p>
    <p v-else-if="type==3">3</p>
    <p v-else="">Boom!</p>
</div>

<script>
    var vm = new Vue({
        el:'#app',
        data:{
            show:true,
            type:1
        }
    })
</script>
</body>
</html>

列表渲染

v-if + v-for

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link rel="stylesheet" href="bootstrap.min.css">

</head>
<body>
<div id="app">
    <button @click="shopping_click" class="btn btn-primary">哔哩哔哩</button>
    <table class="table table-hover table-striped">
        <thead>
            <tr>
                <th>编号</th>
                <th>商品名</th>
                <th>单价</th>
            </tr>
        </thead>
        <tbody>
            <tr v-if="shopping.length==0">
                <td>售罄</td>
                <td>售罄</td>
                <td>售罄</td>
            </tr>
            <tr v-else v-for="value,key in shopping">
                <td>{{key+1}}</td>
                <td>{{value.name}}</td>
                <td>{{value.price}}</td>
            </tr>
        </tbody>
    </table>
</div>

<script>
    var vm = new Vue({
        el:'#app',
        data:{
            shopping:[]
        },
        methods:{
            shopping_click(){
                this.shopping=[
                    {id:1,name:'小包子', price:188},
                    {id:2,name:'包子', price:288},
                    {id:3,name:'大包子', price:388}
                ]
            }
        }
    })
</script>
</body>
</html>

v-for

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link rel="stylesheet" href="bootstrap.min.css">

    <style>
        .cls_obj_red{
            background-color: red;
        }
    </style>
</head>
<body>
<div id="app">
    <p v-for="name in names">id:{{name.cid}} name: {{name.name}} age: {{name.age}}</p>
</div>

<script>
    var vm = new Vue({
        el:'#app',
        data:{
            names:[
                {cid:1, name:'jerry', age:18},
                {cid:2, name:'tom', age:19},
                {cid:3, name:'哔哩哔哩', age:20}
            ]
        }
    })
</script>
</body>
</html>

数组更新与检测

<!--vue中使用的是虚拟DOM, 会和原生的DOM进行比较, 然后进行数据的更新,提高数据的刷新速度(虚拟DOM用了diff算法)-->

一定会触发DOM的比较,如果有数据变了,页面没变,使用该方法赋值 ↓
Vue.set(vm.class_obj, 'background', true)

过滤

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link rel="stylesheet" href="bootstrap.min.css">

</head>
<body>
<div id="app">
    
    <input type="text" @input="changeData" v-model="search" >
    <p v-for="value in new_list">{{value}}</p>
</div>

<script>
    var vm = new Vue({
        el:'#app',
        data:{
            search:'',
            list:['a', 'ab', 'b', 'bs'],
            new_list:['a', 'ab', 'b', 'bs']
        },
        methods: {
            changeData(){
                this.new_list = this.list.filter(item=>{
                    return item.indexOf(this.search)>-1
                })
            }
        }
    })
</script>
</body>
</html>

事件修饰符

事件修饰符 释义
.stop 只处理自己的事件,父控件冒泡的事件不处理(阻止事件冒泡)
.self 只处理自己的事件,子控件冒泡的事件不处理
.prevent 阻止a链接的跳转
.once 事件只会触发一次(适用于抽奖页面)

使用修饰符时,顺序很重要,相应的代码会以同样的顺序产生

@click.prevent.self		:会阻止所有的点击
@click.self.prevent		:只会阻止对元素自身的点击
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件修饰符</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
<!--    <ul @click="handleUl">-->
    <ul @click.self="handleUl">
<!--        <li v-for="data in dataList" @click="handleLi">{{data}}</li>-->
        <li v-for="data in dataList" @click.stop="handleLi">{{data}}</li>
        <li><a href="http://www.baidu.com">不拦截</a></li>
        <li><a href="http://www.baidu.com" @click="handleLink($event)">点击拦截</a></li>
        <li><a href="https://www.baidu.com" @click.prevent="handleLink">点击拦截</a></li>
        <li><button @click.once="test">只执行一次</button></li>
    </ul>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#box',
        data: {
            dataList: ['1','22','333','4444']
        },
        methods: {
            handleUl(ev){
                console.log('ul被点击了')
            },
            handleLi(){
                console.log('li被点击了')
                ev.stopPropagation()    // 点击事件停止 冒泡(向父组件传递时间)
            },
            handleLink(ev){
                ev.preventDefault()
            },
            test(){
                alert('只触发1次')
            }
        }
    })
</script>
</html>

数据的双向绑定(v-model的使用)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link rel="stylesheet" href="bootstrap.min.css">


</head>
<body>
<div id="app">

    <input type="text" v-model="test">{{test}}
</div>

<script>
    var vm = new Vue({
        el:'#app',
        data:{
            test:'',
        }
    })
</script>
</body>
</html>

按键修饰符

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>按键修饰符</title>
    <script src="./js/vue.js"></script>
</head>

<body>


<div id="app">

    <input type="text" v-model="name" @keyup="handelKey1">
    <input type="text" v-model="name" @keyup.enter="handelKey2">
    <!--    <button @click="handelClick">点我</button>-->

</div>


</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: ''
        },
        methods: {
            handelKey1(ev) {
                console.log(ev)
                if (ev.keyCode == 13) {
                    console.log('按下了回车')
                }
            },
            handelKey2() {
                console.log('回车键按下了')
            },
            handelClick(ev) {
                console.log(ev)
            }
        }

    })
</script>

</html>

表单控制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>表单控制</title>
    <script src="./js/vue.js"></script>
</head>

<body>


<div id="app">

    <h1>checkbox的选中与不选中</h1>
    <p>用户名: <input type="text" v-model="name"></p>
    <p>密码: <input type="password" v-model="password"></p>
    <p><input type="checkbox" v-model="isRem">记住密码</p>
    <button @click="submit">登录</button>
    <hr>
    <h1>性别单选:radio</h1>

    <input type="radio" v-model="gender" value="1">男
    <input type="radio" v-model="gender" value="2">女
    <input type="radio" v-model="gender" value="3">其他
    <br>
    您选择的性别是:{{gender}}
    <hr>
    <h1>爱好多选:checkbox</h1>

    <input type="checkbox" v-model="hobby" value="1">篮球
    <br>
    <input type="checkbox" v-model="hobby" value="2">足球
    <br>
    <input type="checkbox" v-model="hobby" value="3">美女
    <br>
    您的爱好是:{{hobby}}

</div>


</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: '',
            password: '',
            isRem: false,
            gender: '',
            hobby:[],
        },
        methods: {
            submit() {
                console.log(this.name)
                console.log(this.password)
                console.log(this.isRem)
            }
        }

    })
</script>

</html>

购物车案例(全选、数量加减)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link rel="stylesheet" href="bootstrap.min.css">
</head>
<body>
<div id="app">

    <table class="table-hover table table-striped">
        <thead>
        <tr>
            <th>商品名</th>
            <th>单价</th>
            <th>数量</th>
            <th>选择 <input type="checkbox" v-model="allCheck" @change="allChange"></th>
        </tr>
        </thead>
        <tbody>
            <tr v-for="shop in shop_list">
                <td>{{shop.name}}</td>
                <td>{{shop.price}}</td>
                <td><button class="btn btn-primary" @click="click_down(shop)">-</button>{{shop.num}}<button class="btn btn-primary" @click="shop.num++">+</button></td>
                <td><input type="checkbox" :value="shop" v-model="check_list" @change="oneChange"></td>
            </tr>
        </tbody>
    </table>
总价为: {{get_price()}}
</div>


<script>
    var vm = new Vue({
        el: '#app',
        data: {
            shop_list:[
                {name:'哔哩', price:123, num:2},
                {name:'书', price:323, num:3},
                {name:'滴滴', price:223, num:4},
            ],
            check_list:[],
            allCheck:false
        },
        methods:{
            get_price(){
                let total = 0
                if (this.check_list.length > 0){
                    for (i in this.check_list){
                        total += this.check_list[i].num * this.check_list[i].price
                    }
                }
                return total
            },
            allChange(){
                if (this.allCheck){
                    this.check_list = this.shop_list
                }else {
                    this.check_list=[]
                }
            },
            oneChange(){
                if (this.check_list.length === this.shop_list.length){
                    this.allCheck = true
                }else {
                    this.allCheck = false
                }
            },
            click_down(shop){
                if (shop.num >1){
                    shop.num --
                }else {
                    shop.num = 1
                }
            }
        }
    })
</script>
</body>
</html>

v-model进阶

  • .lazy :并不是实时改变,而是在失去焦点或者按回车时才会更新
  • .number :将输入转换成Number类型
  • .trim :可以自动过滤输入首尾的空格
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-model进阶</title>
    <script src="./js/vue.js"></script>
</head>

<body>


<div id="app">

<!--    <input type="text" v-model.lazy="name"> 输入内容是:{{name}}-->
<!--    <input type="text" v-model.number="name"> 输入内容是:{{name}}-->
    <input type="text" v-model.trim="name"> 输入内容是:{{name}}

</div>


</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: ''

        },

    })
</script>

</html>

Vue生命周期钩子

img

钩子函数 描述
beforeCreate 创建Vue实例之前调用
created 创建Vue实例成功后调用(可以在此处发送异步请求后端数据)
beforeMount 渲染DOM之前调用
mounted 渲染DOM之后调用
beforeUpdate 重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
updated 重新渲染完成之后调用
beforeDestroy 销毁之前调用
destroyed 销毁之后调用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>v-model进阶</title>
    <script src="./js/vue.js"></script>
</head>

<body>


<div id="app">

<!--    <child v-if="isShow"></child>-->
</div>


</body>
<script>
    //定义一个组件
    Vue.component('child', {
        template: `
            <div>
                {{name}}
                <br>
                {{age}}
                <button @click="name='Darker1'">更新数据1</button>
                <button @click="name='Darker2'">更新数据2</button>
            </div>`,
        data() {
            return {
                name: 'Darker1',
                age: 19
            }
        },

        beforeCreate() {
            console.group('当前状态:beforeCreate')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        created() {
            console.group('当前状态:created')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        beforeMount() {
            console.group('当前状态:beforeMount')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        mounted() {
            console.group('当前状态:mounted')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
            //用的最多,向后端加载数据,创建定时器等
            console.log("页面已被vue实例渲染, data, methods已更新");
            console.log('mounted')
            this.t = setInterval(function () {
                console.log('daada')
            }, 3000)

            clearInterval(this.t)

        },
        beforeUpdate() {
            console.group('当前状态:beforeUpdate')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        updated() {
            console.group('当前状态:updated')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        beforeDestroy() {
            console.group('当前状态:beforeDestroy')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        destroyed() {
            console.group('当前状态:destroyed')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
            //组件销毁,清理定时器
            clearInterval(this.t)
            this.t = null
            console.log('destoryed')
        },


    })


    var vm = new Vue({
        el: '#app',
        data: {
            isShow: true

        },
        methods:{
            init(){
                console.log('init')
            },

        },
        mounted() {
            console.log('mounted执行;了')
            //ajax向后端获取数据
            this.init()

        },



    })
</script>

</html>

与后端交互的几种方式

向后端发送ajax请求

三种方式

  • jQuery的ajax
  • fetch(原生)
  • axios(用的最多)

jQuery的ajax

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="./js/vue.js"></script>
</head>
<body>

<div id="app">
   <div v-for="data in data_list">
       <h3>{{data.name}}</h3>
       <img :src="data.poster" alt="">
       <h5>导演:{{data.director}}</h5>
   </div>

</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            data_list: []
        },
        methods: {
            get_data() {
                //发送请求
                // let _this=this
                $.ajax({
                    url: 'http://127.0.0.1:5000/',
                    type: 'get',
                    success: (data) => {
                        let data_obj=JSON.parse(data)
                        // console.log(typeof data_obj)
                        this.data_list = data_obj.data.films
                    }
                    // success: function (data) {
                    //     // console.log(data)
                    //     _this.data_list = data
                    // }
                })
            }
        },
        mounted() {
            this.get_data()
        },
    })
</script>
</html>

fetch(原生)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>

<div id="app">
    <div v-for="data in data_list">
        <h3>{{data.name}}</h3>
        <img :src="data.poster" alt="">
        <h5>导演:{{data.director}}</h5>
    </div>

</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            data_list: []
        },
        methods: {
            get_data() {
                //发送请求
                fetch("http://127.0.0.1:5000/").then(res => res.json()).then(res => {
                    console.log(res.data.films)
                    this.data_list = res.data.films
                })

            }
        },
        mounted() {
            this.get_data()
        },
    })
</script>
</html>

axios(用的最多)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>

<div id="app">

    <div v-for="data in data_list">
        {[ data.name ]}
        <img :src="data.poster" alt="">
        {[ data.director ]}
        {[ data.synopsis ]}
    </div>

</div>


<script>
    var vm = new Vue({
        el:'#app',
        data:{
            data_list:[]
        },
        delimiters:['{[', ']}'],
        methods:{
            get_data(){
                axios({
                    url:'http://127.0.0.1:8090/index/',
                    methods:'get'
                }).then(res=>{
                    this.data_list = res.data.data.films
                })
            }
        },
        mounted(){
            this.get_data()
        }
    })
</script>
</body>
</html>

计算属性

优点

  • 在同一个页面中使用多次计算属性,不会多次执行
  • 不需要加括号,直接使用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>

<div id="app">
    <input type="text" v-model='name'>
    <br>
    您输入的是:{{get_name()}}
    <br>
    您输入的是2:{{get_name()}}

    <hr>
<!--    您输入的是:{{name.substring(0,1).toUpperCase()+name.substring(1)}}-->
<!--    计算属性优点-->
<!--    1 在同一个页面中使用多次计算属性,不会多次执行-->
<!--    2 不需要加括号,直接使用-->


    <br>
     计算属性:您输入的是:{{upper_name}}
    <br>
     计算属性2:您输入的是:{{upper_name}}
     计算属性2:您输入的是:{{upper_name}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name:''
        },
        computed:{

            upper_name(){
                console.log('计算属性我执行了')
                return this.name.substring(0,1).toUpperCase()+this.name.substring(1)
            },
        },
        methods:{
            get_name(){
                console.log('get_name我执行了')
                return this.name.substring(0,1).toUpperCase()+this.name.substring(1)
            },
        }

    })
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>

<div id="app">
    <input type="text" v-model='search'>
    <div v-for="data in new_list">
        {{data}}
    </div>


</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            search: '',
            data_list: ['aaa', 'abc', 'abcde', 'abcdef', 'bbb', 'bac']
        },
        computed: {
            new_list() {
                return this.data_list.filter(item => {
                    return item.indexOf(this.search) > -1
                })


            }


        },
        methods: {}

    })
</script>
</html>

虚拟dom和diff算法

其实呢不只是vue,react中在执行列表渲染时也会要求给每个组件添加key这个属性。
key简单点来说就是唯一标识,就像ID一样唯一性
要知道,vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。

只做同层级的对比
按照key值比较,出现新的key就插入
通组件对比

img

image-20201214225437290

具体实现

把树按照层级分解

image-20201214225736585

同key值比较

image-20201214225827633

通组件对比

image-20201214225913886

<div id="box">
    <div v-if="isShow">111</div>
    <p v-else>222</p>
    <!--    
    {tag:div,value:111}
    {tag:p,value:222}
    直接不比较,直接删除div,新增p
    -->

    <div v-if="isShow">111</div>
    <div v-else>222</div>
    <!--    
    {tag:div,value:111}
    {tag:div,value:222}
    比较都是div,只替换文本内容
    -->
</div>

详细:https://segmentfault.com/a/1190000020170310

组件

  • 介绍
  • 全局组件
  • 局部组件
  • 组建通信之父传子

介绍

1 组件的作用
	扩展 HTML 元素,封装可重用的代码,目的是复用
    例如:
    	有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html
		组件把js,css,html放到一起,有逻辑,有样式,有html
    
2 组件分类:局部组件和全局组件

全局组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>

<div id="app">

    <myheader></myheader>

    <div>我是div</div>

    <myheader></myheader>

</div>
</body>
<script>


    // 定义一个全局组件
    // 组件可以有data,methods,computed....,但是data 必须是一个函数

    Vue.component('myheader', {
        template: `
         <div>
            <h1 style="background-color: greenyellow">我是全局组件:{{name}}</h1>
            <button @click="handleClick">点我弹出美女</button>

        </div>
        `,
        data(){
            return {
                name:'lqz'
            }
        },
        methods:{
            handleClick(){
                alert('美女')
            }
        },
        mounted(){},
        computed:{

        }


    })

    var vm = new Vue({
        el: '#app',
        data: {},

    })
</script>
</html>

局部组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>

<div id="app">

    <myheader></myheader>

    <div>我是div</div>

    <myheader></myheader>

    <div></div>


</div>
</body>
<script>


    // 定义一个全局组件
    //组件可以有data,methods,computed....,但是data 必须是一个函数

    Vue.component('myheader', {
        template: `
         <div>
            <h1 style="background-color: greenyellow">我是全局组件:{{name}}</h1>
            <button @click="handleClick">点我弹出美女</button>
            <hr>
            <child></child>

        </div>
        `,
        data(){
            return {
                name:'lqz'
            }
        },
        methods:{
            handleClick(){
                alert('美女')
            }
        },
        mounted(){},
        computed:{

        },
        components:{
            child:{
                template: `<div>
                            <span>{{age}}</span>
                            </div>`,
                data(){
                    return {
                        age:19
                    }
                },
                methods:{

                }
            }
        }


    })

    var vm = new Vue({
        el: '#app',
        data: {},

    })
</script>
</html>

组建通信之父传子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>

<div id="app">


    <myheader :myname="name" :myshow="false"></myheader>

    {{obj.length}}



</div>
</body>
<script>


    // 定义一个全局组件
    //组件可以有data,methods,computed....,但是data 必须是一个函数

    Vue.component('myheader', {
        template: `
         <div>
            <h1 style="background-color: greenyellow">我是全局组件:{{myname}}</h1>
            <button @click="handleClick">点我弹出美女</button>
            <br>
            {{myshow}}
            <hr>
            <child v-if=""></child>

        </div>
        `,
        data(){
            return {
                name:'lqz'
            }
        },
        methods:{
            handleClick(){
                alert('美女')
            }
        },
        mounted(){},
        computed:{

        },
        components:{
            child:{
                template: `<div>
                            <span>{{age}}</span>
                            </div>`,
                data(){
                    return {
                        age:19
                    }
                },
                methods:{

                }
            }
        },
        // props:['myname'] , //注册一下

        // 属性验证
        props:{
            myname:String,
            myshow:Boolean
        },


    })

    var vm = new Vue({
        el: '#app',
        data: {
            name:'egon'
        },

    })
</script>
</html>

组建通信之子传父(通过自定义事件)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="box">

    <navbar @myevent="handleEvent"></navbar>


</div>
</body>
<script>
    // 定义全局组件
    Vue.component('navbar', {
        template: `
        <div>
            <h1>我是navbar</h1>
            <hr>
            <input type="text" v-model="name">
            <br>

            <button @click="handleClick">我是子组件的button</button>
        </div>
        `,
        data() {
            return {
                name: 'lqz'
            }
        },
        methods: {
            handleClick() {
                // 触发父组件中myevent这个自定义事件对应的函数执行
                this.$emit('myevent',this.name)
            }
        }
    })
    var vm = new Vue({
        el: '#box',
        data: {},
        methods: {
            handleEvent(name) {
                console.log('我执行了')
                console.log('从子组件传递的name:'+name)
            }
        }

    })
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="box">

    <navbar @myevent="handleEvent" v-if="myshow"></navbar>


</div>
</body>
<script>
    // 定义全局组件
    Vue.component('navbar', {
        template: `
        <div>
            <h1>我是navbar</h1>
            <hr>

            <button @click="handleClick">点我隐藏子组件</button>
        </div>
        `,
        data() {
            return {
                // myshow: true
            }
        },
        methods: {
            handleClick() {
                // 触发父组件中myevent这个自定义事件对应的函数执行
                // this.myshow = !this.myshow
                this.$emit('myevent', false)
            }
        }
    })
    var vm = new Vue({
        el: '#box',
        data: {
            myshow: true
        },
        methods: {
            handleEvent(show) {
                this.myshow = show
            }
        }

    })
</script>
</html>

ref属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="box">
    ref放在标签上,拿到的是原生节点
    <br>
    ref放在组件上,拿到的是组件对象(数据,方法,直接使用即可)
    <hr>
    <h1>ref用在标签上</h1>
    <input type="text" ref="myinput">
    <button @click="handleClick">点我触发事件</button>

    <hr>
    <h1>ref用在组件上</h1>
    <navbar ref="mynavbar"></navbar>


</div>
</body>
<script>
    // 定义全局组件
    Vue.component('navbar', {
        template: `
        <div>
            <h3>我是navbar</h3>
            <hr>
        </div>
        `,
        data() {
            return {
                myshow: true
            }
        },
        methods: {
            handleClick(a) {
                console.log('父组件调用我,传入了:'+a)
            }
        }
    })
    var vm = new Vue({
        el: '#box',
        data: {
            myshow: true
        },
        methods: {
            handleClick() {
                //this.$refs 取到一个对象,放着你在标签上写得ref对应的value值

                //在父组件中直接取到了子组件的值(从子传到父)
                // console.log(this.$refs.mynavbar.myshow)
                //从父传子
                // this.$refs.mynavbar.myshow='sss'
                //调用子组件方法
                this.$refs.mynavbar.handleClick('lqz')

            }
        }

    })
</script>
</html>

事件总线

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="box">

    <child1></child1>

    <hr>
    <child2></child2>




</div>
</body>
<script>
    // 借助事件总线,实现跨组件通信
    //定义一个事件总线

    var bus=new Vue()

    Vue.component('child1', {
        template: `
        <div>
            <input type="text" v-model="msg">
            <button @click="send_msg">发送</button>
            <hr>
        </div>
        `,
        data() {
            return {
                msg: ''
            }
        },
        methods:{
            send_msg(){
                bus.$emit('suibian',this.msg)
            }
        }
    })

    Vue.component('child2', {
        template: `
        <div>
            <h5>我收到的内容是:{{recv_msg}}</h5>
        </div>
        `,
        data() {
            return {
                recv_msg:''
            }
        },
        mounted(){
            bus.$on('suibian',msg=> {
                this.recv_msg=msg
            })
        }
    })

    var vm = new Vue({
        el: '#box',
        data: {},
        methods: {}

    })
</script>
</html>

动态组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="box">


    <button @click="who='Home'">首页</button>
    <button @click="who='User'">用户</button>
    <button @click="who='Order'">订单</button>

    <keep-alive>
        <component :is="who"></component>
    </keep-alive>

</div>
</body>
<script>

    Vue.component('Home', {
        template: `
        <div>
            首页
        </div>
        `,
        data() {
            return {}
        },
    })

    Vue.component('User', {
        template: `
        <div>
           用户组件
           <input type="text" v-model="name">
        </div>
        `,
        data() {
            return {
                name: ''
            }
        },
    })
    Vue.component('Order', {
        template: `
        <div>
            订单页面
        </div>
        `,
        data() {
            return {}
        },
    })

    var vm = new Vue({
        el: '#box',
        data: {
            who: 'Home'
        },

    })
</script>
</html>

插槽

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="box">

    <Home>阿斯顿发送到</Home>

    <Order>
        <button slot="b" @click="handleClick">我是个按钮</button>
    </Order>


</div>
</body>
<script>

    Vue.component('Home', {
        template: `
        <div>
            首页
            <div>
                <slot></slot>
            </div>

        </div>
        `,
        data() {
            return {}
        },
    })

    Vue.component('Order', {
        template: `
        <div>
            订单页面

            <slot name="a"></slot>
            <br>
            我是一行数据
            <br>
            <slot name="b"></slot>


        </div>
        `,
        data() {
            return {}
        },
    })

    var vm = new Vue({
        el: '#box',
        data: {
            who: 'Home'
        },
        methods:{
            handleClick(){
                console.log('我被点了')
            }
        }

    })
</script>
</html>

Vue-CLI 搭建vue项目

1 ECMAScript,javascript,nodejs的关系
2 安装nodejs(安装解释器)
3 java:sun---》oracle(甲骨文)----》有些包,收费
	-安卓使用java开发,涉及到版权
    -jdk:java开发工具包,做java开发,需要安装它  1.5 1.8大更新   java 15
    -jre:java运行环境,
    -jvm:java虚拟机,最少要占200m内存空间
    
    
4   安装node,一路下一步
	node:就是python命令
    npm:就是python的pip命令,npm下载模块慢,我们使用cmpm下载
    cnpm:阿里提供的
    npm install -g cnpm --registry=https://registry.npm.taobao.org
5 安装vue脚手架
cnpm install -g @vue/cli

6 多出vue命令
    vue create my-project: 创建出一个vue项目,等同于djagnoadmin createproject 名字
    # OR
    vue ui
7 开发
	-使用pycharm开发vue项目
    -装vue插件
8 运行起项目
	-terminal中:npm run serve

1626408322582

1626408646319

1626409485838

vue项目目录介绍

myfirstvue  # 项目名
	-node_modules # 该项目所有的依赖,如果要把项目给别人,这个文件夹要删掉(很大)
    -public # 文件夹
        -favicon.ico #小图标
        -index.html  # 整个vue项目的index.html,单页面开发
        
    -src    # 核心
        -store # 如果装了vuex,就会有这个文件夹
        -router #如果装了vue router ,就会有这个文件夹
        -assets # 存放资源文件(js,css,img)
        -components # 小组件(在这写小组件)
        -views      #页面组件(在这写页面组件)
        main.js     # 整个项目的入口,核心配置
        App.vue     # 根组件
       
   -package.json # 项目的依赖,不能删
   -README.md    # 介绍  
        

vue组件介绍

每个组件有三部分组成
	template:写html
    script:写js
    style:写css
<template>   
  <div class="about">
    <h1>写html</h1>
  </div>
</template>

<script>

js代码

</script>

<style>

css代码

</style>

vue-router的使用

1 以后,新建一个页面组件,写三部分
2 在router下的index.js内配置一下
const routes = [
    {  // / 路径,显示Home这个页面组件
        path: '/',
        name: 'Home',
        component: Home
    },
    {
        path: '/order',
        name: 'Order',
        component: Order
    },
    {
        path: '/about',
        name: 'About',
        // component: () => import('../views/About.vue')
        component: About,
    }
]


3 在根vue中写
 <div id="app">
    <router-view/>
  </div>

4 以后要跳转到某个页面
 <router-link to="/路径">
     <button>点我跳转到order</button>
</router-link>

在项目中新建组件和使用

1 在components文件夹创建一个 xx.vue
2 在其他组件中使用
	-在scripts中
    import HelloWorld from '../components/HelloWorld.vue'
    export default {
      name: 'Home',
      components: {
        HelloWorld
      }
	}
    
3 在html中直接使用
<HelloWorld/>

js导入导出语法(了解)

1 有一些变量,函数,想在其他地方都用,可以写成一个包
新建一个文件夹,在文件夹中写index.js
在内部写函数,写变量,最后一定要导出
var name='lqz'
function add(a,b) {
    return a+b
}
export default {
    name,
    add
}
2 在想用的位置,导入使用即可
import xx from '../lqz'
console.log(xx.add(1,2))

使用axios

1 安装 cnpm install axios
2 导入使用
   import axios from 'axios'
   axios.get('api/index/').then(res => {})

前端代理

1 vue.config.js中module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://127.0.0.1:8000',
        changeOrigin: true
      }
    }
  },
}

2 使用axios发送请求
      mounted() {
            axios.get('api/index/').then(res => {
                console.log(res.data)
                this.data_list = res.data.data.films
            })
        }

bootstrap和jq的使用

1 安装
cnpm install jquery
cnpm install bootstrap@3

2 配置vue.config.js中
const webpack = require("webpack");
module.exports = {
    configureWebpack: {
        plugins: [
            new webpack.ProvidePlugin({
                $: "jquery",
                jQuery: "jquery",
                "window.jQuery": "jquery",
                "window.$": "jquery",
                Popper: ["popper.js", "default"]
            })
        ]
    }
};

3 main.js中
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'

elementui的使用

1 安装
cnpm install element-ui -S
2 main.js中配置
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
posted @ 2021-07-18 17:08  Jerry`  阅读(108)  评论(0编辑  收藏  举报