Vue-(4)

内容概览

  • 计算属性(computed)
  • 监听属性(watch)
  • 组件介绍与定义
  • 父子通信
  • ref属性
  • 动态组件
  • 插槽
  • vue-cli

计算属性(computed)

如果在插值语法中直接填入函数:{{func()}},那么每次页面刷新,函数都会重新执行
计算属性将函数当做属性来使用,缓存了数据;当数据发生改变才执行函数更新数据

<!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="name1">--{{handleUpper()}}
    <hr>
    <input type="text" v-model="name2">--{{upper}}
</div>
</body>
<script>
    let vm = new Vue({
        el: "#app",
        data: {
            name1: '',
            name2: '',
        },
        methods: {
            handleUpper() {
                // 页面每次刷新都会变化
                console.log('函数执行')
                return this.name1.slice(0, 1).toUpperCase() + this.name1.slice(1).toLowerCase()
            }
        },
        computed: {
            upper() {
                // 只有计算属性中使用的变量发生变化,函数参会重新运算
                console.log('计算属性执行')
                return this.name2.slice(0, 1).toUpperCase() + this.name2.slice(1).toLowerCase()
            }
        }
    })
</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">
    <h1>过滤案例</h1>
    <p><input type="text" v-model="search" placeholder="请输入要搜索的内容"></p>
    <ul>
        <li v-for="item in newdataList">{{item}}</li>
    </ul>
</div>
</body>
<script>
    let vm = new Vue({
        el: "#app",
        data: {
            search: '',
            dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf', 'd', 'dddd',],
        },
        computed: {
            newdataList() {
                return this.dataList.filter(item => item.indexOf(this.search) >= 0)
            }
        }
    })
</script>
</html>

监听属性(watch)

监听一个属性的变化,只要他发生变化就触发一个函数的执行
函数需要接收一个参数,参数是修改后的值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <span>
        <button @click="type='语文'">语文</button>
        <button @click="type='数学'">数学</button>
        <button @click="type='英语'">英语</button>
    </span>
    <hr>
    {{type}}
</div>
</body>
<script>
    let vm = new Vue({
        el: "#app",
        data: {
            type: ''
        },
        watch: {
            type(item) {
                console.log('监听属性执行了,修改值为:', item)
            }
        }
    })
</script>
</html>

组件介绍和定义

扩展HTML元素,封装需要重复使用的代码
例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html
组件把js,css,html放到一起,有逻辑,有样式,有html

  • 定义组件:
    1. 全局组件:全局都可以使用,可以用在任意其他组件中
    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">
    <h1>全局组件</h1>
    <child></child>
    <hr>
    <h1>局部组件</h1>
    <child1></child1>
</div>
</body>
<script>
    // 定义一个全局组件(必须在一个标签中),组件有自己的数据,方法,生命周期
    let obj = {
        template: `
          <div>
          {{ title }}
          <button @click="handleClick">点击</button>
          </div>`,
        data() {
            return {
                title: '全局组件child'
            }
        },
        methods: {
            handleClick() {
                alert('xxx')
            }
        }
    }
    Vue.component('child', obj)  // obj可以写在外边也可以写在括号内


    // 定义局部组件
    let child1 = {
        template: `
          <div>
          {{ msg }}
          <child2></child2>
          </div>`,
        data() {
            return {
                msg: 'vm中的组件'
            }
        },
        components: {
            child2: {
                template: `
                  <div>
                  {{ msg }}
                  </div>`,
                data() {
                    return {
                        msg: 'vm的组件child1中的组件'
                    }
                }
            }
        }
    }
    let vm = new Vue({
        el: "#app",
        data: {
            type: ''
        },
        components: {
            child1  // 'child1':child1  --简化-->  child1:child1  --简化-->  child
            // es6的对象写法
        }

    })
</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">
    <h1>自定义属性实现父传子</h1>
    {{msg}}
    <child :message="msg"></child>
</div>
</body>
<script>
    let child = {
        template: `
          <div>
          <h2>vm中的child组件</h2>
          <!--使用插值语法插入接收的变量名-->
          {{ message }}
          <!--需要注意自定义属性的名字-->
          </div>`,
        // props: ['message']  // 接收自定义变量,可以传入多个变量
        props: {
            message: String,  // props写成对象,可以指定数据类型
        }
    }
    let vm = new Vue({
        el: "#app",
        data: {
            msg: 'vm中的msg变量'
        },
        components: {
            child
        }
    })
