- Section 1 - Getting Started
- Section 2 - Using Vue.js to Interact with the DOM
- 18 - Passing your own arguments with events
- To pass your own argument, just update the function call with the argument in parentheses, and add the parameter to the function definition.
- Example:
- The template would read <button v-on:click="increase(2)">Click me</button>
- The function definition would read "increase: function(step) {"
- To grab the default event argument while also passing your own, refer to the former as '$event' in the function call, and whatever you want (e.g. 'event') in the function definition. It doesn't seem to matter where in the list of parameters the 'event' parameter shows up, but he says that '$event' is the specific name you need to use in the function call.
- 19 - Modifying an event - with event modifiers
- 22 - Using Two-Way Data Binding
- 24 - An Alternative to Computed Properties: Watching for changes
- Use this for asynchronous stuff.
- Section 3 - Using Conditionals and Rendering Lists
- 36 - Using an alternative v-if syntax: If you want to have a v-if apply to multiple elements that are at the same level, and you don't want to wrap them in a div, you can group the elements in a '<template>' tag (which is part of HTML5), which won't show up in the final HTML, and put the v-if on that template tag.
- 40 - Using an alternative v-for syntax: You can do the same thing with v-for as mentioned above for v-if, where you put it on a <template> tag in order to wrap multiple elements.
- 43 - Keeping track of elements when using v-for - He explains that you sometimes want to assign a unique ':key' to the element when doing a v-for so that Vue will track the element itself and not just the position of the element. (I found this hard to understand). Basic takeaway: if you're encountering weird behavior with v-for, be aware that adding a :key may fix the issue.
- Section 5 - Understanding the Vue.js Instance
- General thoughts: I didn't learn much that I didn't already know. I've noted below the key things I thought were useful that I didn't already know.
- 65 - Accessing the Vue instance from outside - You can access certain internals of the Vue instance (like the 'data' variables) from outside that instance by assigning the instance to a variable and then using dot notation. Example: "vm.variable_name".
- 67 - A closer look at $el and $data
- If you look at the Vue object in your console, you'll see that it has ceratin variables, among which are $data, $el, and $refs.
- $el is how Vue.js keeps track of our template / HTML code.
- $data is how Vue.js keeps track of our data. If you want, you can access the variables through this (i.e. vm.$data.variableName rather than vm.variableName).
- If you Vue.js doesn't create its own internal / black-box world. It's normal JavaScript and you can access its internals.
- 68 - Placing $refs and using them on your templates - He introduce 'this.$refs', which is just used to access particular HTML elements. Just be aware that if you use this method to make changes to parts of the DOM controlled by Vue, those changes will be overwritten when Vue rerenders its template. So $refs is much more useful for getting information from the DOM rather than setting it.
- 73 - How Vue.js updates the DOM - He explains how the Virtual DOM is a layer between the Vue instance and the actual DOM which allows Vue to only update those parts of the DOM which have actually changed, rather than changing the DOM every time a variable in Vue is set (because it might get set to the same value).
- 74 - The Vue.js instance lifecycle
- 75 - The Vue.js instance lifecycle in practice
- 76 - Module wrap-up
- 77 - Module resources and useful links
- Section 6 - Moving to a "Real" Development Workflow with Webpack and Vue CLI
- Lecture 79 - Why do we need a Development Server?
- Apparently it's desirable to code in ES6 and have it transpiled to ES5 "so it runs in the browser". I didn't know that.
- Answer to why to use a dev server:
- it allows us to test under more realistic circumstances
- it allows us to serve only a subset of our assets at first
- 80 - What does "Development Workflow" mean?
- A: It's a process by which you transform your files before putting them on the server so that you can benefit from particular special features:
- Compile single-file template - He's going to dive deeper into this, but basically it makes the code smaller and faster.
- Case-insensitive component selectors
- Preprocessors - Examples: Compiling ES6 to ES5, compiling SASS to SCSS
- ...and still other things.
- 81 - Using the Vue CLI to create Projects
- We're not going to use Webpack with Vue-loader, but instead use the Vue CLI.
- To install, use 'npm install -g vue-cli'
- You can then choose from several 'Project Templates'
- 'simple'
- 'webpack-simple' ← This is the one we'll use in the course.
- 'webpack'
- 'browserify / browserify-simple' ← browserify is an alternative to webpack
- 82 - Installing the Vue CLI and Creating a new Project
- Install the latest version of node
- Run 'npm install -g vue-cli'
- Run 'vue init webpack-simple name-of-the-project-folder'
- Enter the created folder and run 'npm install'
- Run 'npm run dev' to run the development server, which will automatically recompile everything and create a server that you can access from your browser.
- 83 - An Overview over the Webpack Template Folder Structure ← This lecture was helpful.
- A 'src' folder is created that contains our source code.
- .babelrc sets up babel, which is a transpiler that lets us run ES6 code and transpile it to ES5.
- index.html is the file that actually gets served.
- He explains the '<script src="/dist/build.js"></script>' line in index.html.
- We're using webpack to combine all of our Vue files and output a 'build.js' file in a generated 'dist' folder.
- You won't see the 'dist' folder in development mode because it's done in-memory.
- package.json lists all of the dependencies
- they're split into production dependencies (under the 'dependencies' key) and development dependencies (under 'devDependencies')
- the vue-loader dependency is what allows us to use single-file templates (.vue files)
- webpack.config.js - This is the file that configures how all the JavaScript should get combined ('built').
- Example tasks: transpiling, setting up the build process
- 84 - Understanding ".vue" Files
- The goal here, the reason for the .vue files, is to be able to split up our Vue code into multiple files and then have them combined into one big bundle to be sent to the client.
- main.js - This is the first file that gets executed.
- It has an 'el' which is the actual mounting point for the app. None of the other Vue files will have an 'el'.
- It has a 'render: h => h(App)' line, where 'App' is a 'compiled template' (eg import App from 'App.vue'), which is a way to specify which template should be rendered in the specified 'el'.
- App.vue - This is the Vue application.
- He explains how 'single file templates' have a 'template' section, a 'script' section, and a 'style' section, they get put into the main.js, which puts the compiled template into the index.html.
- 85 - Understanding the Object in the Vue File
- "The key takeaway here is that this object (created by a .vue file) behaves like a Vue instance."
- 86 - How to Build your App for Production
- Run 'npm run build' - This will create the dist folder, build.js, and minify the code.
- 87 - Module Wrap Up
- For the rest of course he'll use the 'webpack-simple' template and split up the Vue code into .vue files.
- 88 - More about ".vue" Files and the CLI (not really a lecture, just notes)
- The webpack-simple template doesn't support local CSS or Sass files, because no CSS loader is set up.
- 89 - Debugging VueJS Projects
- The two main tools are Chrome DevTools and Vue DevTools.
- Section 7 - An Introduction to Components
- 90 - Module Introduction - "Components are used to swap different parts of the website in and out."
- 91 - An Introduction to Components
- He does a simple demo in JSFiddle.
- Vue.component('desired-name-of-the-html-tag', { Vue component })
- Make sure to use a prefix for the HTML tag name to not interfere with other tags. For example, use your company's name as a prefix.
- Unlike the root Vue instance, the 'data' parameter needs to be a function that returns an object rather than an object itself.
- The reason is that the component kind of extends Vue and its data object would interfere with Vue's.
- 92 - Storing Data in Components with the Data Method ← This was interesting.
- He explains why the 'data' property of a component needs to be a function by doing a simple demo in JSFiddle to show what would happen if it was a regular object instead (the way it is in the root Vue instance).
- He creates an object outside of the Vue component, sets up two components, and has them refer to the same data object. When he clicks a button to change an item in the data within one of the components, it updates that item in both components. So apparently this is the behavior that using a function avoids.
- 93 - Registering Components Locally and Globally
- If you do Vue.component('template-tag', {Vue-looking object}), and you have two different Vue instances, and they each have a 'template-tag' in them, then that component will show up in both Vue instances. This is referred to as a 'globally-registered Vue component'.
- If you wanted to change it so that both Vue instances still have the 'template-tag' but only one of them has the component, you can 'register the component locally'. Basically you assign the '{Vue-looking object}' to a variable instead of passing it to the Vue.component function, and then in the Vue instance definition for the Vue instance that you want to have access to that component, you add a 'components: {'template-tag': componentVariable}' section.
- 94 - The "Root Component" in the App.vue File
- He basically just switches back from the JSFiddle example (in the previous lecture) to his WebStorm IDE to show how the App.vue file is a component. It needs to have its 'data' property be a function. Because it's the root component it's used differently from other components (as described in an earlier lecture, it's mounted with the 'render' Vue property), but it's a component, not a Vue.js instance; the Vue.js instance is created in main.js.
- 95 - Creating a Component
- You can create a component by:
- Creating a new .vue file with the single-file template format (template/script/style).
- Make sure there's one root element in the <template> section.
- In main.js:
- Add a line that says 'import ComponentName from "./path/to/componentname.vue"
- Add a line that says "Vue.component('desired-tag-name', ComponentName)"
- Wherever you want the component to show up, add a '<desired-tag-name></desired-tag-name>'
- 96 - Using Components
- The naming convention for components is CamelCase with the first word capitalized.
- He shows how to do a local import of a component (importing a component into another component).
- He does a v-for using his new component, which seemed like something I hadn't seen before.
- Assignment 6: Time to Practice - Components
- This is a very easy assignment, it's giving you some practice at breaking up a one-Vue-file app into several smaller components.
- 97 - Moving to a Better Folder Structure
- When you start to get a lot of component files, it usually makes sense to start using subdirectories.
- For smaller projects you may just want a 'components' subdirectory.
- For larger projects you may want to have a subdirectory for each of your major 'features' / parts of the app.
- 98 - Alternative Folder Structures ← This is just a short doc introing the structure below.
- 99 - How to Name your Component Tags (Selectors)
- Summary: He goes into a bunch of options (things you can do), but ultimately recommends that you have your components show up as <kabob-case> in your templates and in the form 'template-tag': ComponentObject in the "components" section.
- If you're using single-file templates / components that are being compiled with webpack, you can use camel-case for the actual tag names. If you're not compiling it (i.e. you just have a Vue component in a Flask template), you're restricted to what the DOM allows, and it does not allow case-sensitive tag names.
- If you're using ES6 you can just list the name of the component object in the "components" section without specifying it as a key-value pair, and ES6 will turn it into a key-value pair where the key is set to the same name as the object (so it'll be 'ExampleObject': ExampleObject).
- He has his filenames without prefixes, but then adds prefixes when listing them in the 'components' property. The reason is that the prefix is only to prevent accidental conflicts. When naming the files you don't need to worry about those conflicts, so you can skip the prefix (which should improve readability).
- 100 - Scoping Component Styles
- Add 'scoped' to the 'style' tag in a component to make sure its styles don't become global.
- He tries to explain what the 'Shadow DOM' is but I didn't understand him.
- Vue mimics this Shadow DOM behavior to get the scoped CSS to stay tied to the proper parts of the DOM; it does this by adding custom attributes to those parts of the DOM that have scoped CSS applied to them.
- The scoped CSS styles get put into the head section of the page, and those styles select based on those custom attributes that Vue has added.
- Vue always adds the styles from a component to the header section of the page, even if the styles are empty.
- 101 - Module Wrap Up - He briefly recaps the topics already covered and explains what's next.
- Section 8 - Communicating between Components
- 103 - Module Introduction - He just briefly explains that this section is about communication between components.
- 104 - Communication Problems - He gives a motivating example: a parent component has two child components. He wants to click a button in the parent component and have it change a displayed value in one of the child components.
- 105 - Using Props for Parent => Child Communication - He just gives a simple example of passing a single prop from the parent to the child. In this case it's a 'name' variable which changes some text.
- Example:
Parent component: <template>
<div>
<child-component :exampleProp="exampleVariable"></child-component>
</div>
</template>
import ChildComponent from './components/ChildComponent.vue'
export default {
data: function() {
return {
exampleVariable: "asdf";
}
}
components: {
'child-component': ChildComponent
}
} |
Child component: <template>
<div>
<p>{{ exampleProp }}</p>
</div>
</template>
export default {
props: [
'exampleProp'
]
} |
- 106 - Naming props - Case-sensitive names only work if you're using the single-file template, which is the preferred development method anyway.
- 107 - Using props in the Child Component - You can access the values of props just like any other entry in the 'data' object. You can also modify them, but IIRC Cody said that's not a best-practice. (In Lecture 109 Max explains why: objects and arrays are passed by reference, and so you would end up having the child component making changes to the object which the parent component is also referencing, which could make it harder to reason about what was going on. And if it's not an object or array, then it will change the value in the child component but not the parent component).
- 108 - Validating props - He explains how to specify the allowed type(s) of each prop, whether it is required or not, and what default value it should have, if any.
- To validate props, the 'props' entry in your component's Vue code should be an object (as opposed to a list of strings).
- To specify a single type: propName: Type
- To specify multiple possible types: propName: [Type 1, Type 2]
- The benefit of validation is that it makes debugging easier: you know what the problem is.
- To specify that the prop is required: propName: { type: Type1, required: true }
- To set a default value: propName: { type: String, default: 'example value' }
- If the default value is an object or array, it should be a function which returns the object / array.
- 109 - Using Custom Events for Child => Parent Communication
- Motivating example: he wants a button in the child component that will change the name in the parent component.
- Important Note: If the prop is an object or array, it is being passed by reference, which means that if you're changing it in the child component, it will also change it in the parent component.
- Sending the event: this.$emit('nameOfTheEventInTheParent', dataToPass)
- Receiving the event in the parent: <child-component @nameOfTheEvent="variableToChange = $event">, where $event refers to the data that was passed ('dataToPass'). The variable assignment here is just an example, you could also call a function with the $event data.
- 110 - Understanding Unidirectional Data Flow - Components can only communicate with their parent or children. Sibling components cannot communicate directly with each other.
- 111 - Communicating with Callback Functions - An alternative to emitting an event from a child component to call a function in the parent component is to pass (as a prop) a function from the parent down to the child as a callback function, and then have the child component call that callback function. The function will have a reference to the parent component's 'this' object.
- 112 - Communication between Sibling Components
- There are two or three ways to communicate between sibling components.
- Motivating example: There's a parent component which contains a 'User Details' child component and another 'Edit User' component. We want to edit the user's age in the "Edit" component and have it show up in the 'View User' component.
- The first approach is to have the child component which is changing the value of the variable emit an event to the parent, and then have the parent update its variable, and have that pass down to the other child component.
- The second approach is to use a callback function instead of emitting an event.
- The third approach is an event bus. This is helpful if you have lots of nested components, so for example, if the sibling components aren't direct siblings but are more like 5th-cousins-5-removed.
- 113 - Using an Event Bus for Communication
- In Angular 2 this is known as "Services".
- In your main.js file, write "export const eventBus = new Vue();"
- The name of the variable (e.g. eventBus) doesn't matter.
- Make sure this line of code is before you instantiate the main Vue instance.
- In the component that will be changing the variable:
- Write "import { eventBus } from '../main';"
- The curly-braces is ES6 syntax for importing named exports.
- Write "eventBus.$emit('nameOfTheEvent', infoToPass)"
- In the component which should receive updates about the variable of interest, put an event listener in the 'created()' hook:
- Add a line to import the eventBus.
- In your created() function, add this listener:
- eventBus.$on('nameOfTheEvent', (infoToPass) => { this.variableName = infoToPass.variable })
- Managing state can get very complicated. To make this simpler we can use VueX.
- For simple-to-medium-sized applications you can use the eventBus approach.
- 114 - Centralizing Code in an Event Bus
- An alternative to emitting an event on the eventBus is having the emit happen in a method in the eventBus, and to then have components call that method when they want to change the value of that variable.
- The basic point he wants to make is that if you want to avoid duplicating code across different components which are interacting with state, you may be able to centralize that code in the eventBus and have components call methods on the eventBus instead.
- Assignment 7: Time to Practice - Component Communication - His example video is worth rewatching. He uses an eventBus and doesn't worry about action-at-a-distance. I don't think that's the way Cody would have done it.
- 115 - Wrap Up
- Section 9 - Advanced Component Usage
- 117 - Module Introduction - 'In this module I'm going to introduce some other features of components'
- 118 - Setting up the Module Project
- Motivating example: He has an app with a 'Quote.vue' component which displays a quote. He wants to be able to pass in a quote from a parent component.
- 119 - Passing Content - The Suboptimal Solution
- He shows how to pass a single quote as a prop, then asks: "What if we wanted to pass complicated HTML to the child component instead of just a single string?" That is the problem that 'slots' solves.
- 120 - Passing Content with Slots
- To use a slot you just put a '<slot></slot>' in the child component and then put the HTML you want to pass in the parent component's template between the child component's tags.
- 121 - How Slot Content gets Compiled and Styled
- Scoped styling in the child component will also apply to any HTML that is passed in via a slot.
- Any Vue.js commands (v-if, v-for, {{ }}) that are applied to HTML to be passed to the child will be applied in the parent component before the HTML is passed to the child.
- 122 - Using Multiple Slots (Named Slots)
- If you want to have multiple different slots you need to name them.
- In the child component, add a name="nameOfTheSlot" attribute to each slot.
- In the parent component, add a slot="nameOfTheSlot" attribute to the topmost tag that should be sent to each slot.
- 123 - Default Slots and Slot Defaults
- If you have a named slot and an unnamed slot, any HTML in the parent component that is set to be slotted, but is within a slot that doesn't have a name, will be passed to the unnamed slot. In other words, an unnamed slot is the "default" slot.
- If you put anything between the <slot> tags in the child component, that material will be treated as the "default slot content", and will be displayed if nothing is passed down from the parent for that slot.
- 124 - A Summary on Slots
- He gives an example use-case: suppose you have a slideshow-style page, where each 'slide' has its own HTML, but you want all of the slides to be framed by the same HTML.
- 125 - Switching Multiple Components with Dynamic Components
- If you want to be able to have multiple different components put into a given place, you can put a <component></component> tag there, give it an attribute :is="selectedComponent", and then set the data property "selectedComponent" to the name of whichever component should be put in that spot.
- 126 - Understanding Dynamic Component Behavior
- By default, when you use the <component> tag to switch between components, those components are destroyed as they are swapped out.
- 127 - Keeping Dynamic Components Alive
- To avoid having a component destroyed when it's swapped out, wrap it in <keep-alive></keep-alive> tags.
- 128 - Dynamic Component Lifecycle Hooks
- Instead of referring to the 'destroyed()' and 'created()' hooks for kept-alive components, you can use the 'activated()' and 'deactivated()' hooks.
- Assignment 8: Time to Practice - Slots and Dynamic Components
- This was a very easy exercise, it takes ~5-10 minutes.
- 129 - Wrap Up
- He gives a brief summary: We learned how to use slots and dynamic components.
- Section 10 - Second Course Project - Wonderful Quotes
- 131 - Module Introduction
- What's to be built: A simple app where you can use a textarea to enter a new quote, that gets displayed on the same page. You can display a max of 10 quotes, and you can delete created quotes by clicking on them. A progress bar shows how many quotes you've created.
- 132 - Setting up the Project
- He thinks about how to break up the project into components: a header component, a 'new quote' component, an 'all quotes' component, and a 'single quote' component. I just had everything in one component.
- 133 - Initializing the Application
- He creates 'quotes' and 'maxQuotes' properties in the App.vue file, and he creates a 'components' folder with a 'Quote.vue' file and a 'QuoteGrid.vue' file.
- 134 - Creating the Application Components
- He fleshes out the QuoteGrid and Quote components.
- He sets up the Quote component to have a slot for the actual text of the quote, which will be supplied by the QuoteGrid component. I wouldn't have thought to do it that way.
- He uses a bunch of bootstrap classes that I wasn't aware of.
- 135 - Passing Data with Props and Slots
- He implements the passing of the quote array from App.vue to the QuoteGrid, and then the text of the quote from the array in QuoteGrid to the actual Quote component.
- 136 - Allowing Users to Create Quotes with a NewQuote Component
- He uses a bunch of boostrap styles. I had a lot of trouble trying to get my version to look right.
- He wraps the textarea in <form> tags, which I didn't do.
- He basically just fills out the <template> portion of the component, the 'quote' data property, but doesn't implement the 'createNew()' method.
- 137 - Adding Quotes with Custom Events
- He implements the 'createNew()' method in the 'NewQuote.vue' component.
- He clears the textarea as soon as he emits the 'quoteAdded' event, which seems like it would clear it even if the user has reached the max number of quotes and will need to delete another one before saving this new one.
- He then implements the 'newQuote()' method in App.vue which just pushes the quote onto the array.
- 138 - Adding an Info Box
- He just adds two divs in the App.vue (one nested in the other). The main difficulty here is knowing which Bootstrap classes to use. I only used one div and couldn't figure out how to use Bootstrap to get the text formatted the way he had it formatted (centered with the vertical padding).
- 139 - Allowing for Quote Deletion
- He uses '@click.native' on the <app-quote> component. Apparently the 'native' modifier is needed when putting an @click on a custom component.
- He adds a 'deleteQuote()' method to the QuoteGrid.vue component which emits an event that App.vue listens for, and then implements a 'deleteQuote()' method in App.vue to actually remove the quote from the array.
- 140 - Controlling Quotes with a Progress Bar
- He puts the progress bar and the h3 in a 'Header.vue' component.
- He passes the quoteCount and maxQuotes from App.vue to the Header.vue component.
- He doesn't use a computed property for the percentage for the progress bar; he does it in-line.
- Lecture 141 - Finishing Touches and State Management
- He implements the limit on the number of quotes.
- Section 11 - Handling User Input with Forms
- 143 - Module Introduction
- Overview of the module: how to fetch values from input fields, how to use different form controls like radio buttons and checkboxes, and how to build your own form control from a component.
- 144 - A Basic <input> Form Binding
- Motivating example: A 'File a Complaint' form.
- For a basic text <input> field, just use v-model to bind the input's value to a data property.
- Confusing: He seems to first suggest that v-model will not overwrite human-entered input with other data if it's changed somewhere else, but then he seems to suggest that it will overwrite that input.
- 145 - Grouping Data and Pre-Populating Inputs
- He just points out that you can group your data into a single object and then refer to it using the dot notation in the form (so, 'userData.email').
- He also points out that you can pre-populate the form by setting the data property to some non-empty value.
- 146 - Modifying User Input with Input Modifiers
- v-model.lazy will set the input to not update on every keystroke, but instead only when you click out of the input.
- He suggests this might be useful for validating passwords.
- Other modifiers: '.trim' gets rid of whitespace and '.number' forces the value to convert to a number.
- 147 - Binding <textarea> and Saving Line Breaks
- You use v-model to bind data properties to textareas as well.
- To output linebreaks on a paragraph tag set a style of 'white-space: pre'
- 148 - Using Checkboxes and Saving Data in Arrays
- To handle checkboxes, just add a v-model to each input which refers to an array that will contain the selected boxes, and Vue will do the rest of the work to hook up the checkboxes to the array.
- 149 - Using Radio Buttons
- To handle radio buttons, just add a v-model to each input which refers to a string variable which will contain the selected radio button, and Vue will do the work to hook up the radio buttons to the variable.
- 150 - Handling Dropdowns with <select> and <option>
- To add options to a dropdown dynamically, have an array in your instance which contains the different options, then use a v-for on an <option> tag.
- To have a default value, you can use ':selected="item == 'desiredDefaultValue'"', but the more-typical way to do it is to set the value of the variable which will contain the selected value, which the v-model on the select tag will use to set the default (see next point).
- Use v-model on the 'select' tag, and have a separate string variable which will contain the selected value.
- 151 - What v-model does and How to Create a Custom Control
- All v-model does is combine 1) a v-bind with 2) an @input listener which updates the value.
- So, to create a custom control, we just need to implement those two pieces: the component needs to have a 'value' prop, and it needs to emit an 'input' event.
- 152 - Creating a Custom Control (Input)
- Motivating example: He has a control which is basically like a lightswitch, where you can click on one half or the other to turn it 'on' or 'off', except it's oriented horizontally and has some colors.
- He creates a 'dataSwitched' data property in the parent component, then creates a 'value' prop in his component, then creates a 'switched()' method which emits the 'input' event.
- 153 - Submitting a Form
- He creates a button which has a @click listener.
- He adds a 'prevent' modifier to the click listener so that the HTML element won't immediately submit the form to the server. This way we can first examine the submission on the client-side, and then, if it looks good, we can submit it to the server using our own Vue code.
- He creates a 'Submitted' method which sets a boolean variable which shows the submitted values on the page. So he doesn't actually do any validation or do a POST request.
- Assignment 9: Forms
- This was a pretty easy assignment.
- Things he did that I missed:
- He set the class of the inputs to 'form-control' to get the styling to look nice with Bootstrap.
- He set the 'type' of the submit button to 'submit'.
- When combining the firstName and lastName fields into a single fullName variable, he splits the full name on the space in the middle, which was an edge case that I immediately thought of and which had me feeling confused about how I was supposed to proceed.
- He doesn't use data properties to hold the first and last name in the custom component, which complicates how he checks for changes.
- 154 - Wrap Up - He just lists the things we covered in this module, which you can find easily enough by reading the titles of the lectures.
- Section 12 - Using and Creating Directives
- 156 - Module Introduction
- Directives are the 'v-for', 'v-if' things.
- This module is mainly about how to create your own directive.
- 157 - Understanding Directives
- Directives generally start with 'v-'. Then comes the name of the directive.
- He demos Vue's built-in 'v-text' and 'v-html' directives.
- He demos creating a 'v-color' directive.
- There are two options when creating a directive: a global directive and a local directive.
- Global: In main.js, write "Vue.directive('name', {configuration});"
- 158 - How Directives Work - Hook Functions
- Directives have five hooks.
- bind() - Executed as soon as the directive is attached.
- inserted() - Executed as soon as the element is inserted in the parent node.
- update() - Whenever the component is updated.
- componentUpdated() - Executed once both the component and its children have been updated.
- unbind() - Executed when the directive is removed.
- bind and update are the most-often used.
- 159 - Creating a Simple Directive
- He created a bind() function in the Vue.directive configuration
- He accesses the element's style with "el.style" (I think this is based on Vue's internal representation of each element?)
- "el.style.background = 'green'"
- He then adds "v-highlight" to the element in the component file (.vue file).
- 160 - Passing Values to Custom Directives
- All he does is switch the hard-coded 'green' to "binding.value" and then update the code in the component to say v-highlight="red".
- 161 - Passing Arguments to Custom Directives
- He updates his calling code to say v-highlight:background=etc., and in the directive code he adds a conditional: if (binding.arg == 'background')
- 162 - Modifying a Custom Directive with Modifiers
- Motivating example: He wants to add a '.delayed' modifier
- He accesses the modifier in the directive's code with binding.modifiers['delayed']
- He points out that you can chain modifiers.
- 163 - Custom Directives - A Summary
- He just summarizes the topics of the previous lectures and the next lectures. It's a 28-second lecture.
- 164 - Registering Directives Locally
- Add a 'directives' property to the component's Vue code.
- You can specify the name as a string with kabob-case or without quotes if you use camel-case.
- The value (in the directives' key-value pairs) is the configuration, just like with the global version.
- 165 - Using Multiple Modifiers
- He implements another modifier, which creates a blinking effect. This doesn't really cover any new Vue concepts.
- Lecture 166 - Passing more Complex Values to Directives
- He switches the attribute value in the HTML from a string ('red') to an object ({ mainColor: 'red', secondColor: 'blue', interval: 1000 }).
- He accesses those properties in the directive with binding.value.propertyName, for example binding.value.mainColor.
- Assignment 10: Time to Practice - Directives
- 167 - Wrap Up
- Section 13 - Improving your App with Filters and Mixins
- Section 14 - Adding Animations and Transitions
- 180 - Module Introduction
- Animations help your users understand where in the application they should focus.
- We'll cover how to animate single objects, the transition of two objects, and animating whole lists.
- 181 - Understanding Transitions
- If you want to animate the appearance or removal of a DOM element (like, if you're using v-if or v-show), you can do that with a <transition> tag.
- 182 - Preparing Code to use Transitions
- He sets up a button and a div, where the button makes the div appear or disappear via 'v-if'.
- He then wraps the div in '<transition>' tags.
- He notes that you can only have one element (as a top-level element?) between <transition> tags.
- 183 - Setting Up a Transition
- When doing an animation, Vue attaches classes to the DOM element, and by styling these classes you can alter the animation.
- He points out that these animations depend on v-if and v-show; you can't use some kind of custom Javascript to make the element appear.
- When the condition for 'v-if' or 'v-show' becomes true, it first attaches a class named "*-enter", where * is the name of your transition. After one frame, it attaches a "*-enter-active" class until the animation finishes.
- When removing the element it works the same, except with "*-leave" and "*-leave-active".
- The default class name is "v-enter".
- 184 - Assigning CSS Classes for Transitions
- You can either just mess with the default ".v-enter" class in the "<style>" section of your .vue file, or you can specify a "name" attribute for the transition and then mess with the ".name-enter" class.
- The CSS properties you use are typically the "transition" property or the "animation" property.
- 185 - Creating a "Fade" Transition with the CSS Transition Property
- He adds an "opacity: 0" line to the "fade-enter" class, then with the "fade-enter-active" class he adds a "transition: opacity 1s" line.
- Weirdly, when setting the "fade-leave" class's styling he says you don't need to specify the opacity, and when setting the "fade-leave-active" class's styling he sets both "transition: opacity 1s" and "opacity: 0", which is different from how he did it when styling the enter-classes. He says that '1' is the default value for the 'opacity' property.
- 186 - Creating a "Slide" Transition with the CSS Animation Property
- He introduces a bunch of new concepts
- First he sets up some keyframes with the "@keyframes" CSS setting: "@keyframes slide-in { ... }" and another one for 'slide-out'.
- Both slide-in and slide-out have a "from" and "to" keyframe, for example: "from { transform: translateY(20px) }"
- The class names are set up in the same way as in the previous lecture, but this time he's going to use the "animation" CSS property.
- He doesn't need to put anything in the 'slide-enter' CSS property because the keyframes take care of the starting position.
- In the 'slide-enter-active' class he sets the 'animation' property to 'slide-in 1s ease-out forwards', where 'slide-in' refers to the keyframes he created, 'ease-out' is an available CSS easing function, and 'forwards' prevents the element from snapping back to its starting position after the animation finishes.
- He demos the animation, but it doesn't fade out, it just pops in and out.
- 187 - Mixing Transition and Animation Properties
- The goal here is to both have the sliding effect and also the fading effect.
- He uses both the 'transition' and 'animation' properties in this case but points out that you could achieve the same effect solely through the use of the 'animation' keyframes.
- If you have both a transition and animation and they have different times over which they run, you can specify which one should be 'definitive' by setting the 'type' attribute on the <transition> tag to either 'animation' or 'transition'.
- 188 - Animating v-if and v-show
- This is a 30-second lecture, he just points out that everything he's done so far works with 'v-show' just as it does with 'v-if'.
- 189 - Setting Up an Initial (on-load) Animation
- If you want the animation to play when the page initially loads, add an 'appear' attribute to the <transition> tag.
- The problem is that Attribute.css requires you to add the name of the desired
- 190 - Using Different CSS Class Names
- He introduces the 'Animate.css' library, and adds it to his index.html
- Animate.css works by having you add certain classes to the element you want to animate.
- The problem is that Vue uses the '*-enter' etc. classes to do animations.
- To get Vue to notice the Animate.css classes, you get rid of the 'name' attribute and instead add an 'enter-class' (etc) attribute which is the class or classes you want applied.
- Example: enter-active-class="animated bounce"
- At the time he recorded the video, the 'appear' attribute didn't work with those custom classes.
- 191 - Using Dynamic Names and Attributes
- You can bind the transition type dynamically by adding a colon to the beginning of the 'name' property.
- 192 - Transitioning between Multiple Elements (Theory)
- 30-second lecture to introduce the motivating situation: You have two elements, and you want the first element to play an animation, and when that animation finishes, have the second element play its animation.
- 193 - Transitioning between Multiple Elements (Practice)
- He creates a transition that wraps two divs, where they alternate using v-if and v-else.
- If I understood him correctly, he says that animations between elements won't work with v-show, only v-if.
- On his first attempt the animations don't work, and he says the reason is that if you wrap two divs, the animation-listener-portion of Vue can't tell that the elements swapped, because it just swaps the content of the divs.
- To fix this he adds a 'key="keyName"' to each div.
- Then there's another problem: the incoming div shows up lower on the screen than the outgoing div, rather than being in the same place on the screen, and then jumps up when the outgoing div's animation finishes and it is removed from the DOM.
- To fix this, he adds 'mode="out-in"' to the <transition> tag, which has the outgoing div's animation finish before animating the incoming div.
- He says another way to fix this would be to set the div's position to 'absolute', so they'd overlap each other.
- 194 - Listening to Transition Event Hooks
- He lists the different hooks available: before-enter, enter, after-enter, enter-cancelled, etc.
- 195 - Understanding JavaScript Animations
- He stresses that you can use both the JavaScript hooks and the CSS animations.
- He demos using the JavaScript hooks.
- He starts by adding a button that adds or removes a div that contains a green square.
- He adds the different '@' hook-attributes to the <transition> element.
- If you don't have any CSS animations in your <transition> tag (eg if you're solely using the JavaScript hooks), Vue won't know when the transition ends, and so you need to call a "done()" function in the 'enter()' and 'leave()' functions to let Vue know that the transition has ended (explicitly specifying when the transition ends allows you to have the transition end when some asynchronous call has finished).
- 196 - Excluding CSS from your Animation
- If you add :css="false" to your <transition> tag, that will tell Vue to skip checking for CSS animations and solely use the JavaScript hooks, which can make it run faster.
- 197 - Creating an Animation in JavaScript
- 'enter()' and 'leave()' are the two hooks to use for the actual animation.
- He gives an example of having a div grow in width when you click a button, and shrink in width when you click the button again.
- He uses setInterval to have the changes happen over a period of time.
- 198 - Animating Dynamic Components
- He sets up a situation where clicking a button switches between a "success" message component and a "warning" message component.
- 199 - Animating Lists with <transition-group>
- Very brief video; he just says that '<transition-group>' is used for lists.
- 200 - Using <transition-group> - Preparations
- In this video he just sets up a v-for to display the numbers (1, 2, 3, etc.) in an array, and then 'addItem' and 'deleteItem' methods.
- 201 - Using <transition-group> to Animate a List
- <transition> is not rendered to the DOM, but <transition-group> renders a <span>. You can override this by setting 'tag="TAG"'.
- Otherwise the <transition-group> tag is generally used just like the <transition> tag.
- One difference is that you need to set a dynamic key which will be different for each item, so that Vue can tell which item to animate.
- By default the items will pop in and out and the rest of the items will jump suddenly to make room for a new item or to collapse the area where an item was just removed. To have the other elements slide gradually, you can define a '.slide-move' class and set 'transition: transform 1s'.
- To allow the items below a removed item to slide above it while it's still be removed, you need to set 'position: absolute' in the 'slide-leave-active' class.
- 202 - Understanding the App
- He demos his 'Super Quiz' app, where you need to solve a simple addition or subtraction problem, and when you click the correct answer the list of questions flips over to reveal a message that says 'Correct!'.
- 203 - Creating the App
- Here he explains how he created the 'Super Quiz' app up to (but not including) the point where it has animations.
- 204 - Adding Animations
- Here he explains how he added the animations. This was the only assignment I couldn't figure out. He uses keyframes and a bunch of options that I wasn't familiar with. I had tried Googling the issue but was led down the wrong path by the links I found.
- 205 - Wrap Up
- He just summarizes the topics covered in this module.
- 206 - Module Resources & Useful Links
- 207 - The Animated "Monster Slayer" App
- This is just an attachment.
- Section 15 - Connecting to Servers via Http - Using vue-resource
- 208 - Module Introduction
- In a lot of applications you need to talk to a server between page-serves.
- You often want the retrieve new information via AJAX rather than having to load an entirely new webpage.
- 209 - Accessing Http via vue-resource - Setup
- Since Vue is regular JavaScript, you can use whatever AJAX library you want. For example, you can use JQuery.
- He's going to show a package called 'vue-resource' that adds some nice features when doing AJAX requests.
- You can install vue-resource with 'npm install vue-resource --save'.
- To enable it, add this to your main.js:
- import VueResource from 'vue-resource'
Vue.use(VueResource);
- 210 - Creating an Application and Setting Up a Server (Firebase)
- Firebase is a service that you can use for a mobile or web app.
- Set up Firebase:
- Click 'Create New Project'
- Name the project, click 'Create Project'.
- He's only going to show the 'Database' part of Firebase for this demo.
- Go to Database → Rules, and set the '.read' and '.write' rules to 'true' to allow us to write to the database.
- Set up the Vue project.
- He sets up 'username' and 'email' inputs which use v-model to bind to two data properties, and @click listener on a submit button that runs a 'submit' function.
- 211 - POSTing Data to a Server (Sending a POST Request)
- Sending the request:
- Grab the endpoint in Firebase from Database → Data.
- Since we added Vue.use(VueResource) in the global scope, all of our components now have access to a 'this.$http' object.
- The first argument of 'this.$http.post()' is the endpoint to post to.
- You need to add 'data.json' to the end of the endpoint because Firebase requires it. The 'data' part can be named by you, but Firebase requires that you work with .json.
- Amazingly, you don't actually need to set up anything in Firebase to get that part working; you don't need to create a 'data' thing in Firebase. It'll just take whatever you give it and create an entry.
- The second argument for a POST request is the data that you want to post.
- Working with the response:
- Vue-resource uses a 'promise' approach for requests.
- So you can have 'this.$http.post(...).then(response => { do stuff }, error => { do stuff })
- The response body from Firebase will be an ID to that data.
- If you post multiple times, you'll create multiple different entries, each with their own ID.
- 212 - GETting and Transforming Data (Sending a GET Request)
- He adds a 'Get Data' button.
- He sets up a v-for to display each user in a list of users that he will query from the db.
- He sets up a 'this.$http.get(endpoint).then( response => { do stuff }'
- Vue-resource gives us some useful functions to use to deal with the response: one of them is 'response.json()', which parses the response for us. [What we do in the v2 code is "response.data['itemName']".
- He points out that just accessing response.json() won't work because it returns a promise, so what we actually need to do is:
- this.$http.get(endpoint).then(response => { return response.json() }).then(data => { do stuff }).
- He writes some code to turn the object he gets back from Firebase into a list so that it'll work with the v-for.
- 213 - Configuring vue-resource Globally
- He notes that it would be nice to avoid having to repeat the full URL for every request.
- To do this, he goes to his global main.js and writes:
- He then sets the endpoint to an empty string, but points out that you could add some subroute there and it would be appended to the global value.
- You can also set the headers (like the content-type) via that options object.
- 214 - Intercepting Requests
- To set these up, add 'Vue.http.interceptors.push((request, next) => { do stuff })
- 'next' is a callback function that indicates what should happen after the intercepting function finishes.
- The interceptor he creates changes 'post' requests to 'put' requests.
- At the end of doing stuff he calls 'next()', but never actually specifies what it does.
- He then shows the effect this has in Firebase: 'put' requests overwrite past requests.
- 215 - Intercepting Responses
- To intercept the response, you put a function within the 'next()' call.
- Just as a demo, he overrides the built-in response.json() method:
- response.json = () => { return {messages: response.body} }
- The effect of this is to make his 'v-for' code work again.
- He notes that you can use 'if' statements to only modify the request/response in certain situations.
- 216 - Where the "resource" in vue-resource Comes From ← This was new for me
- 'resources' are a feature that vue-resource makes available which lets you make AJAX requests by calling functions.
- To set this up, he does the following in App.vue:
- He creates an empty 'resources' object as a data property.
- In the created() hook, he writes:
- this.resource = this.$resource('data.json');
- He then comments out his existing 'submit' function and replaces it with:
- this.resource.save({url parameters}, {data you want to post})
- 217 - Creating Custom Resources
- He demos being able to easily switch an endpoint, so that he can switch "this.resource.save({}, this.user)"
to "this.resource.saveAlt(this.user)".
- 218 - Resources vs "Normal" Http Requests
- This is a 30 second video where he just points out that 'normal' http requests are fine, you don't need to use resources all the time, it's just an alternative.
- 219 - Understanding Template URLs
- He shows how to make the endpoint dynamic, where he lets the user specify the endpoint: "{node}.json"
- He shows the docs for the URI Templates standard (which is something independent of Vue), and says that all of the things described there will work.
- He passes the dynamic endpoint to the resource with this syntax:
- this.resource.getData({node: this.node}), where 'this.node' is the endpoint, and 'node' is the variable he used when setting up the resource.
- 220 - Wrap Up
- He just summarizes the topics covered.
- 221 - Module Resources & Useful Links
- Section 16 - Routing in a VueJS Application
- 222 - Module Introduction
- Routing is what makes single-page applications possible(?)
- He explains how a single-page application works: you have a single 'index.html' file which gets loaded at the root URL, and then the URL changes, but the page only loads / rerenders the parts of the screen/page that need to be changed to reflect whatever action the user has taken by clicking that link.
- He reiterates the major difference here: previously we were dealing with individual pages, where different Vue.js instances needed to exist for each page, and now we're having Vue.js handle the entire web app.
- 223 - Setting up the VueJS Router (vue-router)
- He shows the basic structure of the project he has attached which is ready to have routing added to it: it has an index.html with Bootstrap being imported, a bunch of (basically-empty) components that will be switched in and out with the router.
- He then installs the Vue Router package with 'npm install --save vue-router'. He explains that the router is a separate package because some people might want to use Vue without the router.
- 224 - Setting Up and Loading Routes
- In main.js he writes "import VueRouter from 'vue-router';" and then "Vue.use(VueRouter);".
- He says that you can specify your routes in another file and import that file into the main.js file.
- He emphasizes that you need to register all of your routes with the root Vue instance for them to work.
- He creates a separate file for the routes, calls it 'routes.js', and fills it with "export const routes = [ route objects go here ];"
- Each route object has:
- a 'path' attribute which specifies the relative URL which 'triggers' that route.
- a 'component' attribute which is the imported component that should be loaded.
- For the sake of demonstrating switching routes, he adds a second route for a 'Home' component.
- He goes back to main.js and adds a line that imports the routes.js file: "import { routes } from './routes';". He explains that the curly-braces are necessary because he named the object to be exported.
- He then adds a line in main.js: "const router = new VueRouter({ routes });
- He then adds the created router object to the Vue instance by just adding a line which says 'router,'.
- He then explains we need to tell the Vue instance where to load these components that are being loaded via the router. We do this with the <router-view> tag. He adds this tag pair to the App.vue file.
- He points out the hash in the URL, explains that this is the way VueRouter handles routes, and says he'll go into it further in the next video.
- 225 - Understanding Routing Modes (Hash vs History)
- He explains that the hash is used to allow client-side JavaScript to intercept the request.
- He says it would be nicer to not have the hash when creating an SPA, and then explains how to do it: set up your server to always return the index.html file, even when there's a 404. The Vue build.js will then get run, the URL will get parsed, and Vue will take over.
- [Note from NW: Wouldn't this require two back-and-forths between the client and server? And wouldn't returning index.html each time require rerendering everything?]
- 2018.02.16 - In the next video he explains that using the <router-link> tags is how you have the app skip the request to the server.
- To tell VueRouter that this is the desired mode, add a "mode: 'history'" line to your VueRouter configuration.
- 226 - Navigating with Router Links
- He copies some Bootstrap example code for buttons.
- He explains that he doesn't want to use the href="" attribute for the link tags because that would send a request to the server, and it would be better if our app could handle the change without doing that.
- He gets rid of the <a> tags and replaces them with <rounter-link> tags. He explains that the tags will be rendered as <a> tags but will have some special behavior.
- The <router-link> tag determines where it will link to via a 'to' attribute which can either be a relative path (relative to the current URL) or with a leading-forward-slash, which will make the path relative to the domain (and not to the current URL, if the current URL is not the domain).
- He imports the new 'Header.vue' component into the main Vue file and then demonstrates that it all works.
- 227 - Where am I? - Styling Active Links
- He demos a few different features of the <router-link> tag:
- You can set the router-link to any tag that you want. He shows an example where Bootstrap uses <li> with an inner <a>. and shows that router-link can replace the <li> tags and then have empty <a> tags within (to satisfy Bootstrap's CSS selectors?).
- You can specify what the 'link active' class should be.
- He shows an example where Bootstrap is looking for an 'active' class to style certain links, but router-link uses a 'router-link-active' class by default, which won't get noticed by Bootstrap. He's able to switch that active class to 'active' instead.
- You can specify an 'exact' attribute to make sure that a link is only shows as 'active' if that exact URL is present, rather than even if the URL shows up as a base of the current URL.
- 228 - Navigating from Code (Imperative Navigation)
- To navigate the router from your JavaScript code, use this.$router.push(stringRouteToGoTo);
- He didn't need to import anything in his component to make 'this.$router' work. I guess it just automatically works because you attach it to the root Vue instance.
- 'push' refers to pushing the new route onto the stack of visited routes, so that the 'Back' and 'Forward' buttons in the browser work properly.
- push() can also take an object as an argument, he'll explain the benefits of that later.
- 229 - Setting Up Route Parameters
- To pass a dynamic segment in your path (e.g. '10' in '/user/10') you append a colon and add a variable name (e.g. 'user/:id') when setting up your routes.
- This is just how it works in Flask.
- 230 - Fetching and Using Route Parameters
- To access the dynamic parameter (e.g. '10' in 'user/10'), use this.$route.params.variableName
- So in his example it's this.$route.params.id
- Note that it's this.$route, not this.$router.
- 231 - Reacting to Changes in Route Parameters
- If a particular component is loaded and the path changes, but the same component would be loaded in the new path, the component isn't reloaded.
- The example he gives is going from 'user/1' to 'user/2'. He has already assigned an 'id' variable in his data() section to the value of this.$route.params.id, and that assignment only happened the first time the component was loaded.
- The solution is to set up a watcher for the change of these dynamic parameters and update the necessary parts of your components.
- He watches '$route', so $route: function(toRoute, fromRoute) { etc. }
- 232 - vue-router 2.2: Extract Route Params via "props"
- It isn't a video, just a note:
As of vue-router version 2.2, you can also bind your route params to props of the target components. This eliminates the need of watching $route . There are three ways of using this feature, check this official example to learn more: https://github.com/vuejs/vue-router/tree/dev/examples/route-props You can basically either pass a static value, bind a dynamic value to props or use a function to also convert your dynamic value.
- 233 - Setting Up Child Routes (Nested Routes)
- To set up subroutes, add a "children: [ ]" key-value pair to the route configuration.
- Each child route will have the same structure as the parent component (it'll be an object with a 'path' key and a 'component' key).
- You can actually nest routes even if the URLs are different (i.e. even if the child route's URL doesn't contain the parent route's URL).
- Nested routes aren't loaded in the root <router-view> tag, but rather in a <router-view> tag that you'll need to put in the parent component.
- 234 - Navigating to Nested Routes
- He just uses a <router-link> tag that has a "to" attribute that's set to the relative URL of the child component (so in his case, '/users/1', etc.).
- 235 - Making Router Links more Dynamic
- All he does is show that you can switch the static
to attribute to the dynamic :to (with a colon in front), so that he can do :to="'/user' + $route.params.id + '/edit'"
- 236 - A Better Way of Creating Links - With Named Routes
- He shows an alternative way of filling out the
:to field so that you don't need to use string concatenation. Basically you add a key-value pair to the route configuration where the key is name and the value is a string that you want to be the name, and then in the <router-link> you switch the syntax to :to="{ name: 'nameOfTheRoute', params: { id: $route.params.id } }" which is apparently easier. - He does say at some point that this is better when the URL is longer, so that makes sense to me.
- Another advantage I could see of doing it this way is that changing the URLs would seem to be easier.
- He also shows that you can use the same syntax when using
this.$router.push() in your Vue code.- Ex:
this.$router.push({ name: 'home' });
- 237 - Using Query Parameters
- He explains what query parameters are: they're the key-value pairs you see in URLs after the question mark.
- Ex:
www.example.com/login?next=app&something=100
- He then shows how to add query parameters to a router URL using the object syntax for constructing the URL:
:to="{ name: 'userEdit', (...) query: { locale: 'en', q: 100 } }"
- To access the query params, you use
this.$route.query.paramName - He points out that just as with the normal URL parameters, you may need to set up watchers to watch for changes in the query parameters, depending on how your app works.
- 238 - Multiple Router Views (Named Router Views)
- You can use multiple router views within a single component.
- To do this, add a
name='routerViewName' attribute to the router-views, or leave it off of one that you want to serve as the 'default' router-view. - Then in your routes configuration, you'll replace the
component: ComponentName key-value pair with a components: { 'router-view-name': ComponentName } key-value pair. The default router-view uses the special name default . - This seems like it could be useful for Rhymecraft.
- 239 - Redirecting
- To redirect when the user goes to a particular URL, use the following route set-up:
{ path: '/redirect-me', redirect: '/user' } - So basically you're just adding that
redirect key-value pair. - The value for
redirect can also be an object with a name key like we saw earlier.
- 240 - Setting Up "Catch All" Routes / Wildcards
- Set up this route in your configuration.
{ path: '*', redirect: '/' } - So, just use an asterisk.
- 241 - Animating Route Transitions
- To animate route transitions, wrap the
<router-view> tag pair with a <transition> tag pair, and set the options for the transition as the attributes for the opening tag.
- 242 - Passing the Hash Fragment
- To pass a hash fragment (like for an anchor tag), add a
hash key-value pair to the :to link object. - The value for the
hash key must apparently include the hash symbol, strangely enough.- So it's like
hash: '#data'
- At this point the link object is getting long, so he moves it from the template into a
data variable.
- 243 - Controlling the Scroll Behavior
- Go to the
VueRouter initialization and add a scrollBehavior option. - There's a
savedPosition parameter for the scrollBehavior function which saves the position so that if a user clicks the 'Back' button in their browser, you can return them to the place on the page where they were scrolled to.
- 244 - Protecting Routes with Guards
- He explains that sometimes we may want to control if a user can enter a route and whether they should be able to leave the route.
- He doesn't explain how to do it, but instead just sets up the example situation. The next videos explain how to implement it.
- 245 - Using the "beforeEnter" Guard
- There are three ways to check.
- First way: set up a global check.
- In main.js, set up a
router.beforeEach(); method. - Be aware that the
beforeEach function gets executed a lot, so it may affect the performance of your app.
- Second way: in your routes config, add a
beforeEnter key-value pair to the configuration for the particular route you want to run this check for. - Third way: in the actual component you want to do this check for, add a
beforeRouteEnter function. - In all three methods, you must call
next() to allow the user to continue. - In all three methods, you don't have access to the component data because it hasn't been loaded yet.
- This may seem most unintuitive for the third method, since the code is in the component's Vue code where you normally would have access to the component's variables.
- 246 - Using the "beforeLeave" Guard
- There is only one way to check if a user may navigate away from a component, and that is with the
beforeRouteLeave() component method. - In this case you do have access to the component's data, as would be expected.
- This is useful for preventing users from accidentally navigating away if they have unsaved data.
- 247 - Loading Routes Lazily
- He shows how to defer the downloading of code for a particular component (or group of components) until they're accessed.
- Each time you use this special syntax to replace the import statement in your main.js, Webpack will create a separate bundle for just that component.
- You can also group components into a separate bundle.
- 248 - Wrap Up
- 249 - Module Resources & Useful Links
- Section 17 - Better State Management with Vuex
- 250 - Module introduction
- He points out that we've already learned a little about state management with props, emitting events, and using an event bus.
- He says that this new method is good for bigger applications where those previous methods may not be sufficient.
- 251 - Why a different state management may be needed
- He introduces an example application where a grandchild component needs to communicate with its uncle/aunt component.
- The problem with passing data from child to parent is that it's really complicated: you need to pass the data from the granchild to its parent, and then from its parent to its grandparent, and then from the grandparent to the uncle/aunt.
- The problems with using an event bus are that:
- The event bus will quickly get crowded.
- Changes are hard to track.
- 252 - Understanding 'centralized state'
- There is a central store where the application's shared state is stored.
- 253 - Using the centalized state
- A common way to use Vuex is to have a
store/ folderwithin your src directory, at the same level as your components/ folder. - Within the
store folder he creats a store.js file. - He says he links to an article that describes different ways of setting up your file/folder system.
- He does
npm install ---save vuex to install Vuex. - In
store.js he:- imports
Vue and Vuex import Vue from 'vue';
import Vuex from 'vuex';
Sets up Vue to use Vuex.
- He configures the store.
export const store = new Vuex.Store({
state: {
counter: 0
}
});
- In
main.js he then:- Imports the store object.
import { store } from './store/store.js';
- Adds a
store key / value pair to the root Vue instance, like with the router.
- You can now read and write to the store from within a component by accessing
this.$store.state.variableName - He reiterates that the dollar sign in front of the variable is a way for Vue.js to say "this is a special variable created by Vue.js".
- 254 - Why a centralized state alone won't fix it
- He says that the problem is that if you have several active components which each use the same piece of data, and each process that data in the same way, you can end up with computationally-expensive duplication of work.
- 255 - Understanding getters
- He says that "getters" allow us to solve the problem he brought up in the previous video: you can have the data from the central state processed a single time, within the getter, and then accessed in its processed form by multiple components.
- 256 - Using getters
- getters go in the initialization of your Vuex.Store, same with the state.
- Unlike state variables, getters are functions. They're passed the state automatically by Vuex as an argument.
- To access the getter from a component, you use
this.$store.getters.getterName - You don't include the parens at the end, even though it's a function.
- NW: One question I'm left with is, is that getter being rerun for each component? Or is a getter run only once per 'tick' (or whatever you call it when the Vue instance updates).
- NW: After having set up Rhymecraft with Vuex, I've realized that the advantage of having a getter for a state variable is that it lets you use the convenient "mapGetters" function in your components, so that you can write
this.variableName in your components instead of needing to write this.$store.state.variableName everywhere.
- 257 - Mapping getters to properties
- If you're using a bunch of getters in a component, having a different computed property for each one can start to take up a lot of space.
- To shorten the syntax for including them, we can use a helper from Vuex called
mapGetters - In your component, above the
export default { line, you add import {mapGetters} from 'vuex'; - In your computed properties, you then add this:
...mapGetters([ listOfStringsOfGetterNames ]) - The three dots are an ES6 feature which will have the list of functions returned by
mapGetters "unpacked" each as their own entry in the "computed" section.
- 258 - Understanding mutations
- He briefly explains that mutations are like the "setter" equivalent to "getters".
- They're useful if you've got code in multiple components that makes the same kind of change to a particular state variable.
- They're also useful for tracking what component updated a particular shared-state variable.
- 259 - Using mutations
mutations is another key in the Vuex.Store initialization object (same as with state and getters ).- Each getter is a function just like with the getters.
- Example:
mutations: {
increment: state => {
state.counter++;
},
decrement: state => {
state.counter--;
}
} |
- To use the getter from a component, you run
this.$store.commit('mutation-name') - You can do the same kind of short syntax for listing mutations within a component as with the getters, except the helper function is called
mapMutations Example:
<template>
<div>
<p @click="increment"></p>
</div>
</template>
import { mapMutations } from 'vuex';
export default {
methods: {
...mapMutations([
'increment',
'mutation-2-name'
])
}
} |
- 260 - Why mutations have to run synchronously
- You can't run any asynchronous task within a mutation (such as reaching out to a server).
- He says the reason is that the Vuex code isn't set up to be able to both allow asynchronous code within a mutation and also know for sure which mutation caused a particular change in a shared-state variable.
- 261 - How actions improve mutations
- Actions are like mutations in that you use them from components, but with an action you can have asynchronous code (like calls to APIs), and when the action is finished it will commit a mutation.
- NW: You commit a mutation, and you dispatch an action.
- 262 - Using actions
actions is another key in the Vuex.Store initialization object, just as with mutations , state , and getters - Unlike getters and mutations which get a "state" object as an argument from Vuex, actions are passed a "context" object from Vuex.
- The
context object gives you access to features of the store that you will need, such as the commit() method and the getters.- Remember that the ''commit()" method is used specifically to commit mutations. It takes as an argument the name of the mutation, and an optional extra "payload" argument.
- He shows
something which I don't think I'd use often, which is that if a function is passed an object and you only need one property of that object, ES6 allows you to "deconstruct" the passed-in object and only have the property named.- Ex:
increment: ({ commit }) => etc. will take the context object that's passed into the increment() function and just make the commit method available within the function. So you don't have to write context.commit() . - Later: This is actually very helpful for when one action calls another action, because actions can only receive a single additional argument, so if you want to pass multiple things you need to use an object, which makes your action function definition not helpful because it just says you receive a single object instead of what the object has to contain. This feature lets you have the function defintion like this:
exampleFunction: function({ param1, param2 }) { - Later: This is also helpful for decluttering your code if you have a lot of references to state variables.
- He recommends that if you have even a single need for an action, that you commit all of your mutations via dispatching actions, even the synchronous ones, so that you establish a clear pattern. I guess the idea is to prevent bugs?
- Vuex also has a
mapActions helper function, just like mapMutations , to make it easy to list the actions that should be available within a component.
- 263 - Mapping actions to methods
- The way to dispatch an action within a component is
this.$store.dispatch('actionName'); - You can pass an argument to actions if you're using the
mapActions short syntax for including actions.- He says later you can only pass a single argument.
- The normal parameter name for an argument passed to an action is
payload . - Mutations can also have a
payload parameter. - You can't pass multiple arguments to actions / mutations.
- 264 - A summary of Vuex
- He runs through the major ideas he covered in the previous videos.
- 265 - Two-way-binding (v-model) and Vuex
- One way to do two-way binding is to create a method in your component that will call the action to dispatch a change to the variable you want to update the value of.
- This method isn't as nice because it results in a lot of code, and the two halves of the two-way binding are separated (the computed property method and the method to call the action).
- You can actually get v-model to work.
- To do this, you need to use a rarely-used feature of computed properties, which is that you can set a
get() method and a set() method for each computed property. In this case, the get() method would be the normal computed property function, and the set() method would contain the code that you'd normally have in the methods section.
- 266 - Improving folder structures
- He just says he's going to show us how to split up the Vuex initialization code into separate files.
- He says there is at least one alternative set-up, but the way he's going to show us is used in all official examples.
- He creates a
modules/ folder within his store/ folder.
- 267 - Modularizing the state management
- The idea for the
modules/ folder is to organize your state / getters / mutations / actions into groups based on the parts of your application they're used for. - The format for each JavaScript file within the
modules/ folder is:- You have a
const object for each Vuex property (state, getters, mutations, actions), where the format of the object is the same as what it would be in the Vuex initialization object. - At the bottom you add an
export default { } object where the keys are the names of the Vuex properties (state, etc.) and the values are the objects you created above.- He uses the ES6 shortcut of just listing the name once, which I think is confusing but w/e.
- To merge the module into the
stores.js Vuex initialization object, you just add a new modules key where the value is an object that has key-value pairs, where the key is the name of the module within the central store (I guess?) and the value is the actual object that has been imported from the module.- NW: I'm not sure why they're key-value pairs and not a list.
- 268 - Using separate files
- 269 - Using namespaces to avoid naming problems
- 270 - Auto-namespacing with Vuex
- 271 - Wrap-up
- 272 - Module resources and useful links
- Section 18 - Final Project - The Stock Trader
- Section 19 - Deploying a VueJS Application
- 299 - Module Introduction
- Run 'npm run build' to generate the 'build.js' file.
- 300 - Preparing for Deployment
- If you're using one of these Project Templates, everything should be set up to be deployed.
- webpack.config.js
- 'new wepackDefinePlugin' - This will strip out warnings, reducing the filesize and making it more secure.
- 'webpack.optimize.UglifyJsPlugin' - This minifies the javascript.
- 301 - Deploying the App (Example: AWS S3) ← This was a really useful lecture.
- A disclaimer: At the time of recording, AWS offered a free 12-month period which should cover what we're going to do, but make sure that's still true for you and make sure you don't enable anything extra.
- Go to the AWS dashboard.
- Click on 'S3'.
- Click 'Create Bucket'.
- Name it 'vuejs-deploy'.
- Click 'Static Website Hosting'.
- Click 'Enable', then set the Index Document and Error Document to index.html.
- Click 'Save'.
- Click 'Permissions'.
- Click 'Add bucket policy'.
- Google 'aws static webpage' to find the AWS docs, then scroll down and click 'Configure Your Buckets', then scroll down and select the code snippet it shows you.
- Replace 'example.com' with your bucket name.
- Click 'Save'.
- You can choose to enable logging.
- Click on the link to the bucket you created.
- Click 'Upload'.
- Click 'Add Files'.
- Choose the index.html file and then the build.js file.
- Click 'Start Upload'.
- Create a folder named 'dist' and move the build.js folder to that folder.
- Click on the link to your bucket again.
- Click 'Properties'.
- Click on the 'Endpoint' link to be brought to your website.
|