0
点赞
收藏
分享

微信扫一扫

Vue之webpack(一)

彭维盛 2022-02-07 阅读 75

Vue之webpack

1.webpack概念

前端规范:模块化、组件化、自动化、规范化

为了实现前端项目工程化,webpack诞生,webpack是一种前端工程化的解决方案。

npm install webpack@5.42.1 webpack-cli@4.7.2 -D

webpack的手写过程就先看一遍,后面深入研究

2.Vue

Vue是一套用于构建用户界面的前端框架

两个特点:

1.数据驱动视图,数据一旦变化,视图就变化(页面会重新渲染)。数据驱动视图是单向的

2.数据双向绑定,页面一旦变化,数据也变化。

一个最简单的例子:

<!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>Document</title>
    <!-- 导入vue.js就把vue变成了全局变量 -->
    <script src="./lib/vue.js"></script>
</head>

<body>
    <div id="app">
        {{ message }}
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'Hello Vue!'
            }
        })
    </script>
</body>

</html>

3.Vue指令

1.内容渲染指令

内容渲染指令用来渲染DOM元素中的文本内容。常用的内容渲染指令:

  • v-text
  • {{}}
  • v-html

1.v-text:会覆盖标签内原本的内容(缺点)

<p v-text="name">姓名</p>
data: {
     name: 'zhangsan'
}
// 结果是zhangsan,覆盖了里面原本的姓名

2.{{}};插值字符串,不会覆盖原来的内容

<div id="app">
        大家好,{{ message }}
</div>
 data: {
    message: 'Hello Vue!'
}

3.v-html:会解析里面的html代码

<p v-html="text"></p>
data: {
	text: '<span style="color:red;">zhangsan</span>'
}

2.属性绑定指令

  • v-bind:属性绑定指令

例子:

<input type="text" v-bind:placeholder="tips">
<!-- 简写形式-->
<!--<input type="text" :placeholder="tips">-->
data: {
    tips: '请输入用户名'
}

由于v-bind:使用次数很多,官方推荐简写形式(:)就是一个冒号

在这里插入图片描述

内容渲染指令与属性绑定指令也能进行简单运算

3.事件绑定指令

  • v-on:事件绑定指令
<p>{{count}}</p>
<button v-on:click="addCount">+1</button>
<!--<button @click="addCount">+1</button>-->
var vm = new Vue({
    el: '#app',
    data: {
        count: 1
    },
    methods: {
        addCount(){
            this.count += 1
        }
    }
})

可以在方法里使用this.数据去访问数据

v-on的简写属性@

事件可以传递参数,当不传递参数时,方法默认有一个参数,参数是事件对象,事件对象里面的target属性代表事件源对象,可以利用事件源对象改变背景颜色之类的。

当我们传递参数时,事件对象会被覆盖。那我们就是想传参,又想拿到事件对象,那么传递参数时,必须传递另外的参数,参数是固定写法$event

<button @click="addCount(1,$event)">+1</button>

methods: {
        addCount(n,e){
            ...
        }
 }

4.数据双向绑定指令

注意:上面的指令都只能数据渲染视图,不能视图渲染数据,只有数据双向绑定才能完成

  • v-model

v-model只能和表单数据绑定,因为只有表单元素才能给用户修改

5.条件渲染指令

  • v-if
  • v-show

区别:v-if:每次都是动态的创建元素或删除元素;v-show只是将其display:none而已

v-if配套使用:v-if,v-else-if,v-else

6.列表渲染指令

  • v-for
    <div id="app">
        <p v-for="(item,index) in list" :key="item.id">id是{{item.id}},姓名是{{item.name}}</p>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                list:[
                    {id: '1',name: 'zhangsan'},
                    {id: '2',name: 'lisi'}
                ],
            }
        })
    </script>

其中list是要循环的数组,item是循环中的每一个对象

v-for还支持v-for="(item,index) in list" 其中index为循环的索引,从0开始

官方强烈要求只要使用到了v-for,就必须为每一个循环项添加属性key,而且必须每一个是唯一的,推荐使用id作为key,不能使用索引index作为key

4.Vue过滤器

Vue过滤器在Vue3.0已经被淘汰,但是在Vue2.0版本还能使用。

Vue过滤器只能使用在插值表达式和属性绑定指令中,过滤器本质是一个函数,通过“管道符”调用。管道符前面表示是这个过滤器(函数)的参数。过滤器函数中必须return值

	<div id="app">
        <p>{{message | capi}}</p>
    </div>
    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                message: "nihao"
            },
            // 过滤器必须写在filters节点下
            filters: {
                capi(val){
                    return val.toUpperCase();
                }
            }
        })
	</script>

1.私有过滤器(如上图)

2.全局过滤器

