Vue 笔记

本文是尚硅谷前端笔记,原视频

细节

脚手架文件构造-P62

├── node_modules├── public│ ├── favicon.ico: 页签图标│ └── index.html: 主页面├── src│ ├── assets: 寄存动态资源│ │ └── logo.png│ │── component: 寄存组件│ │ └── HelloWorld.vue│ │── App.vue: 汇总所有组件│ │── main.js: 入口文件├── .gitignore: git 版本管制疏忽的配置├── babel.config.js: babel 的配置文件├── package.json: 利用包配置文件├── README.md: 利用形容文件├── package-lock.json:包版本控制文件

对于不同版本的 Vue-P63

  1. vue.js 与 vue.runtime.xxx.js 的区别:
    vue.js 是完整版的 Vue,蕴含:外围性能 + 模板解析器。
    vue.runtime.xxx.js 是运行版的 Vue,只蕴含:外围性能;没有模板解析器。
  2. 因为 vue.runtime.xxx.js 没有模板解析器,所以不能应用 template 这个配置项,须要应用 render 函数接管到的 createElement 函数去指定具体内容。

vue.config.js 配置文件-p64

  1. 应用 vue inspect > output.js 能够查看到 Vue 脚手架的默认配置。
  2. 应用 vue.config.js 能够对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh

ref 属性-P65

  1. 被用来给元素或子组件注册援用信息(id 的替代者)
  2. 利用在 html 标签上获取的是实在 DOM 元素,利用在组件标签上是组件实例对象(vc)
  3. 应用形式:

    1. 打标识:`<h1 ref="xxx">.....</h1>` 或 `<School ref="xxx"></School>`2. 获取:`this.$refs.xxx`

