Loading

Vue2基础

【一】初识Vue

【1】什么是Vue

Vue 是一套用于构建用户界面的渐(逐渐)进(递进)式 JavaScript 框架

Vue 可以自底向上逐层应用,由国人尤雨溪开发

采用组件化模式,提高代码的复用率、让代码更好维护

声明式编码方式,让编码人员无需直接操作 DOM,提高开发效率

使用虚拟DOM + 优秀的 Diff 算法,尽量复用 DOM 节点

Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:

【2】引入Vue

本地方式引入

<script src="../js/vue.js"></script>

网络CDN方式引入

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

【3】Vue基本结构

在初学阶段,Vue 的结构由 容器 + 对象 两大部分构成

<body>
<div id="app">
    {{name}}
    {{age}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app', // 这是Vue对象所绑定的容器对象,一般使用css选择器绑定
        data: {     // data用于存储数据
            name: 'green',
            age: 18
        }
    })
</script>

【二】基础知识

【1】模板语法

插值语法

<body>
<div id="app">
    {{name}}
    <br>
    {{age}}
    <br>
    {{hobby}}|{{hobby[0]}} // 数组只能用中括号取值
    <br>
    {{obj}}|{{obj.name}}|{{obj["name"]}} // 对象可以用中括号或者点属性取值
    <br>
    {{link}}
</div>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: 'green',
            age: 18,
            hobby: ['洗衣服', '做饭', '打游戏'],
            obj: {name: "hqq", age: 22, hobby: ['抽烟', '喝酒', '洗脚']},
            link: '<a href="https://meizi5.com">点击看美女</a>'
        }
    })
</script>
</body>

指令语法

<div id="root">
    <!-- v-bind 可以简写为 : -->
    <a v-bind:href="url">点我去百度 - 完整写法</a>
    <a :href="url">点我去百度 - 简略写法</a>
</div>

<script>
    new Vue({
        el: '#root',
        data: {
            url: 'https://www.baidu.com'
        }
    })
</script>

总结

​ 插值语法

​ 功能:用于解析标签体中的内容

​ 写法:{{xxxx}},其中 xxxx 是 js 表达式,且可以直接读取到 data 中的所有属性

​ 指令语法

​ 功能:用于解析标签(包括:标签属性,标签体内容,绑定事件)

【2】数据绑定

单向绑定:str变---》input框变,input框变---》str不变

单向绑定:str变---》input框变,input框变---》str也变

<div id="app">
单向绑定 <input type="text" :value="str">
双向绑定 <input type="text" v-model:value="str">
</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
            str: '炎帝萧炎'
        }
    })
</script>
</body>

总结

总结:

单向绑定(v-bind):数据只能由 data 流向页面

双向绑定(v-model)

数据既能从 data 流向页面,也能从页面流向 data

双向绑定一般都应用在表单类元素上(input、select...)

v-model:value 可以简写为 v-model,因为 v-model 默认绑定的就是 value 属性

【3】事件指令

es6的对象写法

// es6 的对象写法
var hobby=['抽烟','烫头']
var obj={  
    'name':'hqq',
    age:19,  // 键值可以不带引号 
    hobby, // 可以直接省略键名,在有定义的情况下
    showName() {
        console.log(this.name)
      // 函数可以省略:function
    }
}

函数传参数问题

<body>
<div id="app">
    <button v-on:click="showFunc1">不传参数,函数有参数(会自动把当前事件传入)</button>
    <button v-on:click="showFunc2(name)">传参数,函数有参数(正常输出)</button>
    <button v-on:click="showFunc3($event)">传参数,函数有参数,把事件对象传入(正常输出)</button>
    <button v-on:click="showFunc4()">传参数,函数有多个参数,少传参数(少传就输出传入的,多传就不关多出来的)</button>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            name: 'green'
        },
        methods: {
            showFunc1(event) {
                console.log(event)
            },
            showFunc2(param) {
                console.log(param)
            },
            showFunc3(event) {
                console.log(event)
            },
            showFunc4(a,b,c) {
                console.log(a,b,c)
            }
        }
    })
</script>

【4】属性指令

1. 标签上有属性 如:
img的src属性,a标签的href属性

