1.nodejs和npm
nodejs不是js的一个框架,是js运行时的运行环境,类似java中的jvm。
npm
是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用 。
2.nodejs和vue的关系
首先vue.js 是库,不是框架。
Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。
Vue.js 的核心是一个允许你采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统。
vue.js 下载过来直接在html中引入就好了并不一定要npm install vue.
vue.js 有路由的 叫vue-route.js,vue.js也有数据请求 叫vue-resource.js
Vue.js可以在html里引用,使用npm引入是方便包管理。
等到应用需要的库和框架多起来后,一个个从html里引入就不方便了。
所以用到打包工具比如webpack(node.js中的构建工具),可以直接require引入之后将不同模块打包成单个js文件。同时这些工具提供各种自动化处理,让前端开发更爽。
最后Vue.js是数据驱动,和JQuery思路不同,你几乎不需要自己进行复杂低效的dom操作,开发简介明了。从这一点上说,可以基本抛弃JQuery了。
3.搭建简单的前后端分离项目
安装node.js => 官网下载安装,npm -v 查看是否安装成功
安装vueCLI脚手架 => npm install vue-cli -g(可在那换cnpm,使用淘宝的镜像) 全局安装
运行vue查看是否安装成功
到指定目录下快速搭建项目 => vue init webpack(模板名称) 项目名称
安装依赖 => 进入项目文件夹下执行cnpm install 来安装模板中的package.json中的依赖,安装成功后
会在项目文件夹下自动生成node_modules文件来存放安装的依赖文件
运行项目 => npm run dev(此时必须使用npm来运行,cnpm不可以)
webpack => 类似一个打包工具,.vue程序浏览器无法解析,webpack将你项目中的Vue组件打包成为一个庞大的js文件
4.main.js => 程序入口文件,是初始化vue实例并使用需要的插件,加载各种公共组件,会用App.vue替换index.html中 的id='app'的div
App.vue => 主组件,页面入口文件,所有的页面都是在App.vue下进行切换的,负责构建定义及页面组件归集
router index.js => 把准备好的路由组件注册到路由里
index.html => vue是单页界面,主窗口通过index.html渲染,默认的http://localhost:8080会去加载index.html,当执行 npm run dev后,main.js会被添加到index.html中
5.使用element-ui
下载elemrnt-ui => npm i element-ui -S
在main.js中引入 => import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';
Vue.use(ElementUI);
new Vue({ el: '#app', render: h => h(App) });
在.vue文件中就可以直接使用了。
6.Vue.js和.Vue文件的理解
vue.js => 是一套构建用户界面的渐进式框架,它采用自底向上增量开发的设计。(自底向上设计方法是根据系统功能要 求,从具体的器件、逻辑部件或者相似系统开始,凭借设计者熟练的技巧和丰富的经验,通过对其进行相互连 接、修改和扩大,构成所要求的系统。)Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或 既有项目整合。另一方面,当与单文件组件和Vue生态系统支持的库结合使用时,Vue 也完全能够为复杂的单
页应用程序提供驱动。
.vue文件 => 是一个自定义的文件类型,用类似HTML的语法描述一个Vue组件。每个.vue文件包含三种类型的顶级语言块 <template>, <script> 和 <style>。这三个部分分别代表了 html,js,css。
7.Vue
指令 => 指令 (Directives) 是带有 v-
前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式 ,稍后我们再讨 论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM
计算属性 => 计算属性是基于响应式依赖进行缓存,只在相关响应式依赖改变时才会进行重新取值。
而方法在每次触发重新渲染时,调用方法总会再次执行函数。
get和set => 通过getter/setter实现对属性数据的显示和监视
使用插件 => 声明使用插件 Vue.use(myPlugin)
Class与Style绑定
对象语法 => 我们可以传给v-bind:class一个对象,以动态切换class,也可以绑定一个返回对象的计算属性
数组语法 => 我们可以把一个数组传给 v-bind:class
,以应用一个 class 列表
8.Vue发送ajax请求
方式一、
- .结合 vue-axios使用
-
import axios from 'axios' import VueAxios from 'vue-axios' Vue.use(VueAxios,axios);
之后就可以在组件中的方法中使用了
getdata(){
this.axios.get('/vue-demo/api/getdata').then((response)=>{
console.log(response.data)
}).catch((response)=>{
console.log(response)
})
}
方式二、axios改写Vue的原型属性
import axios from 'axios'
Vue.prototype.$ajax= axios
在组件中使用
this.$ajax.get('api/getNewsList').then((response)=>{
this.newsList=response.data.data;
}).catch((response)=>{
console.log(response);
})
方式三、 vuex的action
在vuex的仓库文件store.js中引用,使用action添加方法
import Vue from 'Vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
const store = new Vuex.Store({
// 定义状态
state: {
user: {
name: 'xiaoming'
}
},
actions: {
// 封装一个 ajax 方法
login (context) {
axios({
method: 'post',
url: '/user',
data: context.state.user
})
}
}
})
export default store
在组件中发送请求的时候,需要使用 this.$store.dispatch
methods: {
submitForm () {
this.$store.dispatch('login')
}
}
9.router
router/index.js => 定义路由组件
main.js => 配置路由器,映射成路由,new Vue {}里添加路由
<router-link> => 路由链接
<router-view> => 路由渲染,路由链接页面显示的地方
嵌套路由 => children:[{path:'message',component}] => 路由链接和路由渲染在父组件里
缓存路由组件 => <keep-alive><router-view></router-view></keep-alive>
向路由组件传递数据
=> 路由路径参数携带参数 配置路由path:'mdetail/:id'
路由路径<router-link:to="'/mdetail/ '+m.id">
路由组件中读取请求参数 this.$route(代表当前路由).params.id
=> <router-view>属性携带数据 <router-view :msg="msg">
编程式路由导航相关api
1) this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面)
2) this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面)
3) this.$router.back(): 请求(返回)上一个记录路由
4) this.$router.go(-1): 请求(返回)上一个记录路由
5) this.$router.go(1): 请求下一个记录路由
10.vuex => 对 vue 应用中多个组件的共享状态进行集中式的管理(读/写)
状态自管理应用
1) state: 驱动应用的数据源
2) view: 以声明方式将 state 映射到视图
3) actions: 响应在 view 上的用户输入导致的状态变化(包含 n 个更新状态的方法)
vuex 核心概念和 API
state =>
1) vuex 管理的状态对象
2) 它应该是唯一的
const state = { xxx: initValue }
mutations =>
1) 包含多个直接更新 state 的方法(回调函数)的对象
2) 谁来触发: action 中的 commit('mutation 名称')
3) 只能包含同步的代码, 不能写异步代码
const mutations = { yyy (state, {data1}) { // 更新 state 的某个属性 } }
actions =>
1) 包含多个事件回调函数的对象
2) 通过执行: commit()来触发 mutation 的调用, 间接更新 state
3) 谁来触发: 组件中: $store.dispatch('action 名称', data1) // 'zzz'
4) 可以包含异步代码(定时器, ajax)
const actions = { zzz ({commit, state}, data1) { commit('yyy', {data1}) } }
getters =>
1) 包含多个计算属性(get)的对象
2) 谁来读取: 组件中: $store.getters.xxx const getters = { mmm (state) { return ... } }
modules =>
1) 包含多个 module
2) 一个 module 是一个 store 的配置对象
3) 与一个组件(包含有共享数据)对应
向外暴露 store 对象 =>
export default new Vuex.Store({ state, mutations, actions, getters })
组件中 =>
import {mapState, mapGetters, mapActions} from 'vuex' export default { computed: { ...mapState(['xxx']), ...mapGetters(['mmm']), } methods: mapActions(['zzz']) } {{xxx}} {{mmm}} @click="zzz(data)"
映射 store =>
import store from './store' new Vue({ store })
store 对象 =>
1) 所有用 vuex 管理的组件中都多了一个属性$store, 它就是一个 store 对象
2) 属性: state: 注册的 state 对象 getters: 注册的 getters 对象
3) 方法: dispatch(actionName, data): 分发调用 action
--------------------------------------------------
使用
下载vuex => npm install --save vuex
引入vuex => store.js(vuex的核心管理模块)
引入store.js => main.js 内引入
在组件中使用 => 组件对象获取store属性 this.$store.
dispatch => 分发调用action => (与后台交互)触发mutation调用, commit('mutationName')=> mutation中只包含更新
state的同步代码 => 更新state =>getters来读取state中属性
使用mapGetters,mapActions进行优化
11.渲染函数 => render
new Vue({
el: '#app',
render:h => h(App),
store
})
12.Vue实例生命周期
初始化显示 =>beforeCreate() created() beforeMount() mounted()
更新状态this.xxx = value =>beforeUpdate() updated()
销毁vue实例vm.$destory() =>beforeDestory() destoryed()
常用的生命周期方法 => created()/mounted(): 发送 ajax 请求, 启动定时器等异步任务
=> beforeDestory(): 做收尾工作, 如: 清除定时器
13.Vue props 用法
父子组件数据传递 => 子组件要显示的用 props 声明它期望获得的数据
然后在父组件中的占位符添加特性的方式来传递数据
静态
var childNode = {
template: `
<div>
{{forChildMsg}}
</div>
`,
props: ["for-child-msg"]
};
var parentNode = {
template: `
<div>
<p>parentNode</p>
<child for-child-msg="aaa"></child>
<child for-child-msg="bbb"></child>
</div>
`,
components: {
child: childNode
}
};
动态 父组件有所不同
var parentNode = {
template: `
<div>
<p>parentNode</p>
<child :for-child-msg="childMsg1"></child>
<child :for-child-msg="childMsg2"></child>
</div>
`,
components: {
child: childNode
},
data: function() {
return {
childMsg1: "Dynamic props msg for child-1",
childMsg2: "Dynamic props msg for child-2"
};
}
};
props 验证
单向数据流 =>
props 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件五一修改父组件的状态。
所以不应该在子组件中修改 props 中的值,Vue 会报出警告。
14.vue中this.$refs的使用
获取dom节点后,获取dom元素,需要document.querySelector(".input1")获取这个dom节点,然后再获取input1的值
但是用ref绑定之后,我们就不需要在获取dom节点了,直接在上面的input上绑定input1,然后$refs里面调用就行。
15.使用proxyTable解决跨域问题
找到根目录下config文件夹下的index.js文件
dev: {
env: require('./dev.env'),
port: 8080,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
target: 'http://www.abc.com', //目标接口域名
changeOrigin: true, //是否跨域
pathRewrite: {
'^/api': '/api' //重写接口
}
},
cssSourceMap: false
}
上面代码的效果是将本地8080端口的一个请求代理到了http://www.abc.com这一域名下
完整的请求发送流程
1)在组件中通过this.$store.dispatch 触发store中action的调用
2)在store内同一管理mutations,actions,getters,state,action定义方法,方法内来发送请求
api({
url: '/login/getInfo',
method: 'post'
})
3)api的定义
1.在main.js定义全局常量
import {default as api} from './utils/api'
Vue.prototype.api = api
2.在utils/api.js,创建axios实例(同一配置baseURL和超时时间),api即指的是axios实例
3.api.js读取config/prod.env.js内BASE_URL,最后的路径上的'/api'就是这里配置的
module.exports = {
NODE_ENV: '"production"',
BASE_URL:'"/"',
}
4)config/index.js内通过proxyTable内设置指定的端口发送的请求,'/api'替换为指定url,完成跨域