props 配置项-P66

  1. 性能:让组件接管内部传过来的数据
  2. 传递数据:<Demo name="xxx"/>
  3. 接收数据:

    1. 第一种形式(只接管):props:['name']
    2. 第二种形式(限度类型):props:{name:String}
    3. 第三种形式(限度类型、限度必要性、指定默认值):

      props:{ name:{ type:String, //类型 required:true, //必要性 default:'老王' //默认值 }}

备注:props 是只读的,Vue 底层会监测你对 props 的批改,如果进行了批改,就会收回正告,若业务需要的确须要批改,那么请复制 props 的内容到 data 中一份,而后去批改 data 中的数据。

mixin(混入)-P67

  1. 性能:能够把多个组件共用的配置提取成一个混入对象
  2. 应用形式:

    第一步定义混合:

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

    第二步应用混入:
    全局混入:Vue.mixin(xxx)
    部分混入:mixins:['xxx']

插件-P68

  1. 性能:用于加强 Vue
  2. 实质:蕴含 install 办法的一个对象,install 的第一个参数是 Vue,第二个当前的参数是插件使用者传递的数据。
  3. 定义插件:

    对象.install = function (Vue, options) {    // 1. 增加全局过滤器    Vue.filter(....)    // 2. 增加全局指令    Vue.directive(....)    // 3. 配置全局混入(合)    Vue.mixin(....)    // 4. 增加实例办法    Vue.prototype.$myMethod = function () {...}    Vue.prototype.$myProperty = xxxx}
  4. 应用插件:Vue.use()

scoped 款式-P69

  1. 作用:让款式在部分失效,避免抵触。
  2. 写法:<style scoped>

总结 TodoList 案例-P70

  1. 组件化编码流程:

    (1).拆分动态组件:组件要依照性能点拆分,命名不要与 html 元素抵触。(2).实现动静组件:思考好数据的寄存地位,数据是一个组件在用,还是一些组件在用:1>.一个组件在用:放在组件本身即可。2>. 一些组件在用:放在他们独特的父组件上(状态晋升)。(3).实现交互:从绑定事件开始。
  2. props 实用于:

    1. 父组件 ==> 子组件 通信
    2. 子组件 ==> 父组件 通信(要求父先给子一个函数)
  3. 应用 v-model 时要切记:v-model 绑定的值不能是 props 传过来的值,因为 props 是只读的。
  4. props 传过来的若是对象类型的值,批改对象中的属性时 Vue 不会报错,但不举荐这样做。(因为 props 是浅层校验)

webStorage-P78

  1. 存储内容大小个别反对 5MB 左右(不同浏览器可能还不一样)
  2. 浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制。
  3. 相干 API:

    1. xxxxxStorage.setItem('key', 'value');
      该办法承受一个键和值作为参数,会把键值对增加到存储中,如果键名存在,则更新其对应的值。
    2. xxxxxStorage.getItem('person');
      该办法承受一个键名作为参数,返回键名对应的值。
    3. xxxxxStorage.removeItem('key');
      该办法承受一个键名作为参数,并把该键名从存储中删除。
    4. xxxxxStorage.clear()
      该办法会清空存储中的所有数据。
  4. 备注:

    1. SessionStorage 存储的内容会随着浏览器窗口敞开而隐没。
    2. LocalStorage 存储的内容,须要手动革除才会隐没。
    3. xxxxxStorage.getItem(xxx)如果 xxx 对应的 value 获取不到,那么 getItem 的返回值是 null。
    4. JSON.parse(null)的后果仍然是 null。

???组件的自定义事件-P80

  1. 一种组件间通信的形式,实用于:子组件 ===> 父组件
  2. 应用场景:A 是父组件,B 是子组件,B 想给 A 传数据,那么就要在 A 中给 B 绑定自定义事件(事件的回调在 A 中)。
  3. 绑定自定义事件:

    1. 第一种形式,在父组件中:<Demo @atguigu="test"/><Demo v-on:atguigu="test"/>
    2. 第二种形式,在父组件中:

      <Demo ref="demo"/>......mounted(){   this.$refs.xxx.$on('atguigu',this.test)}
    3. 若想让自定义事件只能触发一次,能够应用once修饰符,或$once办法。
  4. 触发自定义事件:this.$emit('atguigu',数据)
  5. 解绑自定义事件this.$off('atguigu')
  6. 组件上也能够绑定原生 DOM 事件,须要应用native修饰符。
  7. 留神:通过this.$refs.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么配置在 methods 中要么用箭头函数,否则 this 指向会出问题!

全局事件总线(GlobalEventBus)-P84

  1. 一种组件间通信的形式,实用于任意组件间通信
  2. 装置全局事件总线:

    new Vue({ ...... beforeCreate() {  Vue.prototype.$bus = this //装置全局事件总线,$bus就是以后利用的vm },    ......})
  3. 应用事件总线:

    1. 接收数据:A 组件想接收数据,则在 A 组件中给$bus 绑定自定义事件,事件的回调留在 A 组件本身。

      methods(){  demo(data){......}}......mounted() {  this.$bus.$on('xxxx',this.demo)}
    2. 提供数据:this.$bus.$emit('xxxx',数据)
  4. 最好在 beforeDestroy 钩子中,用$off 去解绑以后组件所用到的事件。

音讯订阅与公布(pubsub)-P87

  1. 一种组件间通信的形式,实用于任意组件间通信
  2. 应用步骤:

    1. 装置 pubsub:npm i pubsub-js
    2. 引入: import pubsub from 'pubsub-js'
    3. 接收数据:A 组件想接收数据,则在 A 组件中订阅音讯,订阅的回调留在 A 组件本身。

      methods(){  demo(data){......}}......mounted() {  this.pid = pubsub.subscribe('xxx',this.demo) //订阅音讯}
    4. 提供数据:pubsub.publish('xxx',数据)
    5. 最好在 beforeDestroy 钩子中,用PubSub.unsubscribe(pid)勾销订阅。

nextTick-P90

  1. 什么时候用:当扭转数据后,要基于更新后的新 DOM 进行某些操作时,要在 nextTick 所指定的回调函数中执行。
  2. 语法:this.$nextTick(回调函数)
  3. 作用:在下一次 DOM 更新完结后执行其指定的回调。

Vue 封装的适度与动画-P91

  1. 作用:在插入、更新或移除 DOM 元素时,在适合的时候给元素增加款式类名。
  2. 写法:
1. 筹备好款式:   - 元素进入的款式:     1. v-enter:进入的终点     2. v-enter-active:进入过程中     3. v-enter-to:进入的起点   - 元素来到的款式:     1. v-leave:来到的终点     2. v-leave-active:来到过程中     3. v-leave-to:来到的起点2. 应用`<transition>`包裹要适度的元素,并配置 name 属性:<transition name="hello"> <h1 v-show="isShow">你好啊!</h1></transition>备注:若有多个元素须要适度,则须要应用:`<transition-group>`,且每个元素都要指定`key`值。

vue 脚手架配置代理-P96

发申请有哪些?

  1. xhr,new XHLHttpRequest() xhr.open() xhr.send()
  2. jQuery $.get 封装了 xhr
  3. axios
  4. fetch 有局部兼容性问题

同源策略:如果两个 URL 的 protocol、port、host 都雷同的话,则这两个 URL 是同源。即申请发了,服务器收了,但浏览器拦了

  1. cors,承受申请后,携带非凡响应头
  2. jsonp, 只能解决 get 申请
  3. 代理服务器
    nginx(学习老本较高)
    vue-cli
    如果代理服务器自身有,不会转发申请

办法一:在 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": "" },      },      "/api2": {        // 匹配所有以 '/api2'结尾的申请门路        target: "http://localhost:5001", // 代理指标的根底门路        changeOrigin: true,        pathRewrite: { "^/api2": "" },      },    },  },};

阐明:

  1. 长处:能够配置多个代理,且能够灵便的管制申请是否走代理。
  2. 毛病:配置稍微繁琐,申请资源时必须加前缀。

插槽-P102~104

  1. 作用:让父组件能够向子组件指定地位插入 html 构造,也是一种组件间通信的形式,实用于 父组件 ===> 子组件
  2. 分类:默认插槽、具名插槽、作用域插槽
  3. 应用形式:

    1. 默认插槽:

      父组件中:<Category>           <div>html构造1</div>        </Category>子组件中:<template>  <div>    <!-- 定义插槽 -->    <slot>插槽默认内容...</slot>  </div></template>
    2. 具名插槽:

      父组件中:<Category>   <template slot="center">     <div>html构造1</div>   </template>   <template v-slot:footer>      <div>html构造2</div>   </template></Category>子组件中:<template>  <div>    <!-- 定义插槽 -->    <slot name="center">插槽默认内容...</slot>    <slot name="footer">插槽默认内容...</slot>  </div></template>
    3. 作用域插槽:

      1. 了解:数据在组件的本身,但依据数据生成的构造须要组件的使用者来决定。(games 数据在 Category 组件中,但应用数据所遍历进去的构造由 App 组件决定)
      2. 具体编码:

        父组件中:<Category>   <template scope="scopeData">    <!-- 生成的是ul列表 -->    <ul>     <li v-for="g in scopeData.games" :key="g">{{g}}</li>    </ul>   </template>  </Category><Category>   <template slot-scope="scopeData">    <!-- 生成的是h4题目 -->    <h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>   </template>  </Category>子组件中:<template>  <div>    <slot :games="games"></slot>  </div></template><script>export default {  name: "Category",  props: ["title"],  //数据在子组件本身  data() {    return {      games: ["红色警戒", "穿梭前线", "劲舞团", "超级玛丽"],    };  },};</script>

Vuex-P105

1.概念-P107

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

2.何时应用?

多个组件须要共享数据时

3.搭建 vuex 环境-P108

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

    //引入Vue外围库import Vue from "vue";//引入Vueximport Vuex from "vuex";//利用Vuex插件Vue.use(Vuex);//筹备actions对象——响应组件中用户的动作const actions = {};//筹备mutations对象——批改state中的数据const mutations = {};//筹备state对象——保留具体的数据const state = {};//创立并裸露storeexport default new Vuex.Store({  actions,  mutations,  state,});
  2. main.js中创立 vm 时传入store配置项

    //引入storeimport store from "./store";//创立vmnew Vue({  el: "#app",  render: (h) => h(App),  store,});

4.根本应用-P108~110

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

    //引入Vue外围库import Vue from "vue";//引入Vueximport Vuex from "vuex";//援用VuexVue.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,};//创立并裸露storeexport 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 的应用-P111

  1. 概念:当 state 中的数据须要通过加工后再应用时,能够应用 getters 加工。
  2. store.js中追加getters配置

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

6.四个 map 办法的应用-P112~113

  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)的函数

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

7.模块化+命名空间-P115

  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']),
  4. 开启命名空间后,组件中读取 getters 数据:

    //形式一:本人间接读取this.$store.getters['personAbout/firstPersonName']//形式二:借助mapGetters读取:...mapGetters('countAbout',['bigSum'])
  5. 开启命名空间后,组件中调用 dispatch

    //形式一:本人间接dispatchthis.$store.dispatch('personAbout/addPersonWang',person)//形式二:借助mapActions:...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
  6. 开启命名空间后,组件中调用 commit

    //形式一:本人间接committhis.$store.commit('personAbout/ADD_PERSON',person)//形式二:借助mapMutations:...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),

路由-P117

  1. 了解: 一个路由(route)就是一组映射关系(key - value),多个路由须要路由器(router)进行治理。
  2. 前端路由:key 是门路,value 是组件。

1.根本应用-P118

  1. 装置 vue-router,命令:npm i vue-router
  2. 利用插件:Vue.use(VueRouter)
  3. 编写 router 配置项:
//引入VueRouterimport VueRouter from "vue-router";//创立router实例对象,去治理一组一组的路由规定const router = new VueRouter({  routes: [    {      path: "/about",      component: () => import("../components/About"),    },    {      path: "/home",      component: () => import("../components/Home"),    },  ],});//裸露routerexport default router;
  1. 实现切换高亮款式<router-link active-class="active" to="/about">About</router-link>
  2. 指定展现地位<router-view></router-view>

2.几个留神点-P119

  1. 路由组件通常寄存在views文件夹,个别组件通常寄存在components文件夹。
  2. 通过切换,“暗藏”了的路由组件,默认是被销毁掉的,须要的时候再去挂载。
  3. 每个组件都有本人的$route属性,外面存储着本人的路由信息。
  4. 整个利用只有一个 router,能够通过组件的$router属性获取到。

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

  1. 配置路由规定,应用 children 配置项:

    routes: [  {    path: "/about",    component: About,  },  {    path: "/home",    component: Home,    //通过children配置子级路由    children: [      {        path: "news", //此处肯定不要写:/news        component: News,      },      {        path: "message", //此处肯定不要写:/message        component: Message,      },    ],  },];
  2. 跳转(要写残缺门路):<router-link to="/home/news">News</router-link>

4.路由的 query 参数-P121

  1. 传递参数

    <!-- 跳转并携带query参数,to的字符串写法 --><router-link :to="/home/message/detail?id=666&title=你好">跳转</router-link><!-- 跳转并携带query参数,to的对象写法 --><router-link  :to="{    path: '/home/message/detail',    query: {      id: 666,      title: '你好',    },  }">跳转</router-link>
  2. 接管参数:$route.query.id, $route.query.title;

5.命名路由-P122

  1. 作用:能够简化路由的跳转。
  2. 如何应用
<!-- 1. 给路由命名: -->router 中 children 数组对象的 name 配置项<!--简化前,须要写残缺的门路 --><router-link to="/demo/test/welcome">跳转</router-link><!--简化后,间接通过名字跳转 --><router-link :to="{ name: 'hello' }">跳转</router-link><!--简化写法配合传递query参数 --><router-link  :to="{    name: 'hello',    query: {      id: 666,      title: '你好',    },  }">跳转</router-link>

6.路由的 params 参数-P123

  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的字符串写法 --><router-link :to="/home/message/detail/666/你好">跳转</router-link><!-- 跳转并携带params参数,to的对象写法 --><router-link  :to="{    name: 'xiangqing',    params: {      id: 666,      title: '你好',    },  }">跳转</router-link>

特地留神:路由携带 params 参数时,若应用 to 的对象写法,则不能应用 path 配置项,必须应用 name 配置!

  1. 接管参数:$route.params.id; $route.params.title;

7.路由的 props 配置-P124

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

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

8.<router-link>的 replace 属性-P125

  1. 作用:管制路由跳转时操作浏览器历史记录的模式
  2. 浏览器的历史记录有两种写入形式:别离为pushreplacepush是追加历史记录,replace是替换以后记录。路由跳转时候默认为push
  3. 如何开启replace模式:<router-link replace .......>News</router-link>

9.编程式路由导航-P126

  1. 作用:不借助<router-link>实现路由跳转,让路由跳转更加灵便
  2. 具体编码:

    //$router的两个APIthis.$router.push({  name: "detail",  params: {    id: xxx,    title: xxx,  },});this.$router.replace({  name: "detail",  params: {    id: xxx,    title: xxx,  },});this.$router.forward(); //后退this.$router.back(); //后退this.$router.go(); //可后退也可后退

10.缓存路由组件-P127

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

    <keep-alive include="Detail">     <router-view></router-view></keep-alive>

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

  1. 作用:路由组件所独有的两个钩子,用于捕捉路由组件的激活状态。
  2. 具体名字:
    activated路由组件被激活时触发。
    deactivated路由组件失活时触发。

12.路由守卫-P129~132

  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.路由器的两种工作模式-p133

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

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

    1. 地址洁净,好看。2. 兼容性和 hash 模式相比略差。3. 利用部署上线时须要后端人员反对,解决刷新页面服务端 404 的问题。

动静增加路由