2. 属性指令的作用就是使用变量动态的设置属性的值

3. 使用方法
	v-bind:属性名='变量'
    简写
    :属性名='变量'

动态切换美女图片案例

<body>
<div id="app">
    <button @click="handleClick">点击切换自动切换美女</button>
    <img :src="src" alt="">
</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
            list: ['/img/1.jpg', '/img/2.jpg', '/img/3.jpg'],
            src: '',
            index: 0,
            flag: false,
            t: null
        },
        methods: {
            handleChange() {
                console.log(this.index)
                this.src = this.list[this.index]
                this.index += 1
                if (this.index === 3) {
                    this.index = 0
                }
            },
            handleClick() {
                if (this.flag === false) {
                    this.t = setInterval(this.handleChange, 1000)
                    this.flag = true
                } else {
                    clearInterval(this.t)
                    this.flag = false
                }

            }
        }
    })
</script>
</body>

补充:js中的计时器

js 定时器有以下两个方法:

setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式。方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。
setTimeout() :在指定的毫秒数后调用函数或计算表达式。

语法
setInterval(code,millisec,lang)
code 必需。要调用的函数或要执行的代码串。
millisec  	必须。周期性执行或调用 code 之间的时间间隔,以毫秒计。
lang	可选。 JScript | VBScript | JavaScript

【5】style和class

# 1 class 可以绑定 字符串,数组,对象
	字符串: 'div1 div2'---》字符串替换控制样式
    数组:['div1','div2']--->追加数组,删除数组控制样式
    对象:{div1: true, div2: true, div3: true, div4: false}--》通过true和false控制样式
    
# 2 style 可以绑定 字符串,数组,对象
	字符串'background-color: green;height: 300px;width: 300px'---》字符串替换控制样式
    数组:[{'background-color': 'green'}, {height: '300px'}, {width: '300px'}]--->追加数组,删除数组控制样式
    对象:{backgroundColor: 'green', height: '330px', width: '300px'} --》通过根据key修改value控制样式

    
    
# 3 坑:以后如果改了对象,或数组,发现页面没有变化,实际上值被真正的改了
	Vue.set(this.style_list,3,{'margin':'auto'})
    

【6】条件渲染

v-if v-else-if v-else

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

    </style>
</head>
<body>
<div id="app">
    <h1>条件判断</h1>
    <h2>分数是:{{score}}</h2>
    <h3 v-if="score>=90&&score<=100">优秀</h3>
    <h3 v-else-if="score>=80&&score<90">良好</h3>
    <h3 v-else-if="score>=60&&score<80">及格</h3>
    <h3 v-else>不及格</h3>


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

        }

    })


</script>
</html>

【7】列表渲染

通过使用v-for循环显示多条数据

购物车案例

<body>
<div class="container text-center" id="app">
    <div class="row">
        <div class="col-6 offset-3">
            <h1 class="text-center">购物车</h1>
            <button class="btn btn-success" @click="showGood">加载购物车</button>
            <div v-if="!good_list">空空如也</div>
            <table class="table table-info">
                <thead>
                <tr>
                    <th scope="col">商品ID</th>
                    <th scope="col">商品名称</th>
                    <th scope="col">商品数量</th>
                    <th scope="col">商品价格</th>
                    <th scope="col">商品图片</th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="good in good_list">
                    <th scope="row">{{good.id}}</th>
                    <td>{{good.name}}</td>
                    <td>{{good.number}}</td>
                    <td>{{good.price}}</td>
                    <td><img v-bind:src="good_img" alt="" v-bind:style="style_dic"></td>
                </tr>
                </tbody>
            </table>
        </div>
    </div>
</div>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            good_list: null,
            good_img: null,
            style_dic: {}
        },
        methods: {
            showGood() {
                this.good_list = [
                    {'id': 1, 'name': '短裙', 'number': 20, 'price': 22},
                    {'id': 2, 'name': '黑丝', 'number': 34, 'price': 43},
                    {'id': 3, 'name': '白丝', 'number': 55, 'price': 12},
                    {'id': 4, 'name': '过膝袜', 'number': 19, 'price': 5},
                    {'id': 5, 'name': '马油袜', 'number': 39, 'price': 3},
                ]
                this.good_img = '/img/1.jpg'
                Vue.set(this.style_dic, 'width', '30px')
                Vue.set(this.style_dic, 'height', '30px')
            }
        }
    })
