# Vue
> Vue学习过程中遇到的一些小tips
1、组件化
Vue 的组件可以分为全局组件和局部组件
全局组件:声明好后可以在全局使用
局部组件:只可以在当前模块使用
```
//全局组件
Vue.componetns('todo-item',{
template:'
{ {content} } ',
prop:['content']
});
//局部组件
var HobbyItem = {
template:"hobby"
}
new Vue({
el:"#test",
components:{
'todo-item':HobbyItem
}
});
```
2、模块、实例
每一个模块都是 Vue 的一个实例,也就是说可以向每一个模版中像写 Vue 的实例一样进行开发。
3、父组件与子组件通信用 props 传递
4、子组件向外触发事件 this.$emit(事件名,参数列表)
5、template 模版下最外层只可有一个根元素
```
```
6、单独在 .vue 文件中,data 是作为函数存在的。
```
data: function(){
}
data () {
}
```
7、在 vue-cli 脚手架中,组件的声明方式
```
export default{
components : {
'todo-item':Todo-Item
}
}
components:['Todo-item']
```
8、style 中可以声明样式作用域
style 同名的样式不会对其他组件有影响
9、在用 Vue 框架在开发的时候一般都会用 **Vue-cli** 脚手架,但是这样经过 webpack 打包后源代码会被打包成 dist 目录下的 bundle.js,此时的代码是被压缩处理过的,且经过 webpack 的处理各个代码模块的逻辑,代码可读性不是很好且不可调试,此时有些人在开发阶段就会需要调试?此时怎么办呢
慌不要慌,小哥哥带你 hold 住全场。
* 脚手架已经帮你处理好了这块需求了,看下图

* 有些大佬不要脚手架,喜欢自己初始化项目,用 npm 挨个安装所需要的依赖。然后自己配置 webpack 的 options。需要调试的话,需要做下面的配置
```
config.devtool = '#cheap-module-eval-source-map'
```
这样你就可以在浏览器当中像写普通的 JS 一样进行调试代码了。比如

