npm(nodejs package manager)、webpack、Vue组件、Vue脚手架开发工具、Vue Router的使用、Vuex的使用、使用Django前后端交互

  • A+
所属分类:Web前端
摘要

在当前项目下生成文件:node_moduels(包含用npm导入的jQuery包等)、package.json、pack-lock.json(包含导入包的信息)


13.8 npm(nodejs package manager)

使用命令行安装包: 1. cd切换到项目目录下,执行初始化操作 npm init/npm init -y 2. 安装其他依赖包 npm install jquery npm install jquery@1.11.13 npm install jquery -g       全局安装 npm install bootstrap@3 -D  开发环境下 marked包安装和使用    npm install marked -D    npm install vuex -D 3. 卸载包     npm uninstall 包名 4. 更新npm    npm install npm@latest  5. npm安装包慢的解决办法:     1.安装cnpm包 :https://npm.taobao.org/     npm install -g cnpm --registry=https://registry.npm.taobao.org     2. 配置npm源为阿里源     npm config set registry https://registry.npm.taobao.org/

在当前项目下生成文件:node_moduels(包含用npm导入的jQuery包等)、package.json、pack-lock.json(包含导入包的信息)

index.html:

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <meta http-equiv="X-UA-Compatible" content="ie=edge">     <title>Document</title> </head> <body>     <script src="./node_modules/jquery/dist/jquery.min.js"></script>     <script>         $.each([11,22,33], function(k,v){             console.log(k,v)         })     </script> </body> </html>

13.9 webpack

为什么要有webpack? 1. JS中不存在模块化的概念 2. 安装和使用 npm install webpack -g          --> 全局安装 npm install webpack-cli -g 3. webpack进阶:https://webpack.js.org/

在当前项目下生成文件:dist(包含main.js,将项目下的依赖关系文件打包保存在main.js文件中)、node_moduels(包含用npm导入的jQuery包等)、package.json、pack-lock.json(包含导入包的信息)

x.js:

var alex = 'sb'; var login = true; module.exports = {alex}

y.js:

var obj = require('./x') var jquery = require('jquery') console.log(obj);   //sb jquery.each([11,22,33,44], function(k,v){     console.log(k,v) })

main.html:

<body> <script src="./dist/main.js"></script> </body>

13.10Vue组件

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body>     <div id="app">         <button-counter></button-counter>         <button-counter></button-counter>         <button-counter></button-counter>         <component-a></component-a>         <ComponentB             //父组件向子组件通信             v-for="a in aList"             v-bind:url="a.url"             v-bind:title="a.title"         ></ComponentB>        <p> 被选了{{num}}次!</p>     <!--子组件向父组件通信-->         <ComponentC             v-for="name in nameList"             v-bind:name="name"             v-on:do="foo"         ></ComponentC>           <table>                 //组件的is属性         <!-- <ComponentB></ComponentB> 此时组件中template中的tr会显示在table外-->           <tr is="ComponentB"></tr>  //此时组件中template中的tr会显示在table中的tbody中         </table>     </div>     <script src="./node_modules/vue/dist/vue.js"></script>  <!--通过npm导入vue.js-->     <script>         //全局注册组件:定义一个名为button-counter的新组件         Vue.component('button-counter', {         /* data: {             count: 0             } */         data: function (){      //data 必须是一个函数,不能直接是对象,组件复用时会影响到其他实例             return {                 count: 0             }         },         template: '<button v-on:click="count++">你点了我 {{ count }} 次。</button>'         })         //局部注册组件:局部注册的组件在其子组件中不可用,如果你希望ComponentB在ComponentA中可用,需声明         const ComponentA = {              components: {                 ComponentB             },             template: `<a href='https://www.sogo.com'>点我</a>`,             data: function(){                 return {                   }             }         }         //父组件向子组件通信         const ComponentB  = {             //template: `<a> <slot></slot></a>`,通过插槽slot分发内容             //template: ` <tr><slot></slot></tr>`,组件的is属性             template: `<p><a v-bind:href='url'>{{title}}</a></p>`,             props: {            //在子组件中使用props声明将url、title传入组件template并显示                 url: String,     //对传值进行校验                 title: {                     type: String,                     required: true                 }             },             data: function(){                 return {                                  }             }         }          //子组件向父组件通信         const ComponentC = {             //子组件可以通过调用内建的 $emit 方法 并传入事件名称来触发一个事件             template: `<button v-on:click='$emit("do")'>{{ name }}</button>`,             props: {        //使用props声明将name传入组件template并显示                 name             },             methods: {                 do(){ ​                 }             }         }         var vm = new Vue({             el: '#app',             components:{        //局部注册组件需要在components中声明                 'component-a': ComponentA,                 ComponentB,                 ComponentC             },              data: {                 num:0,                 nameList: ["技师A", '技师B', '技师C'],                 aList: [                     {                         url: 'https://www.sogo.com',                         title: 'sogo'                     },                     {                         url: 'https://www.luffycity.com',                         title: 'luffycity'                     },                     {                         url: 'http://www.oldboyedu.com/',                         title: 'oldboy edu'                     },                 ]             },             methods: {                 foo(){                     this.num += 1;                 }             }          })     </script> </body> </html>