</script>
</body>

for循环不同数据类型

<body>
<div id="app">
    <h1>for循环字符串</h1>
    <p>默认循环字符,还可以加入第二个参数,循环索引</p>
    <p v-for="(item,index) in str">字符--->{{item}} 索引--->{{index}}</p>

    <h1>for循环数字</h1>
    <p>从1开始循环到最后一个数字(包括最后一个数字)也可以循环索引</p>
    <p v-for="(item,index) in num">数字--->{{item}} 索引--->{{index}}</p>

    <h1>循环数组</h1>
    <p>默认循环元素,还可以加入第二个参数,循环索引</p>
    <p v-for="(item,index) in list">元素--->{{item}} 索引--->{{index}}</p>

    <h1>循环对象</h1>
    <p>默认循环value值,还可以加入第二个参数,循环键值</p>
    <p v-for="(value,key) in obj">值--->{{value}} 键--->{{key}}</p>
</div>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            list: ['张雪峰', '暴叔', '吉田'],
            str: 'hello word',
            obj: {name: 'green', age: 18},
            num: 10
        }
    })
</script>
</body>

标签内加入key属性

#1 以后写v-for,都要在标签上加  :key="key"  ,key必须唯一

# 2 这样做可以提高虚拟dom的替换效率

【8】事件处理

# 1 input 标签的事件处理
    input	当输入框进行输入的时候 触发的事件
    change	当元素的值发生改变时 触发的事件
    blur	当输入框失去焦点的时候 触发的事件
    focus   当获得焦点的时候 触发的事件
<body>
<div id="app">
    <input type="text" @input="handleInput($event)" value="当输入框进行输入的时候 触发的事件"><br>
    <input type="text" @change="handleChange" value="当元素的值发生改变时 触发的事件"><br>
    <input type="text" @blur="handleBlur" :value="inputValue"><br>
    <input type="text" @focus="handleFocus" :value="inputValue"><br>

</div>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            inputValue: ''
        },
        methods: {
            handleInput(event) {
                console.log(event.data)
            },
            handleChange() {
                alert('发生改变了')
            },
            handleBlur() {
                this.inputValue = '失去焦点了'
            },
            handleFocus(){
                this.inputValue = '得到焦点了'
            }
        }
    })
</script>
</body>

过滤小案例

<body>
<div id="app" class="container-fluid">
    <div class="row">
        <div class="col-6 offset-3">
            <h1 class="text-center">过滤小案例</h1>
            <p class="text-center">搜索框</p>
            <input type="email" class="form-control" v-model:value="kewWord" @input="handleInput">
            <table class="table">
                <tr v-for="item in list">
                    <td class="text-center">{{item}}</td>
                </tr>
            </table>
        </div>
    </div>
</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
            dataList: ['黑丝', '黑丝袜', '黑丝连体袜', '吊带', '吊带蝴蝶结', 'black', 'blac', 'bla'],
            kewWord: 'hahah',
            list: null
        },
        methods: {
            handleInput() {
                let _this = this
                this.list = this.dataList.filter(function (item) {
                    return item.indexOf(_this.kewWord) >= 0
                })
            }
        }

    })
</script>
</body>

# 箭头函数优化代码写法
methods: {
            handleInput() {
                this.list = this.dataList.filter((item)=> item.indexOf(this.kewWord) >= 0
                )
            }
        }

// 流程
核心是 要通过输入框的内容过滤数据列表
输入框的内容可以通过双向绑定得到

通过filter函数过滤,它可以将数组里的一个个元素分别进行校验,如果不通过返回flase,通过返回true

通过 indexOf 方法校验当前输入框的内容和数据数组里的元素是否匹配 如果匹配返回大于0的数,不匹配返回-1

补充:js中的filter函数

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

注意: filter() 不会对空数组进行检测。

注意: filter() 不会改变原始数组。

语法
array.filter(function(currentValue,index,arr), thisValue)

currentValue 当前从array取出校验的元素
index 当前取出的元素的索引
arr 当前元素的来源

