vue学习笔记

VUE学习笔记

认识Vue

    
        

        
        

Hello,{{name.toUpperCase()}},{{address}}

1、Vue的模板语法

重点说明

如果在标签中使用属性绑定值,是字符串,动态绑定则是会去解析表达式。例如

//字符串 

//动态绑定是解析表达式 数字1

Vue模板语法有2大类:
            1.插值语法:
                    功能:用于解析标签体内容
                    写法:{{xxxx}},xxx会作为表达式去解析,且可以自动读取到data中的属性
            2.指令语法:
                    功能:用于解析标签(包括:标签属性、标签体内容、绑定事件.....)
                    举例:v-bind:href="xxxxxx" 或  简写为:
                    备注:Vue中有很多的指令,此处我们只是拿v-bind举个例子

    

插值语法

{{msg}}

{{msg.toUpperCase()}}

指令语法

动态绑定属性是字符串 百度一下

2、数据绑定及双向绑定原理

Vue中有2种数据绑定的方式:
                    1.单向绑定(v-bind):数据只能从data流向页面。
                    2.双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。
                        备注:
                                1.双向绑定一般都应用在表单类元素上(如:input、select等)
                                2.v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。
 

{{msg}}

单项数据绑定(v-bind):
双向数据绑定(v-model):
双向数据绑定(v-model):

4、MVVM模型

MVVM模型
                        1. M:模型(Model) :data中的数据
                        2. V:视图(View) :模板代码
                        3. VM:视图模型(ViewModel):Vue实例
            观察发现:
                        1.data中所有的属性,最后都出现在了vm身上。
                        2.vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。

5、数据代理

5.1 Object.defineProperty方法

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

备注:应当直接在 Object 构造器对象上调用此方法,而不是在任意一个 Object 类型的实例上调用。

语法:Object.defineProperty(obj, prop, descriptor)

obj:要定义属性的对象

prop:要定义或修改的属性的名称或 Symbol

descriptor:要定义或修改的属性描述符,简写就是默认的value值。

描述符默认值汇总

  • 拥有布尔值的键 configurableenumerable(调用Object.keys()获取不到) 和 writable 的默认值都是 false
  • 属性值和函数的键 valuegetset 字段的默认值为 undefined
        let _data = { msg: "小明" };
        let vm = {};
//通过对象方法给vm对象赋值属性msg
        Object.defineProperty(vm, "msg", {
            set(value) {
                // value值就是外部赋值的值
                console.log(value);
                // this指向vm对象
                console.log(this);
               // 调用一次进行赋值会无限递归
                this.msg = value;
            },
            get() {
                return _data.msg;
            }
        })

        vm.msg = "123"

        

5.2关于Vue中的数据代理:

1.什么是数据代理?
(1).配置对象data中的数据,会被收集到vm._data中,然后通过,Object.defineProperty让vm上拥有data中所有的属性。
(2).当访问vm的msg时,返回的是_data当中同名属性的值
(3).当修改vm的msg时,修改的是_data当中同名属性的值
2.为什么要数据代理?
为了更加方便的读取和修改_data中的数据,不做数据代理,就要:vm._data.xxx访问数据
3.扩展思考?—— 为什么要先收集在_data中,然后再代理出去呢?
更高效的监视数据(直接收集到vm上会导致监视效率太低)
4.基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上。
为每一个添加到vm上的属性,都指定一个getter/setter。
在getter/setter内部去操作(读/写)data中对应的属性。
vue底层,当data的数据变化,去更新dom,双向绑定dom元素的data变化也更新dom,本质是数据变化

验证data中的数据就是vm下的_data

 const data = {
      name: "尚硅谷",
      address: "宏福科技园",
    };

    const vm = new Vue({
      el: "#root",
      data
    });
//控制台上
vm._data === data //true

数据代理的原理

// 现在获取msg只能通过vm._data获取
// 如何实现通过vm.msg进行获取,将data下的键值挂载到vm下,每改变data中msg的值,vm.msg也能同步改变?

        // 模拟Vue实例下vm的_data参数对象,配置对象data中的数据,会被收集到vm._data中
        let _data = { msg: "小明" };
        // vm模拟Vue实例化的对象
        let vm = {};
        // 实现方式:为vm对象添加属性值
        Object.defineProperty(vm, "msg", {
            set(value) {
                // value值就是外部赋值的值
                console.log(value);
                // this指向vm对象
                console.log(this);
                //实现双向绑定 修改任意的一个值 两个都会发生改变
                _data.msg=value;
            },
            get() {
                return _data.msg;
            }
        })
        // 外部改变_data.msg的值
        _data.msg = "123"
        console.log(vm.msg);

6、事件处理

事件的基本使用:
                            1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
                            2.事件的回调需要配置在methods对象中,最终会在vm上;
                            3.methods中配置的函数,不要用箭头函数!否则this就不是vm了;
                            4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
                            5.@click="demo" 和 @click="demo($event)" 效果一致,但后者可以传参;

6.1事件的修饰符

Vue中的事件修饰符:

​ 1.prevent:阻止默认事件(常用);

​ 2.stop:阻止事件冒泡(常用);

​ 3.once:事件只触发一次(常用);

​ 4.capture:使用事件的捕获模式,默认是事件冒泡方式

​ 5.self:只有event.target是当前操作的元素时才触发事件;

​ 6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;

1.Vue中常用的按键别名:

​ 回车 => enter

​ 删除 => delete (捕获“删除”和“退格”键)

​ 退出 => esc

​ 空格 => space

​ 换行 => tab (特殊,必须配合keydown去使用)

​ 上 => up

​ 下 => down

​ 左 => left

​ 右 => right