13.11Vue脚手架开发工具

1. 安装 npm install -g vue-cli 2. 使用 查看安装的vue-cli版本:vue -V 查看帮助:vue --help 查看支持的模板:vue list 3.创建Vue项目 webpack简单模板:vue init webpack-simple app01 webpack模板:(使用Bootstrap时候要用这个):vue init webpack vueapp01     ? Project name vueapp01                     '回车确认'     ? Project description A Vue.js project        '回车确认'     ? Author Lmy <1592187014@qq.com>             '回车确认'     ? Vue build (Use arrow keys)                     ? Vue build (standalone)         > Runtime + Compiler: recommended for most users    '回车确认'         Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specific HTML) are              ONLY allowed in .vue files - render functions are required elsewhere     ? Install vue-router? 'Yes'     ? Use ESLint to lint your code? 'No'     ? Set up unit tests No '(设置单元测试)'     ? Setup e2e tests with Nightwatch?  'No'   '(用夜视器设置e2e测试?)'     ? Should we run `npm install` for you after the project has been created? (recommended) (Use arrow keys)    '(npm)'         > Yes, use NPM    '回车确认'         Yes, use Yarn         No, I will handle that myself     。。。。( vue-cli · Generated "vueapp01".)。。。。(Installing project dependencies ...)。。。。 Project initialization finished!。。。。。。 '''To get started:   cd vueapp01   npm run dev''' C:untitled>cd vueapp01 C:untitledvueapp01>npm run dev '(启动前端服务)'' Your application is running here: http://localhost:8080' 停止项目:Ctrl + C  4.在当前项目下安装bootstrap C:untitledvueapp01>npm install bootstrap@3.3.7 -D  或者  npm install bootstrap@3.3.7 --save-d '安装开发环境下的bootstrap,并将依赖关系写入package.json中'

13.12Vue Router的使用

两个组件(Vue Router内置组件):

<router-link to="/foo">Go to Foo</router-link> #默认渲染成a标签 <router-view></router-view>                  #路由视图,组件显示位置

制作组件路由:

components/Home.vue

<template>     <div>         <h1>这是home页面</h1>   //vue文件中,组件template一定要用div包裹所有标签     </div> </template><script> export default {     name:'Home', } </script><style></style>

components/Note.vue

<template>     <div>         <h1>这是note页面</h1>     </div> </template><script> export default {     name:'Note', } </script><style> </style>

router/index.js

import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import Home from '@/components/Home.vue'  //从组件导入,@代表src import Note from '@/components/Note.vue'  ​ Vue.use(Router) ​ export default new Router({   mode:'history',                       //去掉URL中的'#'   routes: [                             //设置组件路由对应关系     {       path: '/home',       name: '我的home页面',            component: Home     },     {       path: '/note',       name: '我的note页面',       component: Note     }   ] })