补充:es6语法箭头函数

    <!--  初始匿名函数写法-->
    let name = 'green'
    let f = function (name){
      return name + 'nb'
    }
    console.log(f(name))

    // 箭头函数写法,去掉function,在括号和大括号中间加上=>
    let f = (name) => {
        return name + 'nb'
    }
    console.log(f(name))


    // 当函数只需要传一个参数时,可以不用 用括号把参数括起来
    let f = name => {
        return name + 'nb'
    }
    console.log(f(name))


    //  当返回值只有一行代码时,可以不用写return 和 大括号
    let f = name => name + 'nb'

    console.log(f(name))

为什么要写箭头函数?

箭头函数是为了解决function函数的this指向问题,
箭头函数体内的this对象,就是定义该函数时所在的作用域指向的对象,而不是使用时所在的作用域指向的对象。

【9】事件修饰符

​ 在Vue中,事件修饰符处理了许多DOM事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理。

在Vue中事件修饰符主要有:

.stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡

.prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播)

.capture:与事件冒泡的方向相反,事件捕获由外到内

.self:只会触发自己范围内的事件,不包含子元素

.once:只会触发一次

【10】jsfor循环的方式

普通的索引循环

<script>
    <!--    普通的索引循环-->
    let arr = [18, 'green', {name: 'hqq', age: 22}]
    for(let i=0 ;i<arr.length;i++){
        console.log(arr[i])
    }
</script>

基于迭代的off循环

<script>
    <!--    迭代off循环-->
    let arr = [18, 'green', {name: 'hqq', age: 22}]
    for (let item of arr) { // item就是数组里面的一个个元素
        console.log(item)
    }
</script>

基于迭代的in循环

<script>
    <!--    迭代in循环-->
    let arr = [18, 'green', {name: 'hqq', age: 22}]
    for (let index in arr) { // index是索引
        console.log(arr[index])
    }
</script>

数组的forEach方法循环

<script>
    <!--    数组的forEach方法循环-->
    let arr = [18, 'green', {name: 'hqq', age: 22}]
    arr.forEach((value,index,array)=>{ // 分别是元素,索引,数据源数组
        console.log(value,index,array)
    })
</script>

【11】按键修饰符

#1 按下某个键盘,触发事件,通过修饰控制只有按下某个键,才触发事件
#2 keyCode对应表--》按键修饰符
	https://www.cnblogs.com/841019rossi/p/16808455.html


<body>
<div id="app">
  <button @keyup.enter="handleEnter">按回车有惊喜</button>
</div>

<script>
  let vm = new Vue({
    el: '#app',
    data:{},
    methods:{
      handleEnter(){
        alert('回车被按了')
      }
    }
  })
</script>
</body>

【12】表单控制

# 1 checkbox   v-model 绑定 
	-布尔 :选中没选中
    -数组:多选
# 2 radio:
	-字符串:value的值