Vue.filter('capi',(val) => {
	return val.toUpperCase();
})
// 全局过滤器
// 第一个参数为过滤器的名称
// 第二个参数为过滤器函数处理

注意事项:如果全局过滤器与私有过滤器一致,那么优先调用私有过滤器。 过滤器也可以连续调用。

5.Watch监听器

监听器意为:监听数据的变化,只要数据一变化,就发生某些操作,监听器必须写在watch节点下;监听器本质也是函数。

    <div id="app">
        <input type="text" v-model="username">
    </div>
    <script>
        const vm = new Vue({
            el: "#app",
            data: {
                username: ''
            },
            watch: {
                // 第一个参数为新的值,第二个参数为旧的值
                username(newval,oldval){
                    console.log('n:'+newval+',o:'+oldval)
                }
            }
        })
    </script>

监听器函数必须写在watch节点下,监听哪个数据,函数名就写那个数据名。

但是我们发现这个监听器函数必须在数据发生变化才会触发函数,我们想页面一刷新就触发一次函数怎么办?

其实监听器格式有2种:

  • 方法监听器(也就是上面那种,不能页面刷新触发,也不能深度监听)
  • 对象监听器(好处 1.就是可以在immediate情况下,页面一刷新就触发 2.可以实现深度监听,当监听的是一个对象时,里面的属性变化也能监听到
    <div id="app">
        <input type="text" v-model="username">
    </div>
    <script>
        const vm = new Vue({
            el: "#app",
            data: {
                username: ''
            },
            watch: {
                username: {
                    handler(newval,oldval){
                        console.log('数据刷新');
                    },
                    // 是否立即触发,true表示触发
                    immediate: true,
                    // 深度监听
                    deep: true
                }
            }
        })
    </script>

6.计算属性

计算属性的本质是属性,但是定义时,是一个函数。通常可以对原来的属性进行计算,得到一个新的属性。

计算属性定义在computed节点下

    <div id="app">
        <p>{{newmsg}}</p>
    </div>
    <script>
        new Vue({
            el:"#app",
            data: {
                msg: "hi"
            },
            computed: {
                newmsg(){
                    return this.msg + "hao"
                }
            }
        })
    </script>

7.基于Vue-cli搭建webpack脚手架项目

npm i @vue/cli -g

搭建项目脚手架:

vue create 文件夹名

看看Vue脚手架项目的结构及项目组成

node_moudel: 项目所依赖的包

public文件夹:项目首页index

src–assets:静态文件

​ --components:组件文件夹

​ --App.vue :组件

​ --main.js :入门文件

main.js内容:

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')  // 这里与el:“#app”一样的效果

意思是将App组件引入到index的#app中

什么是组件

组件就是把可以重复使用的UI界面,js函数封装以便下次使用。

在Vue项目中,以.vue结尾的文件都是组件。

组件组成部分:《template》《script》《style》

声明组件:

<template>
  <p>{{msg}}</p>
</template>

<script>
export default {
    data(){
        return {
            msg: "1234"
        }
    }
}
</script>

<style lang="less" scoped>
    p {
        color: red;
    }
</style>>

注意事项

  • template中只能有一个根节点
  • script标签中data是函数,在return中返回对象

使用组件

  1. 导入组件
  2. 注册组件
  3. 使用组件
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
      // 使用组件
    <Test></Test>
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>
<script>
// 导入组件
import HelloWorld from './components/HelloWorld.vue'
import Test from '@/components/Test.vue'

export default {
  name: 'App',
  // 注册组件
  components: {
    HelloWorld,
    Test
  }
}
</script>

自定义属性:我们再封装好组件后,希望调用方传递参数过来给组件使用,就用到了自定义属性。

export default {
  name: 'App',
  // 自定义属性
  props: ['init']
  // 注册组件
  components: {
    HelloWorld,
    Test
  }
}

注意事项

props属性是只读属性,不能修改。(将其值赋给data里面的值,就能修改)

export default {
  name: 'App',
  // 自定义属性
  props: ['init']
  data(){
	return {
			num: this.init
		}
	}
}

自定义属性的默认值

当调用方不传递参数的时候,自定义属性的值是undefined。那么默认值怎么设置?

export default {
  name: 'App',
  // 自定义属性
    // 默认值是0
  props: {
      init: {
          default: 0
      }
  }
  data(){
	return {
			num: this.init
		}
	}
}

规定自定义属性的类型以及必填项

可以要求调用方传递参数的类型以及调用方调用组件时,必须传递其参数

export default {
  name: 'App',
  // 自定义属性
    // 默认值是0
  props: {
      init: {
          default: 0,
          // 规定参数类型
          type: Number,
          // 规定必须传递参数
          required: true
      }
  }
  data(){
	return {
			num: this.init
		}
	}
}

scoped属性

<style lang="less" scoped>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

加入了scoped属性表示里面的css样式只有在当前这个组件里面其作用,不会影响到别的组件。

那么当我们在组件里,引用了别的第三方组件,想修改子组件的样式,可以使用deep。

<style lang="less" scoped>
/deep/ h5 {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

8.组件的生命周期函数

组件创建周期:

  • beforeCreate():组件的props/data/methods都尚未被创建,都处于不可用的状态。
  • created():组件的props/data/methods已经创建好,都处于可使用的状态,但是组件的模板结构尚未生成。(不能使用页面中的Dom元素)(适合发起ajax请求)
  • beforeMount():把数据和模板渲染到内存中,也不能操作Dom元素
  • mounted():数据和模板从内存中渲染到浏览器中,可以操作Dom元素

组件使用周期:

  • beforeUpdate():当页面中的data数据发生变化时(ajax请求,表单数据双向绑定),在页面会重新渲染数据之前的函数。
  • updated():页面已经重新渲染好了数据。

组件销毁周期:

  • beforeDestroy():将要销毁此组件,此时还处于正常状态,组件还在正常工作中。
  • destroy():组件已经销毁

9.Vue组件之间传值

父子之间传值

父向子传值:

​ 就是利用props属性传值。

​ 子组件写props属性,父组件在使用子组件的时候利用属性绑定v-bind:绑定props属性

子组件:

<template>
  <p>{{msg}}</p>
</template>

<script>
export default {
    props: {
        msg:{}
    }
}
</script>

父组件:

<template>
  <div id="app">
    <input type="text" v-model="username">
    <Test :msg="username"></Test>
  </div>
</template>

<script>
import Test from '@/components/Test.vue'

export default {
  name: 'App',
  data() {
    return {
      username: 'zs'
    }
  },
  components: {
    Test
  }
}
</script>
子向父传值:

子组件向父组件传值需要使用到自定义事件

 // vm.$emit( 自定义事件的名称,自定义事件处理程序需要的参数1,参数2,参数3)

    vm.$emit( 'aa' )

子组件:

<template>
  <div>
    <p>{{ msg }}</p>
      // 子组件定义点击函数
    <button @click="son">按钮</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg: "hello vue",
    };
  },
  methods: {
    son() {
      console.log(this.msg);
        // 激活自定义事件,参数一:事件名称,参数二: 传递参数
      this.$emit("give", this.msg);
    },
  },
};
</script>