10、Vue 中 **...** 底层的做法是 ** render()**方法, 对 template 中的元素依次遍历创造节点
11、使用 stylus 写 css 的时候需要告诉 webpack如何处理代码,所以
```
```
12、在使用 v-for 或 jsx 的map方法时候需要在生成的节点设置一个唯一的**key**作为标识,这样下次渲染的时候就可以根据 key 值判断,是否需要刷新 dom ,提高了效率
13、props 的另一种写法
```
props:[
todos:{
type:Array,
required:true
}
]
```
14、css 单独打包,缓存下来,提高程序的体验。需要使用**extrat-text-webpack-plugin**
15、业务代码与框架代码如果打包在一起,后期维护很麻烦(因为框架代码基本不需要很快更新,但是业务代码经常更新),所以应该拆分出来,单独打包。将框架代码方便缓存。
16、webpack 的2个概念:
hash: 各个文件生成的**hash**值相同
chunkhash:不同文件(模块)生成的**hash**值不同
- Vue 使用官方组件(比如 vue-resource)
- 先引入
- 再 use(必须在 main.js 中)
```
import VueResource from 'vue-resource'
Vue.use(VueResource);
```
- 第三方组件
- 哪里用,哪里引入(比如 axios)
- npm install 组件名 --save
将安装的组件名称的依赖写入 package.json
- 网络请求组件
- vue-resource
- axios
- fetch-jsonp
- 父组件给子组件传值
- 父组件在调用子组件的时候传递
- 子组件 声明 porps
- 同时可以在子组件接收的时候验证传值的正确性
```
props:['name','age']
props:{
'name':String,
'age':Number
}
```
- 父组件给子组件传递方法
```
//父
//子
export default{
props:["run"],
methods:{
test(){
run();
}
}
}
```
- 子组件可以通过上面传递值给父组件
- 父组件可以将自身传递给子组件。所以可以在子组件里面访问父组件的属性和执行父组件的方法
- 父组件主动获取子组件的数据和方法
- 在调用子组件的时候给子组件定义一个 ref
```
```
- 在父组件里面通过**this.$refs.header.属性** 和 **this.$refs.header.方法**
- 子组件里面获取父组件的属性和方法 **this.$parent.属性** 和**this.$parent.方法**
- 非父子组件间的传值
- 先定义1个中间的组件
- 在需要暴露数据的一方。import 中间组件,调用 $emit(事件名称,数据)
- 在需要接受数据的一方。import 中间组件,调用 $on(事件名称,function(data){ //... })
```
//中间组件
import Vue from 'Vue';
var VueEvent = new Vue();
export default = Vue;
//Home.vue(传递数据给 News.vue)
import VueEvent from '../model/VueEvent.js';
VueEvent.$emit("postData",{"name":"杭城小刘"});
//News.vue(接收数据)
import VueEvent from '../model/VueEvent.js';
new Vue({
mounted(){
VueEvent.$on("postData",function(data){
console.log("从Home组件接收到的数据:"+data);
});
}
});
```
- 路由的使用规则
- 创建、引用组件(main.js)
```
import Home form './Components/Home.vue'
import News form './Components/News.vue'
```
- 导入 vue-router 并 use(main.js)
```
import VueRouter from 'vue-router'
Vue.use(VueRouter);
```
- 配置路由(main.js)
```
const routes = [
{path:"/home",component:"Home"},
{path:"/news",component:"News"},
];
```
- 实例化 router(main.js)
```
const router = new VueRouter({
routes
//等于 routes:routes,只有当key和value一致的时候可以简写
});
```
- 挂载 router(main.js)
```
var vue = new Vue({
el:"#app",
router,
data(){
return {
msg:"root components"
}
}
});
```
- 在模版里面放上路由的出口。将 写到根组件上 (App.vue)
```
//App.vue
```
- 要实现类似导航效果,可以使用 ****
```
首页
新闻
```
- 默认首页
```
const routes = [
{path:"/home",component:"Home"},
{path:"/news",component:"News"},
{path:"*",redirect:"News"} //默认跳转到首页
];
```
- Vue 动态路由和 Get 传值
```
//新增加的 router-link 需要在路由配置里面添加配置项。
const routes = [
{path:"/home",component:"Home"},
{path:"/news",component:"News"},
{path:"/content",component:"Content"},
{path:"*",redirect:"News"} //默认跳转到首页
];
```
- 上面的写法是静态路由,也就是不能传递参数
- 那么什么是动态路由,也就是可以传递参数
```
//新增加的 router-link 需要在路由配置里面添加配置项。
const routes = [
{path:"/home",component:"Home"},
{path:"/news",component:"News"},
{path:"/content:newid",component:"Content"}, //动态路由
{path:"*",redirect:"News"} //默认跳转到首页
];
```
- 子组件页面获取动态路由传递过来的值
```
this.$route.params
```
- 子组件拿到父组件动态传递过来的值用动态路由
```
const routes = [
{path:"/home",component:"Home"},
{path:"/news",component:"News"},
{path:"/content:newid",component:"Content"}, //动态路由
{path:"*",redirect:"News"} //默认跳转到首页
];
this.$route.params
```
- Get 传值
```
const routes = [
{path:"/home",component:"Home"},
{path:"/news",component:"News"},
{path:"/content",component:"Content"}, //动态路由
{path:"/product",component:"Product"}, //
{path:"*",redirect:"News"} //默认跳转到首页
];
//拿到值
this.$route.query
```
- 编程式导航(JS 跳转控)
```
//直接跳转到某个组件
this.$route.push({path:'News' });
//跳转到某个组件并且传递值
this.$route.push({path:'/content/495'});
```
- 命名路由跳转
```
const routes = [
{path:"/home",component:"Home"},
{path:"/news",component:"News"},
{path:"/content",component:"Content",name:'news'}, //动态路由
{path:"/product",component:"Product"}, //
{path:"*",redirect:"News"} //默认跳转到首页
];
//跳转
this.$router.push({name:'news'});
```
- vue-router 默认的是 hash 模式, 也就是 127.0.0.1/# 这种。所以我们在初始化 vue-router 的时候可以修改它的模式
```
const VueRouter = new VueRouter({
mode: 'history',//hash 模式改为 history 模式
routs
})
```
- 嵌套路由(比如顶部的菜单栏不变,点击左边的菜单栏实现页面内容的切换)
```
//注册路由嵌套
const routes = [
{path:"/home",component:"Home"},
{path:"/news",component:"News"},
{
path:"/user",
components:"User",
children:[
{path:'useradd',component:'UserAdd'},
{path:'userlist',component:'UserList'},
]
},
{path:"/content",component:"Content",name:'news'}, //动态路由
{path:"/product",component:"Product"}, //
{path:"*",redirect:"News"} //默认跳转到首页
];
//将放到动态加载的子组件的地方
//User.vue
```
- Vuex:主要解决不同组件之间的数据共享、数据持久化(不适合与小项目,主要用于大项目)
- 安装 vuex
- src 目录下新建一个 vuex 的文件夹
- vuex 文件夹下面新建一个 store.js 文件
- 引入 vuex
```
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
```
- 定义数据
```
// state 在 vuex 中用于存储数据
var state = {
count:1
}
```
- 定义方法
```
var muations = {
incCount(){
++state.count;
}
}
```
- 暴露 vuex
```
const store = new Vuex.Store({
state,
mutations
});
export default store;
```
- 使用 vuex(解决不同组件之间数据共享问题;数据持久化)
- 引入 vuex
```
import store from '../vuex/store.js'
```
- 注册 vuex
```
export default{
data(){
return {
msg: 'Hello'
}
},
store,
methods:{
}
}
```
- 使用
```
//访问属性
this.$store.state.count
//触发方法+不带参数
this.$store.commit('incCount');
//触发方法+不带参数
this.$store.commit('方法名',参数);
var mutation = {
addList(state,data{
state.list = data;
}
}
```
- getters 类似于计算属性,改变 state 里面的 count 的值会触发 setters 里面的方法,从而在里面可以获取新的值(做一些逻辑操作)
```
var getters = {
computedCount: (state) => {
return state.count*2
}
}
```
- action 类似于 mutation ,在外面使用的时候用 this.$state.dispath('方法名')
- 某些页面可能我们只需要切换数据源和样式模版。所以数据源有可能是变化的,页面的模版也是变化的。
这样子我们可能会用到 `v-if、v-else-if...v-else` 来切换页面的模版。但是在模版里面去 `v-for` 循环展示数据源。
早期遇到错误,大概意思是说我们循环动态生成的元素,有 key 重复了,最后查找资料得到解决方案。在判断模版的时候需要使用 ``
```
法定代表人:{ {item.legalperson} }
成立时间:{ {item.create} }
注册资本:{ {item.capital} }(万元)
{ {qualification} }
```