购物车小案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-/mhDoLbDldZc3qpsJHpLogda//BVZbgYuw6kof4u2FrCedxOtgRZDTHgHUhOCVim"
            crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app" class="container">
    <div class="row">
        <div class="col-6 offset-3">
            <h1 class="text-center">图书商城</h1>
            <p class="text-center">
                <button class="btn btn-success" @click.once="handleLoad">加载购物车</button>
            </p>
            <div class="input-group mb-3">
                <input type="text" class="form-control" placeholder="搜索书名"
                       aria-label="Recipient's username" aria-describedby="button-addon2" v-model="searchText">
                <button class="btn btn-outline-secondary" type="button" id="button-addon2" @click="handleSearch" >搜索
                </button>
            </div>
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th scope="col">id</th>
                    <th scope="col">书名</th>
                    <th scope="col">作者</th>
                    <th scope="col">价格</th>
                    <th scope="col">数量</th>
                    <th scope="col"><p>全选/全不选 <input type="checkbox" v-model="checkAll" @change="handleChange"></p>
                    </th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(book,index) in showList">
                    <th scope="row">{{index + 1}}</th>
                    <td>{{book.title}}</td>
                    <td>{{book.author}}</td>
                    <td>{{book.Price}}</td>
                    <td>
                        <button class="btn" @click="handleSub(book)">-</button>
                        {{book.num}}
                        <button class="btn" @click="handleAdd(book)">+</button>
                    </td>
                    <td><input type="checkbox" v-model="checkList" @change="handleSum" :value="book"></td>

                </tr>
                </tbody>

            </table>
            <p>总价格</p>
            <input type="text" class="form-control" readonly :value="getSum">
        </div>
    </div>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            bookList: [],
            checkList: [],
            checkAll: null,
            searchText: '',
            showList: []
        },
        methods: {
            handleLoad() {
                axios.get('http://127.0.0.1:8000/api/v1/book/')
                    .then((response) => {
                        for (const responseElement of response.data.results) {
                            responseElement.num = 0
                        }
                        this.bookList = response.data.results
                    })
            },
            handleAdd(book) {
                book.num += 1
                this.handleSum()
            },
            handleSub(book) {
                if (!book.num) {
                    return
                }
                book.num -= 1
                this.handleSum()
            },
            handleSum() {
                this.checkAll = (this.checkList.length === this.bookList.length)
            },
            handleChange() {
                if (this.checkAll) {
                    this.checkList = this.bookList
                } else {
                    this.checkList = []
                }
            },
            handleSearch() {
                this.showList = this.bookList.filter((book) => book.title.indexOf(this.searchText) >= 0)
            }
        },
        computed: {
            getSum() {
                let total = 0
                for (let book of this.checkList) {
                    total += book.num * book.Price
                }
                return total
            }
        }
    })
</script>
</html>

【13】v-model进阶

v-model 之 lazy、number、trim
    lazy:等待input框的数据绑定失去焦点之后再变化
    number:数字开头,只保留数字,后面的字母不保留;字母开头,都保留
    trim:去除首位的空格

【14】vue与ajax

vue的数据与后端进行交互的ajax方式有:

原生js的ajax(不常用)
jquery封装的ajax(不常用)
H5自带的fetch (可能用)
vue的axios(Vue作者推荐用)

原生js的ajax

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
</body>
<script>
/* ajax */
//post数据传递,一般需要接口文档,自己用node写也是可以的
//创建ajax
var xhr = new XMLHttpRequest;
//请求地址
xhr.open('post', 'url');
//请求头
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
//因为ajax异步send还是写这里比较好
xhr.send('name=zhangsan&age=18')
xhr.onreadystatechange = function(){
    if (xhr.readyState === 4){
        if (xhr.status>=200 && xhr.status<300){
            var res = xhr.responseText;
            console.log(res);
        }
    }
}
</script>
</html>

jquery封装的ajax

因为jquery有比较完整的ajax封装,但它主要是操作DOM和Bom,所以一般也不怎么用,作为拓展吧

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- bootcdn的镜像也可以自己下载jquery库-->
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <title>Document</title>
</head>
<body>
</body>
<script>
/* jquery */
 $.ajax({
     method:'post',
     url:'url',
//     // dataType:"",
     data:{
         name:'zhangsan',
         age:18
    },
     success:res=>{
         console.log(res);
     },
//     // error:err=>{

//     // }
 })
</script>
</html>

H5自带的fetch

H5自带的fetch封装的ajax也是比较好的,现在市面上还有些公司在用

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
</body>
<script>
/* fetch */
//get,返回值是对象所以需要调用then()方法,调用出来
 fetch('url?name=zhangsan&age=18').then(res=>res.text()).then(res=>{
      console.log(res);
 })
//post,body里还是不能用对象
 fetch('url',{
    method:'post',
     body:'name=zhangsan&age=14',
     headers: {
         "content-type": 'application/x-www-form-urlencoded'
     }
     //转json数据格式
 }).then(res=>res.json()).then(res=>{
      console.log(res);
 })
</script>
</html>

axios库

主要使用的数据请求方式,因为作者推荐,作者都推荐了嘛,最后还得是看公司,没要求最好还是axios