​ 2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)

​ 3.系统修饰键(用法特殊):ctrl、alt、shift、meta

​ (1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。

​ (2).配合keydown使用:正常触发事件。

​ 4.也可以使用keyCode去指定具体的按键(不推荐)

​ 5.Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名

使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

不要把 .passive.prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你想阻止事件的默认行为

欢迎来到{{school}}学习







点我提示:信息3 (阻止默认行为)


//组合键

7、计算属性computed和数据监视watch

7.1 计算属性

计算属性:

​ 1.定义:要用的属性不存在,要通过已有属性计算得来,默认是getter读取

​ 2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。

​ 3.get函数什么时候执行?

​ (1).初次读取时会执行一次。

​ (2).当依赖的数据发生改变时会被再次调用。

​ 4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。

​ 5.备注:

​ 1.计算属性最终会出现在vm上,直接读取使用即可。

​ 2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

姓名案例:

  1. 使用插值语法实现

    姓:
    名:
    全名:{{firstName + '-' + lastName}}
  2. methods方法实现

            
    姓:
    名:
    全名:{{getFullName()}}
  3. computed方法实现

            
    姓:

    名:

    全名:{{fullName}}

    全名:

methods和computed对比

        

{{x}}

{{y()}}

{{z}}





展示x的值:

7.2 监视方法

  1. watch方法实现

    监视属性watch:
                1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作
                2.属性必须存在,才能进行监视!!
                3.监视的两种写法:
                    (1).new Vue时传入watch配置
                    (2).通过vm.$watch监视
        深度监视:
                            (1).Vue中的watch默认不监测对象内部值的改变(一层)。
                            (2).配置deep:true可以监测对象内部值改变(多层)。
                    备注:
                            (1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
                            (2).使用watch时根据数据的具体结构,决定是否采用深度监视。
    
    


全名:{{fullName}}
    computed和watch之间的区别:
        1.只要是computed能完成的功能,watch都可以完成
        2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
    备注:
        1.所有被Vue所调用(管理)的函数,都不要写箭头函数 ----- 例如:watch中的函数、computed中的函数
        2.所有不是被Vue所调(管理)的函数,都要写成箭头函数 --- 例如:定时器的回调、ajax的回调等等
        3.watch就是Vue给我提供的一个监测数据改变的手段,至于数据发生改变后,要做什么,得看具体的业务了逻辑。
            例如:
                需要新的值、旧的值作比较,决定接下来要干什么
                不要值,只要数据改变了,就要发请求等等

8、绑定样式

    绑定样式:
                    1. class样式
                                写法:class="xxx" xxx可以是字符串、对象、数组。
                                        字符串写法适用于:类名不确定,要动态获取。
                                        对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
                                        数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
                    2. style样式
                                :style="{fontSize: xxx}"其中xxx是动态值。
                                :style="[a,b]"其中a、b是样式对象。

{{title}}

{{title}}

{{title}}

{{title}}

{{title}}

354563

354563

9、条件渲染

条件渲染:
1.v-if
写法:
(1).v-if="表达式" 
(2).v-else-if="表达式"
(3).v-else="表达式"
适用于:切换频率较低的场景。
特点:不展示的DOM元素直接被移除。
注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。

2.v-show
写法:v-show="表达式"
适用于:切换频率较高的场景。
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。

    

今天天气很{{isHot ? '炎热':'凉爽'}}

建议:心境自然就会凉
建议:妈妈告诉你要穿秋裤了

建议:心境自然就会凉

建议:妈妈告诉你要穿秋裤了

10、列表渲染

10.1 基本列表

v-for指令:
                        1.用于展示列表数据
                        2.语法:v-for="(item, index) in xxx" :key="yyy"
                        3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)

    
  • {{p.name}}--{{p.sex}}--{{p.age}}
  1. {{value}}
  1. {{value}}---{{index}}
  1. {{value}}---{{index}}

使用template进行v-for遍历:template会不显示

[v-forv-if 一同使用]:

当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中

   

10.2 key的原理

面试题:react、vue中的key有什么作用?(key的内部原理)
                        
1. 虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 
随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

2.对比规则:
(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。

(2).旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。

3. 用index作为key可能会引发的问题:
1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。

2. 如果结构中还包含输入类的DOM:
会产生错误DOM更新 ==> 界面有问题。

4. 开发中如何选择key?:
1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,
使用index作为key是没有问题的。

如果input输入框不加key属性,input输入框会复用,出现混乱的现象

人员列表(遍历数组)

  • {{p.name}}-{{p.age}}

10.3 列表过滤


    
    
    

人员列表

  • {{p.name}}--{{p.sex}}--{{p.age}}岁

显示过滤排序后的结果

1、可以使用计算属性
2、使用方法v-for=‘item in set(data)’
  • {{ n }}
//数组中嵌套数组不适合使用计算属性 data: { sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]] }, methods: { even: function (numbers) { return numbers.filter(function (number) { return number % 2 === 0 }) } }

10.4 列表排序


    
  • {{p.name}}---{{p.sex}}---{{p.age}}

10.5 列表更新的问题

v-for 遍历数组或对象,VUE无法监测数组或对象中的值的变化,正常情况修改数组元素的值,vue不能动态的更新。原因是:复杂数据类型保存的是对象的引用,当改变对象的键或值,对象的引用并没有发生变化。
vue对于数组的方法作出一层封装,可以改变原数组的方法,vue是可以监测到变化,有push pop  shift unshift reverse splice sort
对于非变更的方法,如filter concat slice 返回新数组 将新的值赋给原数组即可
// 控制台上直接修改app.list[]元素,不会动态刷新
            // 解决方案
            // 1.调用splice方法,Vue进行包裹可直接动态刷新
            // 2.调用$forceUpdate()方法强制进行刷新
            // 3.Vue.set(app.list,indexOf,newValue)
            // 4.app.$set(app.list,indexOf,newValue)

    
    
    

人员列表

  • {{p.name}}--{{p.sex}}--{{p.age}}岁

10.6 模拟数据监测

10.7 Vue.set的使用

向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property (比如 this.myObject.newProperty = 'hi')

注意对象不能是 Vue 实例,或者 Vue 实例的根数据对象。
this.student.sex = '女' //直接使用不是响应式
//两种方式
Vue.set(this.student,'sex','男')
this.$set(this.student,'sex','男')

10.8 总结Vue数据监测

Vue监视数据的原理:
                1. vue会监视data中所有层次的数据。

                2. 如何监测对象中的数据?
                                通过setter实现监视,且要在new Vue时就传入要监测的数据。
                                    (1).对象中后追加的属性,Vue默认不做响应式处理
                                    (2).如需给后添加的属性做响应式,请使用如下API:
                                                    Vue.set(target,propertyName/index,value) 或 
                                                    vm.$set(target,propertyName/index,value)

                3. 如何监测数组中的数据?
                                    通过包裹数组更新元素的方法实现,本质就是做了两件事:
                                        (1).调用原生对应的方法对数组进行更新。
                                        (2).重新解析模板,进而更新页面。

                4.在Vue修改数组中的某个元素一定要用如下方法:
                            1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
                            2.Vue.set() 或 vm.$set()   (对象,数组的索引,添加索引的内容)
                        
                
                特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!

11、收集表单信息

收集表单数据:
                    若:,则v-model收集的是value值,用户输入的就是value值。
                    若:,则v-model收集的是value值,且要给标签配置value值。 不加name属性也可
                    若:
                            1.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
                            2.配置input的value属性:
                                    (1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
                                    (2)v-model的初始值是数组,那么收集的的就是value组成的数组
                    备注:v-model的三个修饰符:
                                    lazy:失去焦点再收集数据
                                    number:输入字符串转为有效的数字
                                    trim:输入首尾空格过滤

    
    
账号:

密码:

性别:男

爱好:抽烟 喝酒 开车

所属校区:

其他信息:

阅读并接受《用户协议》

12、过滤器

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

显示格式化后的时间

现在是:{{fmtTime}}

现在是:{{getFmtTime()}}

现在是:{{time | timeFormater}}

现在是:{{time | timeFormater('YYYY_MM_DD') | mySlice}}

尚硅谷

{{msg | mySlice}}

13、内置指令及自定义指令

13.1 内置指令

    常用内置指令
        v-text     :  更新元素的 innerText   类似于插值 
            1.作用:向其所在的节点中渲染文本内容。
            2.与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。
         v-html :  更新元素的 innerHTML  内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译
             1.作用:向指定节点中渲染包含html结构的内容。
             2.与插值语法的区别:
                (1).v-html会替换掉节点中所有的内容,{{xx}}则不会。
                 (2).v-html可以识别html结构。
             3.严重注意:v-html有安全性问题!!!!
                (1).在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
                (2).一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
         v-cloak :这个指令保持在元素上直到关联实例结束编译(没有值)
             1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
            2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
        v-once指令:
             1.v-once所在节点在初次动态渲染后,就视为静态内容了。
             2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
         v-pre指令:
            1.跳过其所在节点的编译过程。
            2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
         v-if     :  条件渲染(动态控制节点是否存在)
         v-else :  条件渲染(动态控制节点是否存在)
         v-else-if:
         v-show :  条件渲染 (动态控制display)
         v-for  :  遍历数组/对象
         v-on   :  绑定事件监听, 可简写为@   修饰符
         v-bind:xxx : 强制绑定解析表达式, 可简写为 :xxx  修饰符
         v-model: 双向数据绑定  修饰符 .lazy .number .trim
         v-slot(#) : 插槽名

        
    
    
        
        
        

{{name}}

13.2 自定义指令

    需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
    需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
    自定义指令总结:
    一、定义语法:
        (1).局部指令:                                                                                                    new Vue({directives:{指令名:配置对象} })  或  new Vue({    directives{指令名:回调函数}})                          (2).全局指令:
                Vue.directive(指令名,配置对象) 或   Vue.directive(指令名,回调函数)
        注意:配置对象使用函数的写法,默认是bind和update里面的内容
    二、配置对象中常用的3个回调:
        (1).bind:指令与元素成功绑定时调用。
        (2).inserted:指令所在元素被插入页面时调用。
        (3).update:指令所在模板结构被重新解析时调用。
        不用 (4)componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
        不用 (5)unbind:只调用一次,指令与元素解绑时调用。
    三、备注:
        1.指令定义时不加v-,但使用时要加v-;多个单词用v-big-number
        2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。指令名多个单词用双引号

{{name}}

当前的n值是:

放大10倍后的n值是:


15.2 注意点

    几个注意点:
        1.关于组件名:
            一个单词组成:
                第一种写法(首字母小写):school
                第二种写法(首字母大写):School
        多个单词组成:
            第一种写法(kebab-case命名):my-school
            第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
        备注:
            (1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
            (2).可以使用name配置项指定组件在开发者工具中呈现的名字。

        2.关于组件标签:
            第一种写法:
            第二种写法:
            备注:不用使用脚手架时,会导致后续组件不能渲染。

        3.一个简写方式:
            const school = Vue.extend(options) 可简写为:const school = options

15.3 组件的嵌套


        
        

15.3 VueComponent构造函数

关于VueComponent:
    1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend调用生成的。

    2.我们只需要写,Vue解析时会帮我们创建school组件的实例对象,
    即Vue帮我们执行的:new VueComponent(options)。

    3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!

    4.关于this指向:
        (1).组件配置中:
            data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
        (2).new Vue(options)配置中:
            data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。

    5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
        Vue的实例对象,以后简称vm。

15.4 一个重要的内置关系 vc和vm的原型

    1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
    2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

16、单文件组件

    非单文件组件
    通过Vue.extend去注册组件,在new Vue中的components配置,直接在html中使用
    不易复用,现在将功能模块拆分
    单文件组件
        vue文件 1.webpack解析  2.脚手架
        |-main.js  注册app组件 挂载app 使用template 注册app 配置template() 不用在html中写
        |-App.vue   app中引入components中组件 注册 school和student
        |-index.html 引入main.js 和 Vue
        |-components |-student 
                    有template script export default const student = Vue.extend({})  可简写为 export default{}
                    |-school
    

17、分析脚手架

    脚手架
    不使用render函数 在main.js中写

原先写法

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

脚手架写法 缺少模板解析器

只在main.js中写
//只引入了实时运行版的vue
//import Vue from 'vue'
//完整版的包含模板解析器 就可以运行
import Vue from 'vue/dist/vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  // render: h => h(App),
  components:{App},
  template:``
}).$mount('#app')

为什么:Vue = Vue核心(2/3) + 模板解析器(1/3) 所以用render进行渲染 打包后生成最终代码不需要模板解析器的部分

Vue 选项中的 render 函数若存在,则 Vue 构造函数不会从 template 选项或通过 el 选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。

//引入Vue
import Vue from 'vue'
//引入App组件,它是所有组件的父组件
import App from './App.vue'
//关闭vue的生产提示
Vue.config.productionTip = false

/* 
    关于不同版本的Vue:
    
        1.vue.js与vue.runtime.xxx.js的区别:
                (1).vue.js是完整版的Vue,包含:核心功能+模板解析器。
                (2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。

        2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用
            render函数接收到的createElement函数去指定具体内容。
*/

//创建Vue实例对象---vm
new Vue({
    el:'#app',
    //render函数完成了这个功能:将App组件放入容器中   返回的是虚拟dom
  render: h => h(App),
    // render:q=> q('h1','你好啊')

    // template:`

你好啊

`, // template:``, // components:{App}, })

18、常用方法

18.1 ref属性

ref在普通元素上就是真实的Dom节点
组件上就是组件的示例对象(vc)

18.2 props属性

prop接受的值实在data赋值之前

        //简单声明接收
        // props:['name','age','sex'] 

        //接收的同时对数据进行类型限制
        /* props:{
            name:String,
            age:Number,
            sex:String
        } */

        //接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
        props:{
            name:{
                type:String, //name的类型是字符串
                required:true, //name是必要的
            },
            age:{
                type:Number,
                default:99 //默认值
            },
            sex:{
                type:String,
                required:true
            }
        }

18.3 混入Mixin

混入的方式 :方法自身有用自身的 生命周期是都会执行,混入的钩子会提前调用
还可以自定义混入
  1. 功能:可以把多个组件共用的配置提取成一个混入对象
  2. 使用方式:

    第一步定义混合:

    {
        data(){....},
        methods:{....}
        ....
    }

    第二步使用混入:

    ​ 全局混入:Vue.mixin(xxx)
    ​ 局部混入:mixins:['xxx']

18.4 插件

  1. 功能:用于增强Vue
  2. 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。

通过 install 方法给 Vue 或 Vue 实例添加方法, 定义全局指令 混入 过滤器

  1. 定义插件:
对象.install = function (Vue, options) {
    // 1. 添加全局过滤器
    Vue.filter(....)

    // 2. 添加全局指令
    Vue.directive(....)

    // 3. 配置全局混入(合)
    Vue.mixin(....)

    // 4. 添加实例方法
    Vue.prototype.$myMethod = function () {...}
    Vue.prototype.$myProperty = xxxx
}
  1. 使用插件:Vue.use()
import Vue from 'vue'
import loadingComponent from '@/components/Loading/index.vue'
//使用extend创建 组件的vc构造函数
const LoadingConstructor = Vue.extend(loadingComponent)
//实例化vc 挂载在div中
const instance = new LoadingConstructor({
  el: document.createElement('div')
})
//在实例中挂载属性
instance.show = false // 默认隐藏
// 组件中使用props接收
const loading = {
  show(txt = '') { // 显示方法
    instance.show = true
    instance.text = txt || '拼命加载中'
    document.body.appendChild(instance.$el)
  },
  hide() { // 隐藏方法
    instance.show = false
  }
}

export default {
 //install方法 有一个Vue形参 
  install() {
    if (!Vue.$loading) {
      Vue.$loading = loading
    }
  //通过混入 在created中 将实例化$loading 挂载在this上
    Vue.mixin({
      created() {
        this.$loading = Vue.$loading
      }
    })
  }
}

18.5 nextTick

  1. 语法:this.$nextTick(回调函数)
  2. 作用:在下一次 DOM 更新结束后执行其指定的回调。
  3. 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。
//解析时机的问题  当this.isEdit数据变化,并没有立即更新dom 而是执行完focus  所以必须在dom更新后进行执行
if(todo.hasOwnProperty('isEdit')){
                    todo.isEdit = true
                }else{
                    // console.log('@')
                    this.$set(todo,'isEdit',true)
                }
                this.$nextTick(function(){
                    this.$refs.inputTitle.focus()
                })

19、事件总线

main.js
    new Vue({
      render: h => h(App),
      beforeCreate(){
        Vue.prototype.$bus = this
      }
    }).$mount('#app')
绑定 触发 销毁
this.$bus.$on('name',callback=>{})
this.$bus.$emit('name',params)
 this.$bus.$off()全部关闭(name)

发布订阅pubsub.js

//首先是先订阅消息hello, 定义触发的回调 第一个参数的回调的函数名,第二个是接受的数据
this.pubId = pubsub.subscribe('hello',(msgName,data)=>{
                console.log(this)
                // console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data)
})
//发送数据方,需要发布消息,触发回调
pubsub.publish('hello',666)
//取消订阅 是取消订阅号
pubsub.unsubscribe(this.pubId)

20、动画和过度

  1. 作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名。
  2. 图示:
  3. 写法:

    1. 准备好样式:

      • 元素进入的样式:

        1. v-enter:进入的起点
        2. v-enter-active:进入过程中
        3. v-enter-to:进入的终点
      • 元素离开的样式:

        1. v-leave:离开的起点
        2. v-leave-active:离开过程中
        3. v-leave-to:离开的终点
    2. 使用包裹要过度的元素,并配置name属性:

      
          

      你好啊!

    3. 备注:若有多个元素需要过度,则需要使用:,且每个元素都要指定key值。

            

你好啊!

尚硅谷!

使用animate动画库


            

你好啊!

尚硅谷!

21、vue脚手架配置代理

方法一

​ 在vue.config.js中添加如下配置:

//如果本地存在则不会转发
devServer:{
  proxy:"http://localhost:5000"
}

说明:

  1. 优点:配置简单,请求资源时直接发给前端(8080)即可。
  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

方法二

​ 编写vue.config.js配置具体代理规则:

module.exports = {
    devServer: {
      proxy: {
      '/api1': {// 匹配所有以 '/api1'开头的请求路径
        target: 'http://localhost:5000',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api1': ''}//将请求地址中的api1替换为空
      },
      '/api2': {// 匹配所有以 '/api2'开头的请求路径
        target: 'http://localhost:5001',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api2': ''}
      }
    }
  }
}
/*
   changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
   changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
   changeOrigin默认值为true
*/

说明:

  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
  2. 缺点:配置略微繁琐,请求资源时必须加前缀。

代码请求写法:

axios.get('http://localhost:8080/demo/cars')  
//vue.config.js
'/demo': {
        target: 'http://localhost:5001',
        pathRewrite:{'^/demo':''},
        // ws: true, //用于支持websocket
        // changeOrigin: true //用于控制请求头中的host值  true:host值不是实际的
}
//请求本地服务器,会转换撑localhost:5001/cars

22、插槽

  1. 作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件
  2. 分类:默认插槽、具名插槽、作用域插槽
  3. 使用方式:

    1. 默认插槽:

      父组件中:
              
                 
      html结构1
      子组件中:
    2. 具名插槽:

      父组件中:
              
                  
      
                  
              
      子组件中:
              
    3. 作用域插槽:

      1. 理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)
      2. 具体编码:

        在slot上绑定属性,可以在父组件中使用子组件的数据 ,接受方式:

        scope=“”

        slot-scope=""

        可以结构赋值

        v-slot:default=""

        default=""

        父组件中:
                
                    
                
        
                
                    
                
        子组件中:
                
                
                

23、Vuex

1.概念

​ 在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。

2.何时使用?

​ 多个组件需要共享数据时

3.搭建vuex环境

  1. 创建文件:src/store/index.js

    //引入Vue核心库
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //应用Vuex插件
    Vue.use(Vuex)
    
    //准备actions对象——响应组件中用户的动作
    const actions = {}
    //准备mutations对象——修改state中的数据
    const mutations = {}
    //准备state对象——保存具体的数据
    const state = {}
    
    //创建并暴露store
    export default new Vuex.Store({
        actions,
        mutations,
        state
    })
  2. main.js中创建vm时传入store配置项

    ......
    //引入store
    import store from './store'
    ......
    
    //创建vm
    new Vue({
        el:'#app',
        render: h => h(App),
        store
    })

4.基本使用

  1. 初始化数据、配置actions、配置mutations,操作文件store.js

    //引入Vue核心库
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //引用Vuex
    Vue.use(Vuex)
    
    const actions = {
        //响应组件中加的动作
        jia(context,value){
            // console.log('actions中的jia被调用了',miniStore,value)
            context.commit('JIA',value)
        },
    }
    
    const mutations = {
        //执行加
        JIA(state,value){
            // console.log('mutations中的JIA被调用了',state,value)
            state.sum += value
        }
    }
    
    //初始化数据
    const state = {
       sum:0
    }
    
    //创建并暴露store
    export default new Vuex.Store({
        actions,
        mutations,
        state,
    })
  2. 组件中读取vuex中的数据:$store.state.sum
  3. 组件中修改vuex中的数据:$store.dispatch('action中的方法名',数据)$store.commit('mutations中的方法名',数据)

    备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit

5.getters的使用

  1. 概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。
  2. store.js中追加getters配置

    ......
    
    const getters = {
        bigSum(state){
            return state.sum * 10
        }
    }
    
    //创建并暴露store
    export default new Vuex.Store({
        ......
        getters
    })
  3. 组件中读取数据:$store.getters.bigSum

6.四个map方法的使用

  1. mapState方法:用于帮助我们映射state中的数据为计算属性

    computed: {
        //借助mapState生成计算属性:sum、school、subject(对象写法)
         ...mapState({sum:'sum',school:'school',subject:'subject'}),
             
        //借助mapState生成计算属性:sum、school、subject(数组写法)
        ...mapState(['sum','school','subject']),
    },
  2. mapGetters方法:用于帮助我们映射getters中的数据为计算属性

    computed: {
        //借助mapGetters生成计算属性:bigSum(对象写法)
        ...mapGetters({bigSum:'bigSum'}),
    
        //借助mapGetters生成计算属性:bigSum(数组写法)
        ...mapGetters(['bigSum'])
    },
  3. mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数

    methods:{
        //靠mapActions生成:incrementOdd、incrementWait(对象形式)
        ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
        //靠mapActions生成:incrementOdd、incrementWait(数组形式)
        ...mapActions(['jiaOdd','jiaWait'])
    }
  4. mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数,传参写在事件后@click=xxx(data)

    methods:{
        //靠mapActions生成:increment、decrement(对象形式)
        ...mapMutations({increment:'JIA',decrement:'JIAN'}),
        
        //靠mapMutations生成:JIA、JIAN(对象形式)
        ...mapMutations(['JIA','JIAN']),
    }
备注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。

7.模块化+命名空间

  1. 目的:让代码更好维护,让多种数据分类更加明确。
  2. 修改store.js

    const countAbout = {
      namespaced:true,//开启命名空间
      state:{x:1},
      mutations: { ... },
      actions: { ... },
      getters: {
        bigSum(state){
           return state.sum * 10
        }
      }
    }
    
    const personAbout = {
      namespaced:true,//开启命名空间
      state:{ ... },
      mutations: { ... },
      actions: { ... }
    }
    
    const store = new Vuex.Store({
      modules: {
        countAbout,
        personAbout
      }
    })
  3. 开启命名空间后,组件中读取state数据:

    //方式一:自己直接读取
    this.$store.state.personAbout.list
    //方式二:借助mapState读取:
    ...mapState('countAbout',['sum','school','subject']),
    //对象写法
    ...mapState('countAbout',{sum:'sum'),
  4. 开启命名空间后,组件中读取getters数据:

    //方式一:自己直接读取
    this.$store.getters['personAbout/firstPersonName']
    //方式二:借助mapGetters读取:
    ...mapGetters('countAbout',['bigSum'])
    //对象写法
  5. 开启命名空间后,组件中调用dispatch

    //方式一:自己直接dispatch
    this.$store.dispatch('personAbout/addPersonWang',person)
    //方式二:借助mapActions:
    ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    ...mapActions('user',['addCash'])
  6. 开启命名空间后,组件中调用commit

    //方式一:自己直接commit
    this.$store.commit('personAbout/ADD_PERSON',person)
    //方式二:借助mapMutations:
    ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
    ...mapMutations('user',['addCash'])

    ## 24、路由

  7. 理解: 一个路由(route)就是一组映射关系(key - value),多个路由需要路由器(router)进行管理。
  8. 前端路由:key是路径,value是组件。

1.基本使用

  1. 安装vue-router,命令:npm i vue-router
  2. 应用插件:Vue.use(VueRouter)
  3. 编写router配置项:

    //引入VueRouter
    import VueRouter from 'vue-router'
    //引入Luyou 组件
    import About from '../components/About'
    import Home from '../components/Home'
    
    //创建router实例对象,去管理一组一组的路由规则
    const router = new VueRouter({
        routes:[
            {
                path:'/about',
                component:About
            },
            {
                path:'/home',
                component:Home
            }
        ]
    })
    
    //暴露router
    export default router
  4. 实现切换(active-class可配置高亮样式)

    About
  5. 指定展示位置

2.几个注意点

  1. 路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹。
  2. 通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。
  3. 每个组件都有自己的$route属性,里面存储着自己的路由信息。
  4. 整个应用只有一个router,可以通过组件的$router属性获取到。

3.多级路由(多级路由)

  1. 配置路由规则,使用children配置项:

    routes:[
        {
            path:'/about',
            component:About,
        },
        {
            path:'/home',
            component:Home,
            children:[ //通过children配置子级路由
                {
                    path:'news', //此处一定不要写:/news
                    component:News
                },
                {
                    path:'message',//此处一定不要写:/message
                    component:Message
                }
            ]
        }
    ]
  2. 跳转(要写完整路径):

    News

4.路由的query参数

  1. 传递参数

    
    跳转
                    
    
    跳转
  2. 接收参数:

    $route.query.id
    $route.query.title

5.命名路由

  1. 作用:可以简化路由的跳转。
  2. 如何使用

    1. 给路由命名:

      {
          path:'/demo',
          component:Demo,
          children:[
              {
                  path:'test',
                  component:Test,
                  children:[
                      {
                            name:'hello' //给路由命名
                          path:'welcome',
                          component:Hello,
                      }
                  ]
              }
          ]
      }
    2. 简化跳转:

      
      跳转
      
      
      跳转
      
      
      跳转

6.路由的params参数

  1. 配置路由,声明接收params参数

    {
        path:'/home',
        component:Home,
        children:[
            {
                path:'news',
                component:News
            },
            {
                component:Message,
                children:[
                    {
                        name:'xiangqing',
                        path:'detail/:id/:title', //使用占位符声明接收params参数
                        component:Detail
                    }
                ]
            }
        ]
    }
  2. 传递参数

    
    跳转
                    
    
    跳转
    特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!
  3. 接收参数:

    $route.params.id
    $route.params.title

7.路由的props配置*

​ 作用:让路由组件更方便的收到参数

{
    name:'xiangqing',
    path:'detail/:id',
    component:Detail,

    //第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
    // props:{a:900} 不用props接受会放在$attrs中

    //第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
    // props:true
    
    //第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
    props(route){
        return {
            id:route.query.id,
            title:route.query.title
        }
    }
}

8.的replace属性

  1. 作用:控制路由跳转时操作浏览器历史记录的模式
  2. 浏览器的历史记录有两种写入方式:分别为pushreplacepush是追加历史记录,replace是替换当前记录。路由跳转时候默认为push
  3. 如何开启replace模式:News

9.编程式路由导航

  1. 作用:不借助 实现路由跳转,让路由跳转更加灵活
  2. 具体编码:

    //$router的两个API
    this.$router.push({
        name:'xiangqing',
            params:{
                id:xxx,
                title:xxx
            }
    })
    
    this.$router.replace({
        name:'xiangqing',
            params:{
                id:xxx,
                title:xxx
            }
    })
    this.$router.forward() //前进
    this.$router.back() //后退
    this.$router.go() //可前进也可后退

10.缓存路由组件

  1. 作用:让不展示的路由组件保持挂载,不被销毁。
  2. 具体编码:

     
        
    

11.两个新的生命周期钩子

  1. 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。
  2. 具体名字:

    1. activated路由组件被激活时触发。
    2. deactivated路由组件失活时触发。

12.路由守卫

  1. 作用:对路由进行权限控制
  2. 分类:全局守卫、独享守卫、组件内守卫
  3. 全局守卫:

    //全局前置守卫:初始化时执行、每次路由切换前执行
    router.beforeEach((to,from,next)=>{
        console.log('beforeEach',to,from)
        if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
            if(localStorage.getItem('school') === 'atguigu'){ //权限控制的具体规则
                next() //放行
            }else{
                alert('暂无权限查看')
                // next({name:'guanyu'})
            }
        }else{
            next() //放行
        }
    })
    
    //全局后置守卫:初始化时执行、每次路由切换后执行
    router.afterEach((to,from)=>{
        console.log('afterEach',to,from)
        if(to.meta.title){ 
            document.title = to.meta.title //修改网页的title
        }else{
            document.title = 'vue_test'
        }
    })
  4. 独享守卫:

    beforeEnter(to,from,next){
        console.log('beforeEnter',to,from)
        if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
            if(localStorage.getItem('school') === 'atguigu'){
                next()
            }else{
                alert('暂无权限查看')
                // next({name:'guanyu'})
            }
        }else{
            next()
        }
    }
  5. 组件内守卫:

    //进入守卫:通过路由规则,进入该组件时被调用
    beforeRouteEnter (to, from, next) {
    },
    //离开守卫:通过路由规则,离开该组件时被调用
    beforeRouteLeave (to, from, next) {
    }

13.路由器的两种工作模式

  1. 对于一个url来说,什么是hash值?—— #及其后面的内容就是hash值。
  2. hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。
  3. hash模式:

    1. 地址中永远带着#号,不美观 。
    2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
    3. 兼容性较好。
  4. history模式:

    1. 地址干净,美观 。
    2. 兼容性和hash模式相比略差。
    3. 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。
index.html :html的入口文件
    引入css文件
    引入index.js   此时的src指向实例化Vue的js文件
    
css:
    style.css
js:
index.js
定义实例化的Vue  使用render模板去替换el挂载的DOM节点 
导入root文件,指向components中的root
render:(h){return h(root)}
    
components:
    root.js:定义render的返回值
    先导入页面需要的组件 和数据(如果需要则要导入事件总线)
    {
        template:`
        
//如果css中定义了app的样式,id=app需要加上
`, components:{ "todo-list":todolist, "done-list":donelist } } todolist.js donelist.js 先导入事件总线中需要的数据 定义组件的功能:获取数据使用computed计算属性 定义的方法 需要去触发总线中的方法 eventBus.$emit("事件总线中的方法",传入的参数) store store.js 先定义需要的数据,在eventBus上注册子组件需要的方法 this.$on("事件总线中的方法",this.eventBus中的方法)

Jenkins安装

nginx配置

yum install gcc-c++
yum install -y pcre pcre-devel
yum install -y zlib zlib-devel
yum install -y openssl openssl-devel
wget http://nginx.org/download/ngi...
tar zxvf nginx-1.16.1.tar.gz
先进入解压文件夹 ./configure && make && make install
whereis nginx 查看nginx安装路径
在usr/local/nginx/html下
启动
[root@localhost ~]# /usr/local/nginx/sbin/nginx
停止/重启
[root@localhost ~]# /usr/local/nginx/sbin/nginx -s stop(quit、reload)
命令帮助
[root@localhost ~]# /usr/local/nginx/sbin/nginx -h
验证配置文件
[root@localhost ~]# /usr/local/nginx/sbin/nginx -t
配置文件
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf

安装yarn

使用 yum 安装 Yarn
Yarn 官方提供的有 Yarn RPM 软件包,在添加 yum 源配置之后可使用 yum 安装:

添加 yum 源配置

curl -sL https://dl.yarnpkg.com/rpm/ya... | sudo tee /etc/yum.repos.d/yarn.repo

使用 yum 安装

sudo yum -y install yarn

查看安装的 Yarn 版本:

yarn -v
Jenkins安装

jekins+gitee+nginx
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat...
sudo rpm --import https://pkg.jenkins.io/redhat...
sudo yum upgrade
sudo yum install epel-release java-11-openjdk-devel
sudo yum install jenkins
sudo systemctl daemon-reload
sudo systemctl start jenkins 启动
查看状态sudo systemctl status jenkins
修改编辑权限 vim /etc/sysconfig/jenkins
service jenkins restart重启

这时访问jenkins有不可以,要开放阿里云8080端口
1.登录成功
为了确保管理员安全地安装 Jenkins,密码已写入到日志中(不知道在哪里?)该文件在服务器上:
/var/lib/jenkins/secrets/initialAdminPassword
请从本地复制密码并粘贴到下面。
d65c81a6952341dfac53d9efaf61e0cc
2.按照默认配置安装插件
3.创建一个管理员账户,完成配置后,就可以登录 Jenkins 了
4.安装插件
  下面来安装nodejs插件

gitee令牌2e724699896926f21b301598d10d91d7

gitee实验jenkins教程

安装rz :yum install -y lrzsz

gcc 版本过低

4.安装gcc

yum install gcc -y #默认安装旧版本4.85

yum -y install centos-release-scl

yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils #安装新版本

切换为新版本

scl enable devtoolset-9 bash #临时切换,退出服务器恢复

echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile #永久切换

jenkins

需要配置webhook gitee需要配置 参考jenkins+gitee实现前端项目自动化部署 - 简书 (jianshu.com)

安装nodejs

  • 第一步,到官网查看最新源码,并下载
cd /home/downloads
wget https://nodejs.org/dist/v10.16.0/node-v10.16.0.tar.gz

下载编译好的node Linux

ln -s /usr/local/src/node-v16.5.0-linux-x64/bin/node /usr/local/bin/node

ln -s /usr/local/src/node-v16.5.0-linux-x64/bin/npm /usr/local/bin/npm

课堂知识内容回顾

1、使用template会将el挂载的节点内容替换. 注意template模板的使用

 

    

组件间的通信方式有3类:

第一类:父子组件通信

第二类:隔代组件通信

第三类:兄弟组件通信

(1) props/$emit 适用父子组件通信

父-->子传值 props

 
 

(5)EventBus($emit/$on)适用于父子、隔代、兄弟组件通信

    

{{msg}}

(6)Vuex 适用于父子、隔代、兄弟组件通信

组件的插槽slot

你好
你好

编译作用域

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

 
{{msg}}

后背内容 默认的内容

 

具名插槽

    

作用域插槽

    
//补充:当被提供的内容只有默认插槽时 组件的标签才可以被当作插槽的模板来使用 {{ slotProps.user.firstName }} //可以简写为 {{ slotProps.user.firstName }}
//结构赋值
 
            
//这里还是只能写user
             
                    
{{user}}

要改变插槽的值

//第一种传入的是对象  子组件中使用user.lastName
 
                
            
                    
{{user}}
{{user}}
//第二种方式 在组件中直接传入
{{user}}

动态组件 keep-alive

使用keep-alive时,组件将缓存

    
内联模板inline-template

{{msg}}

{{msg}}



x-template 

    

{{msg}}


混入mixin

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

{{msg}}

----------------


过滤器 filter

过滤器可以用在两个地方:**双花括号插值和 `v-bind` 表达式** (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示。

当全局过滤器和局部过滤器重名时,会采用局部过滤器。

全局过滤器:在创建 Vue 实例之前全局定义过滤器

// 全局过滤器

     Vue.filter("replaceMinus",function(value){
         return value.replace(/-/g," ");
     })

局部过滤器

var app = new Vue({

        el:"#app",
        data:{
            msg:'hello-world-haha-heihei'
        },
        filters:{
            "replaceMinus":function(value){
                return value.replace(/-/g," ");
            },
            "upperCase":function(value){
                return value.toUpperCase();
            }
        }
    })

 案例:

{{msg | replaceMinus}}

{{msg | upperCase}}



自定义指令directive

    自定义指令
    

自定义指令的钩子函数

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 。

componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

unbind:只调用一次,指令与元素解绑时调用。


钩子函数参数

指令钩子函数会被传入以下参数:

el:指令所绑定的元素,可以用来直接操作 DOM。
binding:一个对象,包含以下 property:

    name:指令名,不包括 v- 前缀。
    value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
    oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
    expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
    arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
    modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。

vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

注意:除了 el 之外,其它参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的 dataset 来进行。

    


### [动态指令参数](https://cn.vuejs.org/v2/guide/custom-directive.html#动态指令参数)

创建一个自定义指令,用来通过固定布局将元素固定在页面上。我们可以像这样创建一个通过指令值来更新竖直位置像素值的自定义指令:

这会把该元素固定在距离页面顶部 200 像素的位置。但如果场景是我们需要把元素固定在左侧而不是顶部又该怎么办呢?这时使用动态参数就可以非常方便地根据每个组件实例来进行更新。


Scroll down inside this section ↓


I am pinned onto the page at 200px to the left.



//通过
Vue.directive('pin', {
bind: function (el, binding, vnode) {

el.style.position = 'fixed'
var s = (binding.arg == 'left' ? 'left' : 'top')
el.style[s] = binding.value + 'px'

}
})

new Vue({
el: '#dynamicexample',
data: function () {

return {
  direction: 'left'
}

}
})

渲染函数render

`createElement` 到底会返回什么呢?其实不是一个*实际的* DOM 元素。它更准确的名字可能是 `createNodeDescription`,因为它所包含的信息会告诉 Vue 页面上需要渲染什么样的节点,包括及其子节点的描述信息。我们把这样的节点描述为“虚拟节点 (virtual node)”,也常简写它为“**VNode**”。“虚拟 DOM”是我们对由 Vue 组件树建立起来的整个 VNode 树的称呼

   
Hello-world!

## vue-router

index.html

链接到vue的router中
About
Home
展示跳转显示的模板位置

js/index.js

导入router
定义router:router

router/index.js

导入组件About 组件中导入的地址是相对自身文件的
new VueRouter({
    routes:[
        {
            path:'/about',
            component:About
        }
    ]
})

你可能感兴趣的:(程序员)