Apple.vue:

<li><router-link to="/home">link home版</router-link></li> <li><router-link to="/note">link note版</router-link></li> <router-view></router-view>

<router-link           to="/home"            tag="li"               #指定生成li标签           active-class="active"   #指定标签被点击时的样式         >           <a href="">link home版</a>         </router-link>  <router-link           to="/note"            tag="li"                          active-class="active"            >           <a href="">link note版</a>         </router-link> <router-view></router-view>

<router-link     v-for="(item,index) in allRouters"     v-bind:to="item.path"     tag="li"     active-class="active"         v-bind:key=index         >     <a href="">{{ item.name }}</a> </router-link> <router-view></router-view><script> import 'bootstrap/dist/css/bootstrap.min.css' export default {   name: 'App',   // 计算属性   computed:{     allRouters(){   // 当前Vue实例注册的所有路由       return this.$router.options.routes     }   } } </script>

main.js:

import Vue from 'vue' import App from './App' import router from './router'  //导入路由对象 ​ Vue.config.productionTip = false/* eslint-disable no-new */ new Vue({   el: '#app',   router,           //注册路由对象   components: { App },   template: '<App/>' })

13.13Vuex的使用

store.js:

import Vue from 'vue' import Vuex from 'vuex' ​ Vue.use(Vuex) // 开一家商店 export default new Vuex.Store({     state: {       count:0     },     mutations:{             //提交 mutation来更改 Vuex 的 store 中的状态       increment(state){         state.count+=1       }     }   })

main.js:

import Vue from 'vue' import App from './App' import router from './router' import store from './store' ​ Vue.config.productionTip = false/* eslint-disable no-new */ new Vue({   el: '#app',   router,   //注册路由对象   store,    //向vue实例注册我的商店   components: { App },   template: '<App/>' })

NoteItem.vue:

<template>   <div   class="list-group-item"   v-on:click="foo"   >   {{n}}   </div> </template><script> export default{     name:'NoteItem',     props:{       n:String     },     methods:{                   //v-on监听事件使用method       foo(){                  //子组件被点击时向父组件传值 ,使用$emit()传递事件,告知父组件子组件被点击        // this.$emit('plus')   //使用子组件向父组件传值时使用$emit,使用vuex时注释此项        //this.$store.state.count+=1      //使用vuex,在被点击时修改store中的count        this.$store.commit('increment')  //使用vuex,在被点击时提交事件increme     }     }   } </script><style> </style>

NoteList.vue:

<template>     <div>     <div class="list-group">       <!-- #父组件向子组件传值,将循环数据使用v-bind传给子组件,子使用props接收并使用,后替换NoteItem -->             <NoteItem             v-for="(note,index) in noteList"             v-bind:n='note'             v-bind:key='index'             v-on:plus='p'>  <!-- #子组件向父组件传值,使用v-on监听$emit传递的事件 -->             </NoteItem>             <p>计数器:{{count}}</p>         </div>      </div> </template><script>   import NoteItem from '@/components/NoteItem'   export default {     name:'NoteList',     components:{        NoteItem      },      data:function() {        return {          noteList: [            '第一项','第二项','第三项'          ],          //count:0          //使用子组件向父组件传值时使用data,使用vuex时注释此项        }      },      methods:{     //v-on监听事件使用method        p(){          //console.log(this.count);          this.count+=1      }      },      computed:{         //使用vuex时使用此项,要用return返回        count:function() {          return this.$store.state.count        }      } ​ } </script> <style> </style>

Vue组件之间的通信:

   父组件->子组件:子组件中要使用:props声明我接收的变量

   子组件 -> 父组件:1.子组件 通过this.$emit('事件名') 向父组件抛出事件

           2.父组件 通过v-on:事件名='方法名' 监听子组件的事件从而触发一个修改数据的方法

13.14使用Django前后端交互

1.django做后端,(先导入pip3 install django-cors-headers)在Django的settings文件中配置:

#允许跨域请求的IP(因为vue默认8080端口,Django默认8000端口) #授权白名单 CORS_ORIGIN_WHITELIST=(     'http://localhost:8080',     'http://127.0.0.1:8080' )

views.py:

from app01 import models from django.http import JsonResponse ​ def note_list(request):     ret = {"code": 0}     data = list(models.Note.objects.all().values("id", "title", "content", "markedcontent"))     ret["data"] = data     return JsonResponse(ret) #返回json字符串

2.vue作前端,使用axios发送请求并接受后端的数据(安装:npm install axios)

App.vue:

<script>   import 'bootstrap/dist/css/bootstrap.min.css'   export default {     name: 'App',     data: function () {       return {}     },     // 计算属性     computed: {       // 当前Vue实例注册的所有路由       allRouters() {         return this.$router.options.routes       }     },     beforeMount(){     //在挂载前执行store.js中的playNote函数接受后端数据      this.$store.commit('playNote')     },   } </script>

store.js:将接收到的数据放进商店

import Vue from 'vue' import Vuex from 'vuex' import axios from 'axios'  //导入axios Vue.use(Vuex) ​ export default new Vuex.Store({     state: {       count:0,       notelist:[]     },     mutations:{            addnote_store(state,data){   //捕获NoteEdit传到store的数据用data接收         state.notelist.push(data)       },       playNote(state,data){         //在挂载DOM之前向后端获取数据         axios.get('http://127.0.0.1:8000/api/notes/')  //访问note_list视图函数的路由                .then(function (response) {          //response接收包含json字符串(ret)在内的数据                    //console.log(response.data.data);                    state.notelist=response.data.data  //后端返回到response中的数据(ret)以data命名         })                .catch(function (error) {              //获取后端数据失败打印错误信息                   console.log(error);         });       }     },     actions:{              //方法一:直接将新添加的数据使用 addnote_store添加到 notelist:[]       addnode_post(context,data){    //异步操作store      // 发送 POST 请求        var data=qs.stringify(data) //发送json类型        axios({          method: 'post',          url: 'http://127.0.0.1:8000/api/add/',          data: data,          })          .then(function (response) {            console.log('插入数据');              console.log(response);              context.commit('addnote_store',response.data.data)  // {id: 3, title: "第三条笔记", content: "", markdownContent: ""}               //此处只让后端在数据库中添加数据,不添加到notelist:[]            })          .catch(function (error) {              console.log(error);            })            },     }     })

NoteList.vue:取出商店里的数据,交给template进行渲染

<template>         <div class="list-group">             <NoteItem             v-for="(note,index) in noteList"             v-bind:n='note'             v-bind:key='index'             </NoteItem>         </div> </template><script>   import NoteItem from '@/components/NoteItem'   export default {     name:'NoteList',     components:{        NoteItem      },      data:function() {        }      },      computed:{         //使用vuex时使用此项        count:function() {          return this.$store.state.count        },        noteList:function(){    //使用vuex获得store的数据          return this.$store.state.notelist        }      } } </script>

NoteItem.vue:

<template>   <div   class="list-group-item"   v-on:click="foo"   >   {{n.title}}{{n.content}}   </div> </template><script> export default{     name:'NoteItem',     props:{      //props指定接收父组件传递的数据       n:Object     },     methods:{                 //v-on监听事件使用method       foo(){                  //子组件被点击时向父组件传值 ,使用$emit()传递事件,告知父组件子组件被点击        // this.$emit('plus')   //使用子组件向父组件传值时使用$emit,使用vuex时注释此项        //this.$store.state.count+=1      //使用vuex,在被点击时修改store中的count        this.$store.commit('increment')   //使用vuex,在被点击时提交事件increme     }     }   } </script>