使用需要下载axios插件,使用方法详见官网:axios官网

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
</body>
<script src="./node_modules/axios/dist/axios.js"></script>
<script>
/* axios */
//设置全局令牌,发送请求就不用特地带令牌了
axios.defaults.headers['authorization'] = 'token'
//get,可以设置全局地址提高代码复用率,减少自己写代码,就不用每个都写这么长的地址,嘿嘿
axios.defaults.baseURL='url'
axios.get('third', {
    params: {
        name: 'lisi',
        age: 20
    }
}).then(res => {
    console.log(res.data);
})
//post
axios.post('/fourth', 'name=a&age=12').then(res => {
    console.log(res);
})
</script>
</html>

【15】计算属性

# 1  计算属性是基于它们的依赖进行缓存的

# 2 计算属性只有在它的相关依赖发生改变时才会重新求值

# 3 计算属性就像Python中的property,可以把方法/函数伪装成属性

# 4 写在computed中,必须返回值--》返回值才是属性
	-以后把他当属性用
    -可以被for循环

通过计算属性实现名字首字母大写

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <input type="text"  v-model="nameText"> ---> {{upperFirst}}
</div>
<script>
    let vm = new Vue({
        el: '#app',
        data:{
            nameText:'',
        },
        methods:{},
        computed:{
            upperFirst(){
                return this.nameText.substring(0, 1).toUpperCase() + this.nameText.substring(1)
            }
        }
    })
</script>
</body>
</html>

【16】监听属性

​ 虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

​ 需要监听哪个属性,就在watch里面写哪个属性,只要这个属性发送改变,就会自动执行这个方法

小案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-/mhDoLbDldZc3qpsJHpLogda//BVZbgYuw6kof4u2FrCedxOtgRZDTHgHUhOCVim"
            crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <button class="btn btn-success" @click="res='python'">python</button>
    <button class="btn btn-info" @click="res='java'">java</button>
    <button class="btn btn-danger" @click="res='go'">go</button>
    result --->{{res}}
</div>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            res: ''
        },
        watch:{ // 想要监听哪个参数就在watch里面写哪个参数,当这个参数发生变化就会自动执行
            // before改变前,back改变后 这两参数可填可不填
            res(before,back){
                console.log(back,before)
            }
        }
    })
</script>
</body>
</html>

【17】生命周期

​ vue生命周期分别有创建、初始化数据、编译模板、挂在DOM、渲染-更新-渲染、卸载利用钩子函数完成对应的项目效果

beforeCreate( 创建前 )

在实例化之后,数据的观测和事件的配置之前的时候调用,此时组件的选项对象还未创建,el 和 data 并未初始化,因此无法访问methods, data, computed等上的方法和数据

created ( 创建后)

在创建之后使用,主要用于数据观测、属性和方法的运算,watch/event事件回调,完成了data 数据的初始化,el没有。 然而,挂在阶段还没有开始.

beforeMount (挂载前)

用于在挂载之前使用,在这个阶段是获取不到dom操作的,把data里面的数据和模板生成html,完成了data等初始化,注意此时还没有挂在html到页面上

mount (挂载后)

用于挂载之后使用,在这个时候可以获取到dom操作,比如可以获取到ref等,操作的dom, 在这个时候只能调用一次ajax,在这个时候el和data都可以获取的到

beforeUpdate (更新前)

在数据更新之前被调用,发生在虚拟DOM重新渲染,可以在该钩子中进一步地更改状态,不会触发重复渲染过程

updated (更新后)

在由于数据更改导致地虚拟DOM重新渲染会调用,调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作,然后在大多是情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环,但是在服务器端渲染期间不被调用,可以用于监听某些数据的时候使用钩子

beforeDestroy(销毁前)

在这个时候还是可以用this来获取,可以用于销毁计时器时候使用,为了防止跳转到其它页面该事件还在执行,还可以清除dom事件等

destroy(销毁后)

在实例销毁之后调用,调用后,所以的事件监听器会被移出,所有的子实例也会被销毁.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <child v-if="showChild"></child>
    <button @click="showChild=!showChild">点我消失</button>