</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">
    <h1>自定义事件实现子传父</h1>
    父组件中的msg值=={{msg}}
    <hr>
    <child @myevent="handleEvent"></child>
    <hr>
</div>
</body>
<script>
    let child = {
        template: `
          <div>
          <h2>vm中的child组件</h2>
          name<input type="text" v-model="name"> ----{{ name }}
          <br>
          <button @click="handleSend">点击将name传给父组件</button>
          </div>`,
        data() {
            return {
                name: ''
            }
        },
        methods: {
            handleSend() {
                // 在这里触发父组件中的自定义事件执行,并将参数传入
                this.$emit('myevent', this.name)  // 第一个值为自定义事件的名字,然后传入参数
            }
        }

    }
    let vm = new Vue({
        el: "#app",
        data: {
            msg: 'vm中的msg变量'
        },
        components: {
            child
        },
        methods: {
            handleEvent(name) {
                this.msg = name
            }
        }
    })
</script>
</html>

ref属性

# ref属性,vue定义的
	-可以放在普通标签上,通过this.$refs.自定义的名字取到的是 原生的dom对象
		-使用原生dom操作(不推荐)
    -可以放在组件上:通过this.$refs.自定义的名字取到的是 vc对象(组件对象)-可以之间使用组件对象上的方法和属性---》子的数据给了父亲
        -父组件有个方法执行,需要传参数,传入子组件的数据---》子的数据给了父亲
        -拿到子对象之间使用父中的数据修改----》父传子
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>ref属性放在普通标签上</h1>
    <input type="text" ref="myinput" v-model="name"> ----> {{name}}
    <button @click="handlePrint">点击</button>
    <hr>
    <h1>ref属性放在组件上</h1>
    <child ref="mychild"></child>

