本篇是仿网易云音乐PC-总结的第四部分,Part4-VUE。本项目仅使用了VUE这一个前端框架,由于其简单易用,具有十分友好的文档,使新手如我也可以直接上手。本文主要总结在项目过程中遇过的问题和使用心得,全部官方文档请戳https://cn.vuejs.org/v2/guide/
仿网易云音乐PC全部项目请戳->>>>> https://github.com/love3forever/gogo3
使用VUE
使用VUE.js有两种方法:
直接在HTML文件中引入
1<script src="https://unpkg.com/vue"></script>通过脚手架vue-cli创建vue项目(需要Node环境)
本项目使用第二种方法。
配置环境
安装node.js
进入https://nodejs.org/en/download/直接下载并安装。
安装完成后,可以命令行工具中输入 node -v 和 npm -v,如果能显示出版本号,就说明安装成功。如果已有node环境,建议更新版本(低版本node可能无法识别vue)。
|
|
安装vue-cli
|
|
安装完成后,可以命令行工具中输入 vue -V,如果能显示出版本号,就说明安装成功。如果安装失败,先清理缓存再重新安装。
新建项目
- 通过命令行进入项目目录,然后输入1vue init webpack Vue-Project
执行后,按照提示手动输入项目名称、描述、作者、打包方式、是否安装vue-router、是否使用ESLint检查代码、是否建立单元测试等内容后,会在当前目录生成一个以输入的项目名称为文件名的项目文件夹。
然后进入项目文件件夹,安装依赖项
1npm install安装vue-router和vue-resource模块(可选)
vue-router和vue-resource是官方提供的扩展,分别用于配置路由和处理http请求,可根据实际情况选择是否安装。1cnpm install vue-router vue-resource --save安装完成后,启动项目
1npm run dev
这时应自动启动chrome,并跳转到localhost:8080页面了。
- 关于修改配置文件
项目默认使用8080端口,如果已被占用,可以进入config->index.js中修改配置文件使用其他端口。
打包项目
项目开发完成后,进入项目文件夹输入
将项目打包,打包成功后会生成dist文件夹,这个文件夹里的文件就是最终的成果,它部署到服务器上就OK辣。
项目结构
项目的目录结构如所示。我们需要关注的是src目录、static目录和index.html。
- src文件夹是项目源码目录,其中初始包括三个文件夹和两个文件:
- assets文件夹 一般存放图片等资源
- components文件夹 存放以.vue为后缀的组件
- router文件夹 其中的index.js用于配置路由
- App.vue 默认主组件,可以理解为其他所有组件的父组件
- main.js 入口js文件,主要作用是初始化vue实例并使用需要的插件
- static文件夹是纯静态资源文件夹,其中的文件不会被webpack构建
- index.html是入口页面
组件结构
一个vue组件就是一个以.vue为后缀的文件,它包括template、script、style三个部分,分别写入HTML、JavaScript、css代码。结构例子直接戳下边链接中的任何一个文件
https://github.com/love3forever/gogo3/tree/master/src/components
下面说说每个部分需要注意的地方
template
template标签内是html元素的书写区域,这里需要注意的是,下面只能有一个孩子节点(独生子女哇)。123456789101112<!--正确--><template><div><div></div><div></div></div></template><!--错误--><template><div></div><div></div></template>script
script标签内是javascript的书写区域,可以通过import…from引入其他vue组件或方法。如果引用了其他vue组件,则需要在export default中注册组件,不注册就使用会报错:
123456789<script>import mode from './user-fansfavmode'export default {components: {mode},}</script>通过vue-cli方式搭建的项目,export default中如果有data,则一定要写成函数的形式,数据写在函数return的对象中。 如下:
12345678910<script>export default {data (){return {a:1,b:2,}}}</script>
style
style标签中写的就是css样式啦,唯一需要注意的一定就是,如果在style标签中加入了scoped属性,那么这个标签里的所有样式仅供它所在的组件使用,其他组件无法使用;而如果不加scoped属性,那么这个标签里的样式可供全局使用。
data
前面已经说过,通过vue-cli创建的vue项目,组件中的data只能以函数的形式return数据。关于data还需要注意的一点是:只有在data中声明的数据才是响应式的。在data之外,可以通过vue.set将响应式属性添加到data中已有的响应式数据上,但无法创建一个根级别的响应式属性。
对于数组,则有另外的问题。受JS限制,Vue 不能检测以下变动的数组:
- arr[index] = newValue;
- arr.length = newLength;
也就是说,通过以上两种方法改变数组成员,即便数组是响应式的,console.log也确实发现了变化,但这个变化不会被vue识别到。想要将数据的改动具有响应式,可以通过arr.splice()或vue.set解决。
props
props 是定义在子组件中的属性,用于接收父组件传来的数据。格式:
关于props,需要注意:
数据流是单向的,props是用来接收父组件的数据的,并不能向父组件传递数据
通过v-bind可以实现动态props,父组件传递的值发生变化,子组件也会同步变化。这就意味着,可以用watch观测动态props的变化。
不能直接修改props的数据。直接修改props接收的数据是不被允许的,在子组件中的props是父组件传递的数据的引用,在子组件中改变props的值也会导致父组件变化。如果想对props进行修改,可以定义一个计算属性处理props并返回。
methods
methods是一个对象,以键值对的形式存储所在组件中的方法。
这里需要注意的是,methods中的方法必须以属性名:函数的形式定义,不能使用箭头函数。因为箭头函数会将this指针绑定到函数定义时所在的作用域。在方法内部可以使用箭头函数。
钩子函数
贯穿一个vue实例全生命周期的有以下钩子函数,它们的作用就是在不同阶段执行某些操作。
beforeCreate
vue实例创建后立即执行这个钩子函数,此时数据和事件都没有被初始化。也就是说,这里无法直接访问data、methods等。
这个钩子里比较适合写loading和http请求(本项目使用vue-resource)。因为http请求是异步的,通常请求返回时已经vue实例已经created了,可以直接访问data和methods等属性和方法。为了稳妥以及避免造成混乱,还是建议把http请求写在created钩子中。123456789101112131415<script>export default {beforeCreate:function(){var result = this.result;//错误,此时result未初始化,无法访问到this.$http.get('http://123.206.211.77:33333/api/v1/index/detail').then(response => {this.result = response.data;//正确,http请求正常返回后,通常result已被初始化,可以访问到}).catch(response => {console.log(response)});},}</script>created
数据、事件等属性和方法初始化完毕,但DOM并未生成,el属性不存在。在这里可以直接访问data和methods等,但无法获取DOM元素。
这个钩子里比较适合写Loading结束、http请求、一些初始化操作。- beforeMount
模板挂载之前,el属性存在,但并未挂载,仅仅是“占坑”。 - mounted
模板挂载之后,el属性存在。
这个钩子可以配合this.$nextTick实现依赖DOM的操作,如监听事件等。 - beforeUpdate
组件更新之前执行 - updates
组件更新之后执行 - beforeDestory
组件销毁前执行,常用确认是否执行销毁动作。 - destoryed
组件销毁后执行,常用于收尾清除数据。 - activated
针对keep-alive,组件被激活时执行 - deactivated
针对keep-alive,组件被移除时执行
条件渲染 v-if vs v-show
v-if和v-show都是控制DOM元素是否渲染的。他们存在以下区别:
- v-if在条件为假时,不去渲染元素;v-show始终渲染,仅仅是通过设置display属性来控制元素的显示和隐藏
- v-if 可以写在template标签内控制整个模板的渲染与否,v-show不可以,只能写在template标签的子元素中
- v-if 可以与v-else、v-else-if联合使用;v-show不可以
综上,v-if适用于运行时条件不太可能改变的场景,比如:异步请求数据,在数据返回之后渲染页面时使用v-if更好;v-show适合可能频繁切换元素的显示和隐藏的场景,比如hover。
computed属性 vs watch属性
- computed属性
简单说,一个computed属性是依赖于data中一个或几个数据“计算”得到的。1234567891011121314<script>export default {data () {return {others: [{ num: 5, name: "title"}],}},computed:{cmtFrontMore:function(){return this.others[0].num>2;},},}</script>
computed属性是响应式的。这里的响应式有以下含义:
- computed属性跟随其依赖的变化而变化。如上栗,computed属性cmtFrontMore是依赖于data中的others属性的,others变化也会触发cmtFrontMore的变化。
- 默认情况下computed属性的变化只会由其依赖的变化触发,任何在computed属性外部试图更改属性都会被拒绝。如果想实现这一的效果,则需要为属性提供set方法。1234567891011121314151617181920212223<script>export default {data () {return {others: [{ num: 5, name: "title"}],}},computed:{cmtFrontMore:{get: function(){return this.others[0].num === 2;},set: function(newVal){if (newVal){this.others[0].num = 2;} else {this.others[0].num = 5;}}}},}</script>
这样,this.others[0].num变化会引起cmtFrontMore变化;this.cmtFrontMore变化也会触发this.others[0].num变化。
- watch属性
watch属性是一种观测并相应数据变化的属性。1234567891011121314151617<script>export default {data () {return {others: [{ num: 5, name: "title"}],cmtFrontMore: false,}},watch:{others: function(newVal,oldVal){if (newVal[0].num === 2){this.cmtFrontMore = true;}},},}</script>
如上栗,当others属性发生变化,则执行watch中others对应的函数。
- 比较
大多数情况下,computed属性更适合,但是在执行异步操作或开销较大的操作时,就需要使用watch了。可以理解为,computed属性是要返回一个依赖于某个数据变化而变化的数据,而watch属性是要在发现某个数据变化后,dosomething。
this.$nextTick
Vue 异步执行DOM更新。也就是说,当你更改了一个响应式数据,它所涉及的组件并不会立即重新渲染。数据更改触发DOM更新的流程是:
数据更改->执行完其它同步命令->DOM更新。
因此,在数据更改后试图立即操作更新后的DOM会失败,此刻DOM还未更新呢!
为了解决这个问题,我们可以使用this.$nextTick(callback)。在数据更改后立刻使用this.$nextTick(),会在DOM更新后立即执行其中的回调函数。