</div>
</body>
<script>
    Vue.component('Child', {
        template: `
          <div>
          <button @click="handleClick">{{ title }}</button>
          </div>`,
        data() {
            return {
                title: 'hello word'
            }
        },
        methods: {
            handleClick() {
                alert(this.title)
                this.title = '你好世界'
            },
        },
        // 在创建实例之前执行 this.title不会有值 this.$el不会有值
        beforeCreate() {
            console.log('beforeCreate')
            console.log(this.title)
            console.log(this.$el)
        },
        // 创建实例时执行 this.$el不会有值
        created() {
            console.log('Create')
            console.log(this.title)
            console.log(this.$el)
        },
        // 挂载之前执行 this.$el不会有值
        beforeMount() {
            console.log('beforeMount')
            console.log(this.title)
            console.log(this.$el)
        },
        mounted() {
            console.log('mounted')
            console.log(this.title)
            console.log(this.$el)
        },
        // 在没有更新数据就不会执行, 有更新的话会在更新之前执行
        beforeUpdate() {
            console.log('beforeUpdate')
            console.log(this.title)
            console.log(this.$el)
        },
        //  // 在没有更新数据就不会执行, 有更新的话会在更新之后执行
        updated() {
            console.log('Updated')
            console.log(this.title)
            console.log(this.$el)
        },
        // 在没有执行删除就不会执行, 有删除操作的话会在删除之前执行
        beforeDestroy() {
            console.log('beforeDestroy')
            console.log(this.title)
            console.log(this.$el)
        },
        // 在没有执行删除就不会执行, 有删除操作的话会在删除之后执行
        destroyed() {
            console.log('destroyed')
            console.log(this.title)
            console.log(this.$el)
        }
    })
    let vm = new Vue({
        el: '#app',
        data: {
            showChild: true
        },
        methods: {}
    })
</script>
</html>

【18】组件的使用

​ 组件分为局部组件和全局组件,全局组件可以在根组件的任意位置使用,局部组件只能使用在父组件里面

​ 组件中的数据,事件都是独立的

全局组件的书写

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


<script>
    // 全局组件的书写
    Vue.component('Child', {
        // 需要通过template挂载
        template: `
          <div><h1>我是全局组件</h1>
          <p>{{ message }}</p>
          <button @click="handleClick">点我显示名字</button>
          </div>`,
        // data需要写成一个函数 然后把值写在函数的返回值里
        data() {
            return {
                message: '需要写在根组件里'
            }
        },
        // 方法的写法和根组件的写法一致
        methods: {
            handleClick() {
                this.message = 'green'
            }
        }
    })

    let vm = new Vue({
        el: '#app',

    })
</script>

局部组件的书写

<body>
<div id="app">
    <p>{{message}}</p>
    <button @click="handleClick">点击显示根组件名字</button>
    <Child></Child>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            message: '我是根组件'
        },
        methods: {
            handleClick() {
                this.message = 'green'
            }
        },
        // 在根组件中定义局部组件,这里以根组件为例子,定义在哪里的局部组件,就只能在哪里使用
        components:{
            Child:{
                template:`<div><h1>我是局部组件,根组件的子组件</h1><button @click="handleClick">点我弹窗</button></div>`,
                data(){
                    return{
                        message:'我是子组件Child'
                    }
                },
                methods: {
                    handleClick(){
                        alert(this.message)
                    }
                }
            }
        }
    })
</script>

【19】组件中通信

​ 各个组件的数据都是独立的,要想实现各个组件的数据互通,需要用到一些特定的方法

父传子

<body>
<div id="app">
    <button @click="handleClick">点击给在子组件发消息</button>
    <!--    1.在子组件标签中绑定数据属性-->
    <Child :message="message"></Child>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            message: ''
        },
        methods: {
            handleClick() {
                this.message = '我是来自父组件的消息--->你好'
            }
        },
        // 定义子组件
        components: {
            Child: {
                template: `
                  <div><h1>我是子组件Child</h1>
                  <p>来自父组件的消息---->{{ message }}</p></div>`,
                // 2.在子组件中定义props,将子组件标签中定义的数据属性键值填入props的数组
                props: ['message']
            }
        }
    })
</script>

子传父

<body>
<div id="app">
    <h1>我是父组件</h1>
    <img :src="src" width="250px" height="300px" alt="" v-if="src">
    <!--    子组件给父组件传参数,需要给子组件标签绑定一个自定义事件-->
    <Child @event="handleEvent"></Child>