</div>
</body>
<script>
    let child = {
        template: `
          <div>
          {{ name }}
          </div>`,
        data() {
            return {
                name: 'child的name'
            }
        },
        methods: {
            handleAlert(name) {
                alert(name)
            }
        }

    }
    let vm = new Vue({
        el: "#app",
        data: {
            name: ''
        },
        components: {
            child
        },
        methods: {
            handlePrint() {
                // console.log(this.$refs.myinput)  // 原生dom对象
                // this.$refs.myinput.value='xxx'  // 通过dom修改input框的value值
                console.log(this.$refs)
                console.log(this.$refs.mychild)  // Vc对象
                // this.$refs.mychild.name = 'xxx'  // 修改组件中的变量
                // this.name = this.$refs.mychild.name  // 获取组件中的值
                this.$refs.mychild.handleAlert(this.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="app">
    <div>
        <span @click="type='home'">首页</span>
        <span @click="type='goods'">商品</span>
        <span @click="type='order'">订单</span>
    </div>
    <div>
    
        <component :is="type"></component>
    </div>
</div>
</body>
<script>
    // 定义第三个全局组件
    Vue.component('home', {
        template: `
          <div>
          <h1>首页</h1>
          </div>`,
    })
    Vue.component('goods', {
        template: `
          <div>
          <h1>商品</h1>
          </div>`,
    })
    Vue.component('order', {
        template: `
          <div>
          <h1>订单</h1>
          </div>`,
    })
    let vm = new Vue({
        el: "#app",
        data: {
            type: 'home'
        },
    })
</script>
</html>
keep-alive
<!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>
        <span @click="type='home'">首页</span>
        <span @click="type='goods'">商品</span>
        <span @click="type='order'">订单</span>
    </div>
    <div>
        <keep-alive>  <!--使搜索框中的数据缓存,切换其他组件后切换回来数据任然存在-->
            <component :is="type"></component>
        </keep-alive>
    </div>
</div>
</body>
<script>
    // 定义第三个全局组件
    Vue.component('home', {
        template: `
          <div>
          <h1>首页</h1>
          </div>`,
    })
    Vue.component('goods', {
        template: `
          <div>
          <h1>商品</h1>
          <input type="text" placeholder="请输入要搜索的商品"> <button>搜索</button>
          </div>`,
    })
    Vue.component('order', {
        template: `
          <div>
          <h1>订单</h1>
          </div>`,
    })
    let vm = new Vue({
        el: "#app",
        data: {
            type: '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="app">
    <h1>插槽的使用</h1>
    <home>
        <img src="https://img0.baidu.com/it/u=3947432154,2892596664&fm=253&fmt=auto&app=138&f=JPEG?w=658&h=404"
             alt="">
    </home>
    <goods>
        <div slot="bottom">底部</div>
        <div v-slot=top>顶部</div>  <!--推荐写法-->
    </goods>
</div>
</body>
<script>
    Vue.component('home', {
        template: `
          <div>
          <h1>首页</h1>
          <slot></slot>
          </div>`,  // 在slot的位置上插入组件标签中的内容
    })
    Vue.component('goods', {
        template: `
          <div>
          <slot name="top"></slot>
          <slot name="bottom"></slot>
          <h1>商品</h1>
          <input type="text" placeholder="请输入要搜索的商品"> <button>搜索</button>
          <slot name="bottom"></slot>
          </div>`,  // 有多个标签也可以使用name来选择位置插入
    })


    let vm = new Vue({
        el: "#app",
    })
</script>
</html>

vue-cli

# vue的脚手架:快速帮我们创建出vue的项目
# vue2 和 vue3 
	-vue-cli可以创建vue2和vue3的项目    webpack构建工具
    -Vite:新一代构建工具
    -vue3上,推荐使用ts写  js
    
    
# 先安装nodejs 后端语言---》语法就是js的语法
	-js运行在浏览器中,浏览器中有它的解释器环境
    -不能运行在操作系统之上,把chrom浏览器的v8引擎,把它安装在操作系统上
    	-c语言写了内置库:文件操作,网络操作
        
    -官网:https://nodejs.org/zh-cn/download/ ,下载,一路下一步
    -安装完会释放两个命令(在环境变量中,任意路径都能敲这俩命令)
    	-node      python3
        -npm        pip
        -cnpm      等同于pip ,只是下模块,直接取淘宝镜像站下载,速度快
    
 # npm 下载时候,去国外,速度慢,使用国内镜像
	-淘宝做了一个cnpm可执行文件,用来替换npm,以后所有使用npm的地方都换成cnpm即可
    -安装cnpm 
    npm install -g cnpm --registry=https://registry.npm.taobao.org
  
        
 # 安装vue-cli ,通过脚手架创建vue项目 (django--->django项目--->django-admin)
 	cnpm install -g @vue/cli
    -只要装成功,又会多出一个可执行文件  vue  
    
 # 创建vue项目
	vue create myfirstvue
    
    
    
 # ide的选择(vscode,webstorm:jetbrains公司的,跟pycharm一家的,使用习惯一样)
	-选择使用pycharm+vue插件 开发vue项目
    -使用pycharm打开vue项目
    
 # 运行vue项目
	-方式一:在命令行中敲:npm run serve
    -方式二:在pycharm中点击绿色箭头运行
    
    
    
 #cnpm install axios

""" cnpm : 无法加载文件 XXX ,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https
:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
解决方法:管理员模式打开PowerShell,输入set-executionpolicy remotesigned
选择y
"""

练习

# 获取所有图书接口drf写,处理跨域(响应头)
# 前端vue项目首页,只要加载好就获取所有图书v-for循环显示在页面上
  • django:
"""urls"""
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import SimpleRouter
from app01 import views

router = SimpleRouter()
router.register('books', views.BookView, 'books')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls))
]

"""models"""
from django.db import models

class Books(models.Model):
    title = models.CharField(max_length=32)
    price = models.CharField(max_length=32)

"""serializer"""
from rest_framework import serializers
from app01.models import Books

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Books
        fields = '__all__'

"""views"""
from rest_framework.viewsets import ReadOnlyModelViewSet
from app01.models import Books
from app01.serializers import BookSerializer


class BookView(ReadOnlyModelViewSet):
    queryset = Books.objects.all()
    serializer_class = BookSerializer

    def list(self, request, *args, **kwargs):
        response = super().list(request, *args, **kwargs)
        response['Access-Control-Allow-Origin'] = '*'
        return response
  • vue
<template>
  <div class="home">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
    <div class="container-fluid">
      <div class="row">
        <div class="col-md-6 col-md-offset-3">
          <table class="table table-hover">
            <thead>
            <tr>
              <th class="text-center">id</th>
              <th class="text-center">书名</th>
              <th class="text-center">价格</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="book in booksDetail">
              <th scope="row" class="text-center">{{ book.id }}</th>
              <td>{{ book.title }}</td>
              <td>{{ book.price }}</td>
            </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>

  </div>
</template>

<script>
import axios from 'axios'

export default {
  name: 'HomeView',
  data() {
    return {
      booksDetail: []
    }
  },
  created() {
    axios.get('http://127.0.0.1:8000/books/').then(res => {
      this.booksDetail = res.data
      // console.log(res.data)
    })
  }
}
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值