父组件:

<template>
  <div id="app">
    <p>{{username}}</p>
      // 使用子组件时,自定义函数,前面give指的是事件名称,后面指的是事件触发函数
    <Son @give="give"></Son>
  </div>
</template>

<script>
import Son from '@/components/Son.vue'
export default {
  name: 'App',
  data() {
    return {
      username: ''
    }
  },
  components: {
    Son
  },
  methods: {
      // 使用自定义函数
    give(val){
      this.username = val;
    }
  }
}
</script>

兄弟之间传值

在Vue2.0中,兄弟之间传值需要用到EventBus.js作为中间人。

使用步骤:

  • 创建eventBus.js模块,并向外共享一个Vue实例对象
  • 在数据发送方,调用bus.$emit(‘事件名称’,发送的数据)
  • 在数据接收方,调用bus.$on(‘事件名称’,‘接受到数据要处理的函数’)

eventBus.js

import Vue from 'vue'

export default new Vue()

数据发送方:

<template>
    <button @click="send">发送</button>
</template>

<script>
import Bus from '@/components/eventBus.js'
export default {
    data(){
        return {
            msg: 'nihao'
        }
    },
    methods: {
        send(){
            Bus.$emit('send',this.msg)
        }
    }
}
</script>

<style>

</style>

数据接收方:

<template>
  <p>{{msgfromleft}}</p>
</template>

<script>
import Bus from '@/components/eventBus.js'
export default {
    data(){
        return {
            msgfromleft:''
        }
    },
    created(){
        Bus.$on('send',(val) => {
            this.msgfromleft = val
        })
    }
}
</script>

<style>

</style>

10.refs引用

由于Vue不推荐操作Dom元素,但是有些情况必须操作Dom元素。所以Vue里内置了 r e f s 对 象 。 refs对象。 refsrefs默认是一个空对象。

当给元素赋值ref属性时就能拿到该Dom元素:

<template>
  <p ref="myp">{{msg}}</p>
  <button @click="changecolor"></button>
</template>

<script>
export default {
    data(){
        return {
            msg:''
        }
    },
	methods: {
        changecolor(){
            this.$refs.myp.style.color="red"
        }
    }   
}
</script>

同理:也能拿到组件Vue。

11.this.$nextTick(callback)方法

组件的$nextTick(callback)方法,会把回调函数里的方法延迟到Dom更新之后执行,从而保证回调函数里的方法能操作到最新的Dom元素。

举报

相关推荐

0 条评论