</div>
</body>
<script>
    let em = new Vue({
        el: '#app',
        data: {
            src: ''
        },
        methods: {
            handleEvent(src) {
                this.src = src
            }
        },
        components: {
            Child: {
                template: `
                  <div><h1>我是子组件</h1><img :src="src" alt="" width="250px" height="300px" v-if="src">
                  <button @click="handleClick">点击把图片传到父组件</button>
                  </div>`,
                data() {
                    return {
                        src: './img/1.jpg'
                    }
                },
                methods: {
                    handleClick() {
                        // 通过this.$emit('event', this.src),第一个参数就是自定义事件的名称,第二个参数就是传递的参数
                        this.$emit('event', this.src)
                        this.src = ''
                    }
                }
            }
        }
    })
</script>

【20】ref属性

​ ref是Vue2中一个重要的属性,用于在组件中对DOM元素或者子组件的引用。通过ref,可以在某个组件的内部直接访问DOM元素或者它的子组件。

​ 在Vue2中可以将ref添加到元素,组件或者子组件的标签上,然后可以通过组件实例的$refs对象来访问这些引用

<body>
<div id="app">
    <h1>我是父组件</h1>
    <button @click="handleClick" ref="button">点我看控制台</button>
    <Child ref="child"></Child>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {},
        methods: {
            handleClick() {
                // this是当前Vue的实例
                // this.$refs是一个对象,里面包含了所有的有ref属性的标签的dom对象或者组件对象
                // 1.拿到子组件的属性
                console.log(this.$refs.child.message)
                // 2.修改子组件的属性
                this.$refs.child.message = '我是修改后的消息'
                // 3.调用子组件的函数
                this.$refs.child.handleClick('我是来自父组件的参数')
                // 4.给子组件的函数传参数
            }
        },
        components: {
            Child: {
                template: `
                  <div ><h1>我是子组件</h1> <button @click="handleClick">点我看看</button><p>{{message}}</p></div>`,
                data() {
                    return {
                        message: '我是来自子组件的消息'
                    }
                },
                methods: {
                    handleClick(name){
                        console.log('我被父组件的事件调用了')
                        console.log(name)
                    }
                }
            }
        }

    })
</script>

【21】动态组件

动态组件,就是实现动态切换的组件

记住以下三点,就能掌握动态组件

① 利用 <component/> 元素的 is 属性

is 属性应该用 v-bind 修饰(可以简写为 :

is属性应该传入注册的组件名

<body>
<div id="app">
    <button @click="name='Girl1'">美女1</button>
    <button @click="name='Girl2'">美女2</button>
    <button @click="name='Girl3'">美女3</button>
<!--   component是一个万能组件,他的is属性就决定了它是哪一个组件 -->
    <component :is="name"></component>
</div>
</body>
<script>
    let vm = new Vue({
        el: '#app',
        data: {
            name:''
        }
    })
    Vue.component('Girl1', {
        template: `<div><h1>美女1</h1><img src="./img/1.jpg" alt=""></div>`
    })
    Vue.component('Girl2', {
        template: `<div><h1>美女2</h1><img src="./img/2.jpg" alt=""></div>`
    })
    Vue.component('Girl3', {
        template: `<div><h1>美女3</h1><img src="./img/3.jpg" alt=""></div>`
    })
</script>

【22】keep-alive

​ 在平常开发中,有部分组件没有必要多次初始化,这时,我们需要将组件进行持久化,使组件的状态维持不变,在下一次展示时,也不会进行重新初始化组件。

​ 也就是说,keepaliveVue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染 。也就是所谓的组件缓存

<keep-alive>是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。

<!--被keepalive包含的组件会被缓存-->
<keep-alive>
    <component><component />
</keep-alive>

【23】插槽

​ 正常情况下,如果已经写好了一个组件,并且想要往组件里面添加别的东西,就只能修改组件内容,拓展性很差

​ 所以就出现了插槽的概念,只需要在模板中可能需要更改的地方加上<slot></slot>,后续想要更新内容的时候直接在html里面加就行

posted @ 2024-05-04 19:29  HuangQiaoqi  阅读(50)  评论(0编辑  收藏  举报