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:\untitled\vueapp01>npm run dev '(启动前端服务)'' Your application is running here: http://localhost:8080'
- 停止项目:Ctrl + C
- 4.在当前项目下安装bootstrap
- C:\untitled\vueapp01>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>